160 lines
5.8 KiB
TypeScript
160 lines
5.8 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { DashboardElement, DriverManagementConfig, DriverInfo } from "../types";
|
|
import { DriverListView } from "./DriverListView";
|
|
import { DriverManagementSettings } from "./DriverManagementSettings";
|
|
import { MOCK_DRIVERS } from "./driverMockData";
|
|
import { filterDrivers, sortDrivers, DEFAULT_VISIBLE_COLUMNS } from "./driverUtils";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Settings, Search, RefreshCw } from "lucide-react";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
|
|
interface DriverManagementWidgetProps {
|
|
element: DashboardElement;
|
|
onConfigUpdate?: (config: DriverManagementConfig) => void;
|
|
}
|
|
|
|
export function DriverManagementWidget({ element, onConfigUpdate }: DriverManagementWidgetProps) {
|
|
const [drivers, setDrivers] = useState<DriverInfo[]>(MOCK_DRIVERS);
|
|
const [searchTerm, setSearchTerm] = useState("");
|
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
const [lastRefresh, setLastRefresh] = useState(new Date());
|
|
|
|
// 기본 설정
|
|
const config = element.driverManagementConfig || {
|
|
viewType: "list",
|
|
autoRefreshInterval: 30,
|
|
visibleColumns: DEFAULT_VISIBLE_COLUMNS,
|
|
theme: "light",
|
|
statusFilter: "all",
|
|
sortBy: "name",
|
|
sortOrder: "asc",
|
|
};
|
|
|
|
// 자동 새로고침
|
|
useEffect(() => {
|
|
if (config.autoRefreshInterval <= 0) return;
|
|
|
|
const interval = setInterval(() => {
|
|
// 실제 환경에서는 API 호출
|
|
setDrivers(MOCK_DRIVERS);
|
|
setLastRefresh(new Date());
|
|
}, config.autoRefreshInterval * 1000);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [config.autoRefreshInterval]);
|
|
|
|
// 수동 새로고침
|
|
const handleRefresh = () => {
|
|
setDrivers(MOCK_DRIVERS);
|
|
setLastRefresh(new Date());
|
|
};
|
|
|
|
// 설정 저장
|
|
const handleSaveSettings = (newConfig: DriverManagementConfig) => {
|
|
onConfigUpdate?.(newConfig);
|
|
setSettingsOpen(false);
|
|
};
|
|
|
|
// 필터링 및 정렬
|
|
const filteredDrivers = sortDrivers(
|
|
filterDrivers(drivers, config.statusFilter, searchTerm),
|
|
config.sortBy,
|
|
config.sortOrder,
|
|
);
|
|
|
|
// 컴팩트 모드 판단 (위젯 크기가 작을 때)
|
|
const isCompact = element.size.width < 400 || element.size.height < 300;
|
|
|
|
return (
|
|
<div className="relative flex h-full w-full flex-col bg-background">
|
|
{/* 헤더 - 컴팩트 모드가 아닐 때만 표시 */}
|
|
{!isCompact && (
|
|
<div className="flex-shrink-0 border-b border-border bg-muted px-3 py-2">
|
|
<div className="flex items-center justify-between gap-2">
|
|
{/* 검색 */}
|
|
<div className="relative max-w-xs flex-1">
|
|
<Search className="absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
|
|
<Input
|
|
type="text"
|
|
placeholder="기사명, 차량번호 검색"
|
|
value={searchTerm}
|
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
className="h-8 pl-8 text-xs"
|
|
/>
|
|
</div>
|
|
|
|
{/* 상태 필터 */}
|
|
<Select
|
|
value={config.statusFilter}
|
|
onValueChange={(value) => {
|
|
onConfigUpdate?.({
|
|
...config,
|
|
statusFilter: value as DriverManagementConfig["statusFilter"],
|
|
});
|
|
}}
|
|
>
|
|
<SelectTrigger className="h-8 w-24 text-xs">
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="all">전체</SelectItem>
|
|
<SelectItem value="driving">운행중</SelectItem>
|
|
<SelectItem value="standby">대기중</SelectItem>
|
|
<SelectItem value="resting">휴식중</SelectItem>
|
|
<SelectItem value="maintenance">점검중</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
|
|
{/* 새로고침 버튼 */}
|
|
<Button variant="ghost" size="icon" className="h-8 w-8" onClick={handleRefresh}>
|
|
<RefreshCw className="h-4 w-4" />
|
|
</Button>
|
|
|
|
{/* 설정 버튼 */}
|
|
<Popover open={settingsOpen} onOpenChange={setSettingsOpen}>
|
|
<PopoverTrigger asChild>
|
|
<Button variant="ghost" size="icon" className="h-8 w-8">
|
|
<Settings className="h-4 w-4" />
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-[500px] p-0" align="end">
|
|
<DriverManagementSettings
|
|
config={config}
|
|
onSave={handleSaveSettings}
|
|
onClose={() => setSettingsOpen(false)}
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</div>
|
|
|
|
{/* 통계 정보 */}
|
|
<div className="mt-2 flex items-center gap-3 text-xs text-foreground">
|
|
<span>
|
|
전체 <span className="font-semibold text-foreground">{filteredDrivers.length}</span>명
|
|
</span>
|
|
<span className="text-muted-foreground">|</span>
|
|
<span>
|
|
운행중{" "}
|
|
<span className="font-semibold text-success">
|
|
{filteredDrivers.filter((d) => d.status === "driving").length}
|
|
</span>
|
|
명
|
|
</span>
|
|
<span className="text-muted-foreground">|</span>
|
|
<span className="text-xs text-muted-foreground">최근 업데이트: {lastRefresh.toLocaleTimeString("ko-KR")}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* 리스트 뷰 */}
|
|
<div className="flex-1 overflow-hidden">
|
|
<DriverListView drivers={filteredDrivers} config={config} isCompact={isCompact} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|