Files
ai-showcase-platform/components/admin/system-settings.tsx

877 lines
35 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import React, { useState } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Textarea } from "@/components/ui/textarea"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import {
Settings,
Shield,
Mail,
Server,
Users,
Bell,
Save,
Eye,
EyeOff,
Lock,
TestTube,
CheckCircle,
HardDrive,
Clock,
Database,
RefreshCw,
AlertCircle,
CheckCircle2,
XCircle,
Globe,
} from "lucide-react"
export function SystemSettings() {
const [settings, setSettings] = useState({
// 一般設定
siteName: "AI應用展示平台",
siteDescription: "展示和分享AI應用的專業平台",
timezone: "Asia/Taipei",
language: "zh-TW",
maintenanceMode: false,
// 安全設定
twoFactorAuth: true,
sessionTimeout: 30,
maxLoginAttempts: 5,
passwordMinLength: 8,
// 郵件設定
smtpHost: "smtp.gmail.com",
smtpPort: "587",
smtpUser: "",
smtpPassword: "",
smtpEncryption: "tls",
// 系統性能
cacheEnabled: true,
cacheTimeout: 3600,
maxFileSize: 10,
maxUploadSize: 50,
// 用戶管理
allowRegistration: true,
emailVerification: true,
defaultUserRole: "user",
// 通知設定
systemNotifications: true,
emailNotifications: true,
slackWebhook: "",
notificationFrequency: "immediate",
})
const [activeTab, setActiveTab] = useState("general")
const [saveStatus, setSaveStatus] = useState<"idle" | "saving" | "saved" | "error">("idle")
const [showSmtpPassword, setShowSmtpPassword] = useState(false)
// 資料庫狀態
const [databaseStatus, setDatabaseStatus] = useState<any>(null)
const [isLoadingStatus, setIsLoadingStatus] = useState(false)
const [syncStatus, setSyncStatus] = useState<any>(null)
const [isLoadingSync, setIsLoadingSync] = useState(false)
const handleSave = async () => {
setSaveStatus("saving")
// 模擬保存過程
setTimeout(() => {
setSaveStatus("saved")
setTimeout(() => setSaveStatus("idle"), 2000)
}, 1000)
}
const handleTestEmail = () => {
// 測試郵件功能
alert("測試郵件已發送!")
}
const updateSetting = (key: string, value: any) => {
setSettings((prev) => ({ ...prev, [key]: value }))
}
// 獲取資料庫狀態
const fetchDatabaseStatus = async () => {
setIsLoadingStatus(true)
try {
const response = await fetch('/api/admin/database-status')
const data = await response.json()
if (data.success) {
setDatabaseStatus(data.data)
} else {
console.error('獲取資料庫狀態失敗:', data.error)
}
} catch (error) {
console.error('獲取資料庫狀態失敗:', error)
} finally {
setIsLoadingStatus(false)
}
}
// 切換資料庫
const switchDatabase = async (database: 'master' | 'slave') => {
try {
const response = await fetch('/api/admin/database-status', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ action: 'switch', database }),
})
const data = await response.json()
if (data.success) {
// 重新獲取狀態
await fetchDatabaseStatus()
alert(data.message)
} else {
alert(`切換失敗: ${data.message}`)
}
} catch (error) {
console.error('切換資料庫失敗:', error)
alert('切換資料庫失敗')
}
}
// 獲取同步狀態
const fetchSyncStatus = async () => {
setIsLoadingSync(true)
try {
const response = await fetch('/api/admin/database-sync')
const data = await response.json()
if (data.success) {
setSyncStatus(data.data)
} else {
console.error('獲取同步狀態失敗:', data.error)
}
} catch (error) {
console.error('獲取同步狀態失敗:', error)
} finally {
setIsLoadingSync(false)
}
}
// 同步表資料
const syncTable = async (tableName: string) => {
try {
const response = await fetch('/api/admin/database-sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'sync_table',
tableName: tableName
})
})
const data = await response.json()
if (data.success) {
alert(`成功同步表 ${tableName} 到備機`)
} else {
alert(`同步表 ${tableName} 失敗: ${data.message}`)
}
} catch (error) {
console.error('同步表失敗:', error)
alert('同步表失敗')
}
}
// 組件載入時獲取資料庫狀態
React.useEffect(() => {
if (activeTab === 'performance') {
fetchDatabaseStatus()
fetchSyncStatus()
}
}, [activeTab])
return (
<div className="p-6 max-w-6xl mx-auto">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-3">
<Settings className="w-8 h-8 text-blue-600" />
<div>
<h1 className="text-3xl font-bold"></h1>
<p className="text-muted-foreground"></p>
</div>
</div>
<Button onClick={handleSave} disabled={saveStatus === "saving"}>
<Save className="w-4 h-4 mr-2" />
{saveStatus === "saving" ? "保存中..." : saveStatus === "saved" ? "已保存" : "保存設定"}
</Button>
</div>
<Tabs value={activeTab} onValueChange={setActiveTab} className="space-y-6">
<TabsList className="grid w-full grid-cols-6">
<TabsTrigger value="general" className="flex items-center gap-2">
<Globe className="w-4 h-4" />
</TabsTrigger>
<TabsTrigger value="security" className="flex items-center gap-2">
<Shield className="w-4 h-4" />
</TabsTrigger>
<TabsTrigger value="email" className="flex items-center gap-2">
<Mail className="w-4 h-4" />
</TabsTrigger>
<TabsTrigger value="performance" className="flex items-center gap-2">
<Server className="w-4 h-4" />
</TabsTrigger>
<TabsTrigger value="users" className="flex items-center gap-2">
<Users className="w-4 h-4" />
</TabsTrigger>
<TabsTrigger value="notifications" className="flex items-center gap-2">
<Bell className="w-4 h-4" />
</TabsTrigger>
</TabsList>
{/* 一般設定 */}
<TabsContent value="general" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Globe className="w-5 h-5" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="siteName"></Label>
<Input
id="siteName"
value={settings.siteName}
onChange={(e) => updateSetting("siteName", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="timezone"></Label>
<Select value={settings.timezone} onValueChange={(value) => updateSetting("timezone", value)}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="Asia/Taipei"> (UTC+8)</SelectItem>
<SelectItem value="Asia/Tokyo"> (UTC+9)</SelectItem>
<SelectItem value="UTC">UTC (UTC+0)</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="siteDescription"></Label>
<Textarea
id="siteDescription"
value={settings.siteDescription}
onChange={(e) => updateSetting("siteDescription", e.target.value)}
rows={3}
/>
</div>
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
checked={settings.maintenanceMode}
onCheckedChange={(checked) => updateSetting("maintenanceMode", checked)}
/>
</div>
</CardContent>
</Card>
</TabsContent>
{/* 安全設定 */}
<TabsContent value="security" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Shield className="w-5 h-5" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<div className="flex items-center gap-2">
<Badge variant={settings.twoFactorAuth ? "default" : "secondary"}>
{settings.twoFactorAuth ? "已啟用" : "已停用"}
</Badge>
<Switch
checked={settings.twoFactorAuth}
onCheckedChange={(checked) => updateSetting("twoFactorAuth", checked)}
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="sessionTimeout"> ()</Label>
<Input
id="sessionTimeout"
type="number"
value={settings.sessionTimeout}
onChange={(e) => updateSetting("sessionTimeout", Number.parseInt(e.target.value))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="maxLoginAttempts"></Label>
<Input
id="maxLoginAttempts"
type="number"
value={settings.maxLoginAttempts}
onChange={(e) => updateSetting("maxLoginAttempts", Number.parseInt(e.target.value))}
/>
</div>
</div>
<div className="p-4 bg-green-50 border border-green-200 rounded-lg">
<div className="flex items-center gap-2 text-green-800">
<CheckCircle className="w-5 h-5" />
<span className="font-medium"></span>
</div>
<p className="text-sm text-green-700 mt-1"></p>
</div>
</CardContent>
</Card>
</TabsContent>
{/* 郵件設定 */}
<TabsContent value="email" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Mail className="w-5 h-5" />
SMTP
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="smtpHost">SMTP </Label>
<Input
id="smtpHost"
value={settings.smtpHost}
onChange={(e) => updateSetting("smtpHost", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="smtpPort">SMTP </Label>
<Input
id="smtpPort"
value={settings.smtpPort}
onChange={(e) => updateSetting("smtpPort", e.target.value)}
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="smtpUser">SMTP </Label>
<Input
id="smtpUser"
value={settings.smtpUser}
onChange={(e) => updateSetting("smtpUser", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="smtpPassword">SMTP </Label>
<div className="relative">
<Lock className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
<Input
id="smtpPassword"
type={showSmtpPassword ? "text" : "password"}
value={settings.smtpPassword}
onChange={(e) => updateSetting("smtpPassword", e.target.value)}
className="pl-10 pr-10"
/>
<button
type="button"
onClick={() => setShowSmtpPassword(!showSmtpPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
{showSmtpPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
</button>
</div>
</div>
</div>
<div className="flex items-center gap-4">
<Button onClick={handleTestEmail} variant="outline">
<TestTube className="w-4 h-4 mr-2" />
</Button>
<Badge variant="outline" className="text-green-600 border-green-600">
<CheckCircle className="w-3 h-3 mr-1" />
</Badge>
</div>
</CardContent>
</Card>
</TabsContent>
{/* 系統性能 */}
<TabsContent value="performance" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Server className="w-5 h-5" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
checked={settings.cacheEnabled}
onCheckedChange={(checked) => updateSetting("cacheEnabled", checked)}
/>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="maxFileSize"> (MB)</Label>
<Input
id="maxFileSize"
type="number"
value={settings.maxFileSize}
onChange={(e) => updateSetting("maxFileSize", Number.parseInt(e.target.value))}
/>
</div>
<div className="space-y-2">
<Label htmlFor="maxUploadSize"> (MB)</Label>
<Input
id="maxUploadSize"
type="number"
value={settings.maxUploadSize}
onChange={(e) => updateSetting("maxUploadSize", Number.parseInt(e.target.value))}
/>
</div>
</div>
<div className="p-4 bg-blue-50 border border-blue-200 rounded-lg">
<div className="flex items-center gap-2 text-blue-800 mb-2">
<HardDrive className="w-5 h-5" />
<span className="font-medium">使</span>
</div>
<div className="space-y-2">
<div className="flex justify-between text-sm">
<span>使</span>
<span>2.3 GB / 10 GB</span>
</div>
<div className="w-full bg-blue-200 rounded-full h-2">
<div className="bg-blue-600 h-2 rounded-full" style={{ width: "23%" }}></div>
</div>
</div>
</div>
</CardContent>
</Card>
{/* 資料庫狀態監控 */}
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle className="flex items-center gap-2">
<Database className="w-5 h-5" />
</CardTitle>
<Button
variant="outline"
size="sm"
onClick={fetchDatabaseStatus}
disabled={isLoadingStatus}
>
<RefreshCw className={`w-4 h-4 mr-2 ${isLoadingStatus ? 'animate-spin' : ''}`} />
</Button>
</div>
</CardHeader>
<CardContent className="space-y-4">
{databaseStatus ? (
<>
{/* 備援狀態概覽 */}
<div className="p-4 bg-gray-50 border rounded-lg">
<div className="flex items-center justify-between mb-2">
<span className="font-medium"></span>
<Badge variant={databaseStatus.isEnabled ? "default" : "secondary"}>
{databaseStatus.isEnabled ? "已啟用" : "已停用"}
</Badge>
</div>
<div className="text-sm text-muted-foreground">
使: {databaseStatus.currentDatabase === 'master' ? '主機' : '備機'} |
: {databaseStatus.consecutiveFailures}
</div>
<div className="text-xs text-muted-foreground mt-1">
: {new Date(databaseStatus.lastHealthCheck).toLocaleString()}
</div>
</div>
{/* 主機資料庫 */}
<div className="p-4 border rounded-lg">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<Server className="w-5 h-5" />
<span className="font-medium"></span>
{databaseStatus.currentDatabase === 'master' && (
<Badge variant="default" className="bg-green-100 text-green-800">
使
</Badge>
)}
</div>
<div className="flex items-center gap-2">
{databaseStatus.masterHealthy ? (
<CheckCircle2 className="w-5 h-5 text-green-500" />
) : (
<XCircle className="w-5 h-5 text-red-500" />
)}
<Badge variant={databaseStatus.masterHealthy ? "default" : "destructive"}>
{databaseStatus.masterHealthy ? '正常' : '故障'}
</Badge>
</div>
</div>
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<span className="text-muted-foreground">:</span>
<span className="ml-2 font-mono">mysql.theaken.com:33306</span>
</div>
<div>
<span className="text-muted-foreground">:</span>
<span className="ml-2 font-mono">db_AI_Platform</span>
</div>
</div>
{databaseStatus.currentDatabase !== 'master' && databaseStatus.masterHealthy && (
<Button
size="sm"
className="mt-3"
onClick={() => switchDatabase('master')}
>
</Button>
)}
</div>
{/* 備機資料庫 */}
<div className="p-4 border rounded-lg">
<div className="flex items-center justify-between mb-3">
<div className="flex items-center gap-2">
<Database className="w-5 h-5" />
<span className="font-medium"></span>
{databaseStatus.currentDatabase === 'slave' && (
<Badge variant="default" className="bg-blue-100 text-blue-800">
使
</Badge>
)}
</div>
<div className="flex items-center gap-2">
{databaseStatus.slaveHealthy ? (
<CheckCircle2 className="w-5 h-5 text-green-500" />
) : (
<XCircle className="w-5 h-5 text-red-500" />
)}
<Badge variant={databaseStatus.slaveHealthy ? "default" : "destructive"}>
{databaseStatus.slaveHealthy ? '正常' : '故障'}
</Badge>
</div>
</div>
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<span className="text-muted-foreground">:</span>
<span className="ml-2 font-mono">122.100.99.161:43306</span>
</div>
<div>
<span className="text-muted-foreground">:</span>
<span className="ml-2 font-mono">db_AI_Platform</span>
</div>
</div>
{databaseStatus.currentDatabase !== 'slave' && databaseStatus.slaveHealthy && (
<Button
size="sm"
className="mt-3"
onClick={() => switchDatabase('slave')}
>
</Button>
)}
</div>
{/* 狀態說明 */}
<div className="p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
<div className="flex items-start gap-2">
<AlertCircle className="w-4 h-4 text-yellow-600 mt-0.5" />
<div className="text-sm text-yellow-800">
<p className="font-medium">:</p>
<ul className="mt-1 space-y-1 text-xs">
<li> </li>
<li> </li>
<li> </li>
</ul>
</div>
</div>
</div>
</>
) : (
<div className="p-8 text-center">
<Database className="w-12 h-12 mx-auto text-muted-foreground mb-4" />
<p className="text-muted-foreground">
{isLoadingStatus ? '載入資料庫狀態中...' : '點擊重新整理按鈕載入資料庫狀態'}
</p>
</div>
)}
</CardContent>
</Card>
{/* 資料庫同步管理 */}
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle className="flex items-center gap-2">
<Database className="w-5 h-5" />
</CardTitle>
<Button
variant="outline"
size="sm"
onClick={fetchSyncStatus}
disabled={isLoadingSync}
>
<RefreshCw className={`w-4 h-4 mr-2 ${isLoadingSync ? 'animate-spin' : ''}`} />
</Button>
</div>
</CardHeader>
<CardContent className="space-y-4">
{syncStatus ? (
<>
{/* 同步狀態概覽 */}
<div className="p-4 bg-gray-50 border rounded-lg">
<div className="flex items-center justify-between mb-2">
<span className="font-medium"></span>
<Badge variant={syncStatus.enabled ? "default" : "secondary"}>
{syncStatus.enabled ? "已啟用" : "未啟用"}
</Badge>
</div>
<div className="text-sm text-gray-600">
<p>: {syncStatus.masterHealthy ? "正常" : "異常"}</p>
<p>: {syncStatus.slaveHealthy ? "正常" : "異常"}</p>
{syncStatus.lastSyncTime && (
<p>: {new Date(syncStatus.lastSyncTime).toLocaleString()}</p>
)}
</div>
</div>
{/* 手動同步操作 */}
<div className="space-y-3">
<h4 className="font-medium"></h4>
<div className="grid grid-cols-2 gap-2">
{['users', 'apps', 'teams', 'competitions', 'proposals', 'activity_logs'].map((tableName) => (
<Button
key={tableName}
variant="outline"
size="sm"
onClick={() => syncTable(tableName)}
className="justify-start"
>
<Database className="w-4 h-4 mr-2" />
{tableName}
</Button>
))}
</div>
</div>
{/* 同步說明 */}
<div className="p-3 bg-blue-50 border border-blue-200 rounded-lg">
<div className="flex items-start gap-2">
<AlertCircle className="w-4 h-4 text-blue-600 mt-0.5" />
<div className="text-sm text-blue-800">
<p className="font-medium">:</p>
<ul className="mt-1 space-y-1 text-xs">
<li> </li>
<li> </li>
<li> </li>
</ul>
</div>
</div>
</div>
</>
) : (
<div className="p-8 text-center">
<Database className="w-12 h-12 mx-auto text-muted-foreground mb-4" />
<p className="text-muted-foreground">
{isLoadingSync ? '載入同步狀態中...' : '點擊重新整理按鈕載入同步狀態'}
</p>
</div>
)}
</CardContent>
</Card>
</TabsContent>
{/* 用戶管理 */}
<TabsContent value="users" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Users className="w-5 h-5" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
checked={settings.allowRegistration}
onCheckedChange={(checked) => updateSetting("allowRegistration", checked)}
/>
</div>
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground">使</p>
</div>
<Switch
checked={settings.emailVerification}
onCheckedChange={(checked) => updateSetting("emailVerification", checked)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="defaultUserRole"></Label>
<Select
value={settings.defaultUserRole}
onValueChange={(value) => updateSetting("defaultUserRole", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="user"></SelectItem>
<SelectItem value="contributor"></SelectItem>
<SelectItem value="moderator"></SelectItem>
</SelectContent>
</Select>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 p-4 bg-gray-50 rounded-lg">
<div className="text-center">
<div className="text-2xl font-bold text-blue-600">2,847</div>
<p className="text-sm text-muted-foreground"></p>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-green-600">356</div>
<p className="text-sm text-muted-foreground"></p>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-purple-600">23</div>
<p className="text-sm text-muted-foreground"></p>
</div>
</div>
</CardContent>
</Card>
</TabsContent>
{/* 通知設定 */}
<TabsContent value="notifications" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Bell className="w-5 h-5" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
checked={settings.systemNotifications}
onCheckedChange={(checked) => updateSetting("systemNotifications", checked)}
/>
</div>
<div className="flex items-center justify-between p-4 border rounded-lg">
<div className="space-y-1">
<Label></Label>
<p className="text-sm text-muted-foreground"></p>
</div>
<Switch
checked={settings.emailNotifications}
onCheckedChange={(checked) => updateSetting("emailNotifications", checked)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="slackWebhook">Slack Webhook URL</Label>
<Input
id="slackWebhook"
placeholder="https://hooks.slack.com/services/..."
value={settings.slackWebhook}
onChange={(e) => updateSetting("slackWebhook", e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="notificationFrequency"></Label>
<Select
value={settings.notificationFrequency}
onValueChange={(value) => updateSetting("notificationFrequency", value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="immediate"></SelectItem>
<SelectItem value="hourly"></SelectItem>
<SelectItem value="daily"></SelectItem>
<SelectItem value="weekly"></SelectItem>
</SelectContent>
</Select>
</div>
<div className="p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
<div className="flex items-center gap-2 text-yellow-800 mb-2">
<Clock className="w-5 h-5" />
<span className="font-medium"></span>
</div>
<p className="text-sm text-yellow-700">24 12 </p>
</div>
</CardContent>
</Card>
</TabsContent>
</Tabs>
{saveStatus === "saved" && (
<div className="fixed bottom-4 right-4 bg-green-600 text-white px-4 py-2 rounded-lg shadow-lg flex items-center gap-2">
<CheckCircle className="w-4 h-4" />
</div>
)}
</div>
)
}