기사 관리 위젯 구현

This commit is contained in:
dohyeons
2025-10-14 11:26:53 +09:00
parent 7cad74a41f
commit 0d4b985d5a
11 changed files with 1365 additions and 7 deletions

View File

@@ -0,0 +1,195 @@
"use client";
import { useState } from "react";
import { DriverManagementConfig } 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 { COLUMN_LABELS, DEFAULT_VISIBLE_COLUMNS } from "./driverUtils";
interface DriverManagementSettingsProps {
config: DriverManagementConfig;
onSave: (config: DriverManagementConfig) => void;
onClose: () => void;
}
export function DriverManagementSettings({ config, onSave, onClose }: DriverManagementSettingsProps) {
const [localConfig, setLocalConfig] = useState<DriverManagementConfig>(config);
const handleSave = () => {
onSave(localConfig);
};
// 컬럼 토글
const toggleColumn = (column: string) => {
const newColumns = localConfig.visibleColumns.includes(column)
? localConfig.visibleColumns.filter((c) => c !== column)
: [...localConfig.visibleColumns, column];
setLocalConfig({ ...localConfig, visibleColumns: newColumns });
};
return (
<div className="flex h-full max-h-[600px] flex-col overflow-hidden">
<div className="flex-1 space-y-6 overflow-y-auto p-6">
{/* 자동 새로고침 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"> </Label>
<Select
value={String(localConfig.autoRefreshInterval)}
onValueChange={(value) => setLocalConfig({ ...localConfig, autoRefreshInterval: parseInt(value) })}
>
<SelectTrigger className="w-full">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="0"> </SelectItem>
<SelectItem value="10">10</SelectItem>
<SelectItem value="30">30</SelectItem>
<SelectItem value="60">1</SelectItem>
<SelectItem value="300">5</SelectItem>
</SelectContent>
</Select>
</div>
{/* 정렬 설정 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"> </Label>
<div className="grid grid-cols-2 gap-3">
<Select
value={localConfig.sortBy}
onValueChange={(value) =>
setLocalConfig({ ...localConfig, sortBy: value as DriverManagementConfig["sortBy"] })
}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="name"></SelectItem>
<SelectItem value="vehicleNumber"></SelectItem>
<SelectItem value="status"></SelectItem>
<SelectItem value="departureTime"></SelectItem>
</SelectContent>
</Select>
<Select
value={localConfig.sortOrder}
onValueChange={(value) =>
setLocalConfig({ ...localConfig, sortOrder: value as DriverManagementConfig["sortOrder"] })
}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="asc"></SelectItem>
<SelectItem value="desc"></SelectItem>
</SelectContent>
</Select>
</div>
</div>
{/* 테마 설정 */}
<div className="space-y-3">
<Label className="text-sm font-semibold"></Label>
<div className="grid grid-cols-3 gap-3">
<Button
type="button"
variant={localConfig.theme === "light" ? "default" : "outline"}
className="w-full"
onClick={() => setLocalConfig({ ...localConfig, theme: "light" })}
>
Light
</Button>
<Button
type="button"
variant={localConfig.theme === "dark" ? "default" : "outline"}
className="w-full"
onClick={() => setLocalConfig({ ...localConfig, theme: "dark" })}
>
🌙 Dark
</Button>
<Button
type="button"
variant={localConfig.theme === "custom" ? "default" : "outline"}
className="w-full"
onClick={() => setLocalConfig({ ...localConfig, theme: "custom" })}
>
🎨 Custom
</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">
<div className="flex items-center justify-between">
<Label className="text-sm font-semibold"> </Label>
<Button
type="button"
variant="ghost"
size="sm"
onClick={() => setLocalConfig({ ...localConfig, visibleColumns: DEFAULT_VISIBLE_COLUMNS })}
>
</Button>
</div>
<div className="grid grid-cols-2 gap-2">
{Object.entries(COLUMN_LABELS).map(([key, label]) => (
<Card
key={key}
className={`cursor-pointer border p-3 transition-colors ${
localConfig.visibleColumns.includes(key) ? "border-primary bg-primary/5" : "hover:bg-gray-50"
}`}
onClick={() => toggleColumn(key)}
>
<div className="flex items-center justify-between">
<Label className="cursor-pointer text-sm font-medium">{label}</Label>
<Switch
checked={localConfig.visibleColumns.includes(key)}
onCheckedChange={() => toggleColumn(key)}
/>
</div>
</Card>
))}
</div>
</div>
</div>
{/* 푸터 - 고정 */}
<div className="flex flex-shrink-0 justify-end gap-3 border-t border-gray-200 bg-gray-50 p-4">
<Button variant="outline" onClick={onClose}>
</Button>
<Button onClick={handleSave}></Button>
</div>
</div>
);
}