213 lines
7.9 KiB
TypeScript
213 lines
7.9 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { ClockConfig } from "../types";
|
||
import { Button } from "@/components/ui/button";
|
||
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 { Separator } from "@/components/ui/separator";
|
||
|
||
interface ClockSettingsProps {
|
||
config: ClockConfig;
|
||
onSave: (config: ClockConfig) => void;
|
||
onClose: () => void;
|
||
}
|
||
|
||
/**
|
||
* 시계 위젯 설정 UI (Popover 내부용)
|
||
* - 모달 없이 순수 설정 폼만 제공
|
||
*/
|
||
export function ClockSettings({ config, onSave, onClose }: ClockSettingsProps) {
|
||
const [localConfig, setLocalConfig] = useState<ClockConfig>(config);
|
||
|
||
const handleSave = () => {
|
||
onSave(localConfig);
|
||
};
|
||
|
||
return (
|
||
<div className="flex max-h-[600px] flex-col">
|
||
{/* 헤더 */}
|
||
<div className="border-b p-4">
|
||
<h3 className="flex items-center gap-2 text-lg font-semibold">
|
||
<span>⏰</span>
|
||
시계 설정
|
||
</h3>
|
||
</div>
|
||
|
||
{/* 내용 - 스크롤 가능 */}
|
||
<div className="flex-1 space-y-4 overflow-y-auto p-4">
|
||
{/* 스타일 선택 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-sm font-semibold">시계 스타일</Label>
|
||
<div className="grid grid-cols-3 gap-2">
|
||
{[
|
||
{ value: "digital", label: "디지털" },
|
||
{ value: "analog", label: "아날로그" },
|
||
{ value: "both", label: "둘 다" },
|
||
].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-1 py-3"
|
||
size="sm"
|
||
>
|
||
<span className="text-xs">{style.label}</span>
|
||
</Button>
|
||
))}
|
||
</div>
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 타임존 선택 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-sm font-semibold">타임존</Label>
|
||
<Select
|
||
value={localConfig.timezone}
|
||
onValueChange={(value) => setLocalConfig({ ...localConfig, timezone: value })}
|
||
>
|
||
<SelectTrigger className="w-full" size="sm">
|
||
<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>
|
||
|
||
<Separator />
|
||
|
||
{/* 테마 선택 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-sm font-semibold">테마</Label>
|
||
<div className="grid grid-cols-3 gap-2">
|
||
{[
|
||
{
|
||
value: "light",
|
||
label: "Light",
|
||
gradient: "bg-gradient-to-br from-background to-muted",
|
||
text: "text-foreground",
|
||
},
|
||
{
|
||
value: "dark",
|
||
label: "Dark",
|
||
gradient: "bg-gradient-to-br from-foreground to-foreground",
|
||
text: "text-background",
|
||
},
|
||
{
|
||
value: "custom",
|
||
label: "사용자",
|
||
gradient: "bg-gradient-to-br from-primary to-primary/80",
|
||
text: "text-primary-foreground",
|
||
},
|
||
].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" : ""
|
||
}`}
|
||
size="sm"
|
||
>
|
||
<div className={`${theme.gradient} ${theme.text} w-full rounded px-3 py-2 text-xs font-medium`}>
|
||
{theme.label}
|
||
</div>
|
||
</Button>
|
||
))}
|
||
</div>
|
||
|
||
{/* 사용자 지정 색상 */}
|
||
{localConfig.theme === "custom" && (
|
||
<Card className="mt-2 border p-3">
|
||
<Label className="mb-2 block text-xs font-medium">배경 색상</Label>
|
||
<div className="flex items-center gap-2">
|
||
<Input
|
||
type="color"
|
||
value={localConfig.customColor || "#3b82f6"}
|
||
onChange={(e) => setLocalConfig({ ...localConfig, customColor: e.target.value })}
|
||
className="h-10 w-16 cursor-pointer"
|
||
/>
|
||
<Input
|
||
type="text"
|
||
value={localConfig.customColor || "#3b82f6"}
|
||
onChange={(e) => setLocalConfig({ ...localConfig, customColor: e.target.value })}
|
||
placeholder="#3b82f6"
|
||
className="flex-1 font-mono text-xs"
|
||
/>
|
||
</div>
|
||
</Card>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
{/* 옵션 토글 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-sm font-semibold">표시 옵션</Label>
|
||
<div className="space-y-2">
|
||
{/* 날짜 표시 */}
|
||
<div className="flex items-center justify-between rounded-lg border p-3">
|
||
<div className="flex items-center gap-2">
|
||
<span className="text-lg">📅</span>
|
||
<Label className="cursor-pointer text-sm">날짜 표시</Label>
|
||
</div>
|
||
<Switch
|
||
checked={localConfig.showDate}
|
||
onCheckedChange={(checked) => setLocalConfig({ ...localConfig, showDate: checked })}
|
||
/>
|
||
</div>
|
||
|
||
{/* 초 표시 */}
|
||
<div className="flex items-center justify-between rounded-lg border p-3">
|
||
<div className="flex items-center gap-2">
|
||
<span className="text-lg">⏱️</span>
|
||
<Label className="cursor-pointer text-sm">초 표시</Label>
|
||
</div>
|
||
<Switch
|
||
checked={localConfig.showSeconds}
|
||
onCheckedChange={(checked) => setLocalConfig({ ...localConfig, showSeconds: checked })}
|
||
/>
|
||
</div>
|
||
|
||
{/* 24시간 형식 */}
|
||
<div className="flex items-center justify-between rounded-lg border p-3">
|
||
<div className="flex items-center gap-2">
|
||
<span className="text-lg">🕐</span>
|
||
<Label className="cursor-pointer text-sm">24시간 형식</Label>
|
||
</div>
|
||
<Switch
|
||
checked={localConfig.format24h}
|
||
onCheckedChange={(checked) => setLocalConfig({ ...localConfig, format24h: checked })}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 푸터 */}
|
||
<div className="flex justify-end gap-2 border-t p-4">
|
||
<Button variant="outline" size="sm" onClick={onClose}>
|
||
취소
|
||
</Button>
|
||
<Button size="sm" onClick={handleSave}>
|
||
저장
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|