ERP-node/frontend/components/admin/dashboard/widgets/ClockConfigModal.tsx

206 lines
8.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useState } from "react";
import { ClockConfig } from "../types";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Switch } from "@/components/ui/switch";
import { Input } from "@/components/ui/input";
import { Card } from "@/components/ui/card";
import { X } from "lucide-react";
interface ClockConfigModalProps {
config: ClockConfig;
onSave: (config: ClockConfig) => void;
onClose: () => void;
}
/**
* 시계 위젯 설정 모달
* - 스타일 선택 (아날로그/디지털/둘다)
* - 타임존 선택
* - 테마 선택
* - 옵션 토글 (날짜, 초, 24시간)
*/
export function ClockConfigModal({ config, onSave, onClose }: ClockConfigModalProps) {
const [localConfig, setLocalConfig] = useState<ClockConfig>(config);
const handleSave = () => {
onSave(localConfig);
onClose();
};
return (
<Dialog open={true} onOpenChange={onClose}>
<DialogContent className="max-h-[90vh] max-w-2xl overflow-hidden p-0">
<DialogHeader className="border-b p-6">
<DialogTitle className="flex items-center gap-2 text-xl">
<span></span>
</DialogTitle>
</DialogHeader>
{/* 내용 - 스크롤 가능 */}
<div className="flex-1 space-y-6 overflow-y-auto px-6 py-4">
{/* 스타일 선택 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"> </Label>
<div className="grid grid-cols-3 gap-3">
{[
{ value: "digital", label: "디지털", icon: "🔢" },
{ value: "analog", label: "아날로그", icon: "🕐" },
{ value: "both", label: "둘 다", icon: "⏰" },
].map((style) => (
<Button
key={style.value}
type="button"
variant={localConfig.style === style.value ? "default" : "outline"}
onClick={() => setLocalConfig({ ...localConfig, style: style.value as any })}
className="flex h-auto flex-col items-center gap-2 p-4"
>
<span className="text-3xl">{style.icon}</span>
<span className="text-sm font-medium">{style.label}</span>
</Button>
))}
</div>
</div>
{/* 타임존 선택 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"></Label>
<Select
value={localConfig.timezone}
onValueChange={(value) => setLocalConfig({ ...localConfig, timezone: value })}
>
<SelectTrigger className="w-full">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="Asia/Seoul">🇰🇷 (KST)</SelectItem>
<SelectItem value="Asia/Tokyo">🇯🇵 (JST)</SelectItem>
<SelectItem value="Asia/Shanghai">🇨🇳 (CST)</SelectItem>
<SelectItem value="America/New_York">🇺🇸 (EST)</SelectItem>
<SelectItem value="America/Los_Angeles">🇺🇸 LA (PST)</SelectItem>
<SelectItem value="Europe/London">🇬🇧 (GMT)</SelectItem>
<SelectItem value="Europe/Paris">🇫🇷 (CET)</SelectItem>
<SelectItem value="Australia/Sydney">🇦🇺 (AEDT)</SelectItem>
</SelectContent>
</Select>
</div>
{/* 테마 선택 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"></Label>
<div className="grid grid-cols-3 gap-3">
{[
{
value: "light",
label: "Light",
gradient: "bg-gradient-to-br from-white to-gray-100",
text: "text-gray-900",
},
{
value: "dark",
label: "Dark",
gradient: "bg-gradient-to-br from-gray-800 to-gray-900",
text: "text-white",
},
{
value: "custom",
label: "사용자 지정",
gradient: "bg-gradient-to-br from-blue-400 to-purple-600",
text: "text-white",
},
].map((theme) => (
<Button
key={theme.value}
type="button"
variant="outline"
onClick={() => setLocalConfig({ ...localConfig, theme: theme.value as any })}
className={`relative h-auto overflow-hidden p-0 ${
localConfig.theme === theme.value ? "ring-primary ring-2 ring-offset-2" : ""
}`}
>
<div className={`${theme.gradient} ${theme.text} w-full rounded p-3 text-center text-xs font-medium`}>
{theme.label}
</div>
</Button>
))}
</div>
{/* 사용자 지정 색상 선택 */}
{localConfig.theme === "custom" && (
<Card className="border p-4">
<Label className="mb-2 block text-sm font-medium"> </Label>
<div className="flex items-center gap-3">
<Input
type="color"
value={localConfig.customColor || "#3b82f6"}
onChange={(e) => setLocalConfig({ ...localConfig, customColor: e.target.value })}
className="h-12 w-20 cursor-pointer"
/>
<div className="flex-1">
<Input
type="text"
value={localConfig.customColor || "#3b82f6"}
onChange={(e) => setLocalConfig({ ...localConfig, customColor: e.target.value })}
placeholder="#3b82f6"
className="font-mono"
/>
<p className="text-muted-foreground mt-1 text-xs"> </p>
</div>
</div>
</Card>
)}
</div>
{/* 옵션 토글 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"> </Label>
<div className="grid grid-cols-3 gap-3">
{/* 날짜 표시 */}
<Card className="hover:bg-accent flex cursor-pointer flex-col items-center justify-center border p-4 text-center transition-colors">
<span className="mb-2 text-2xl">📅</span>
<Label className="mb-1 cursor-pointer text-sm font-medium"> </Label>
<Switch
checked={localConfig.showDate}
onCheckedChange={(checked) => setLocalConfig({ ...localConfig, showDate: checked })}
/>
</Card>
{/* 초 표시 */}
<Card className="hover:bg-accent flex cursor-pointer flex-col items-center justify-center border p-4 text-center transition-colors">
<span className="mb-2 text-2xl"></span>
<Label className="mb-1 cursor-pointer text-sm font-medium"> </Label>
<Switch
checked={localConfig.showSeconds}
onCheckedChange={(checked) => setLocalConfig({ ...localConfig, showSeconds: checked })}
/>
</Card>
{/* 24시간 형식 */}
<Card className="hover:bg-accent flex cursor-pointer flex-col items-center justify-center border p-4 text-center transition-colors">
<span className="mb-2 text-2xl">🕐</span>
<Label className="mb-1 cursor-pointer text-sm font-medium">24 </Label>
<Switch
checked={localConfig.format24h}
onCheckedChange={(checked) => setLocalConfig({ ...localConfig, format24h: checked })}
/>
</Card>
</div>
</div>
</div>
<DialogFooter className="border-t p-6">
<Button variant="outline" onClick={onClose}>
</Button>
<Button onClick={handleSave}></Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}