차량관리(기초데이터) 구현

This commit is contained in:
dohyeons
2025-12-01 18:41:02 +09:00
parent cea2421899
commit 9c3f1d26ad
10 changed files with 914 additions and 3 deletions

View File

@@ -11,8 +11,18 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Camera, X } from "lucide-react";
import { Camera, X, Car, Wrench, Clock } from "lucide-react";
import { ProfileFormData } from "@/types/profile";
import { Separator } from "@/components/ui/separator";
// 운전자 정보 타입
export interface DriverInfo {
vehicleNumber: string;
vehicleType: string | null;
licenseNumber: string;
phoneNumber: string;
vehicleStatus: string | null;
}
// 알림 모달 컴포넌트
interface AlertModalProps {
@@ -54,6 +64,14 @@ function AlertModal({ isOpen, onClose, title, message, type = "info" }: AlertMod
);
}
// 운전자 폼 데이터 타입
export interface DriverFormData {
vehicleNumber: string;
vehicleType: string;
licenseNumber: string;
phoneNumber: string;
}
interface ProfileModalProps {
isOpen: boolean;
user: any;
@@ -70,6 +88,13 @@ interface ProfileModalProps {
message: string;
type: "success" | "error" | "info";
};
// 운전자 관련 props (선택적)
isDriver?: boolean;
driverInfo?: DriverInfo | null;
driverFormData?: DriverFormData;
onDriverFormChange?: (field: keyof DriverFormData, value: string) => void;
onDriverStatusChange?: (status: "off" | "maintenance") => void;
onDriverAccountDelete?: () => void;
onClose: () => void;
onFormChange: (field: keyof ProfileFormData, value: string) => void;
onImageSelect: (event: React.ChangeEvent<HTMLInputElement>) => void;
@@ -89,6 +114,12 @@ export function ProfileModal({
isSaving,
departments,
alertModal,
isDriver = false,
driverInfo,
driverFormData,
onDriverFormChange,
onDriverStatusChange,
onDriverAccountDelete,
onClose,
onFormChange,
onImageSelect,
@@ -96,6 +127,21 @@ export function ProfileModal({
onSave,
onAlertClose,
}: ProfileModalProps) {
// 차량 상태 한글 변환
const getStatusLabel = (status: string | null) => {
switch (status) {
case "off":
return "대기";
case "active":
return "운행중";
case "inactive":
return "공차";
case "maintenance":
return "정비";
default:
return status || "-";
}
};
return (
<>
<ResizableDialog open={isOpen} onOpenChange={onClose}>
@@ -234,6 +280,101 @@ export function ProfileModal({
</Select>
</div>
</div>
{/* 운전자 정보 섹션 (공차중계 사용자만) */}
{isDriver && driverFormData && onDriverFormChange && (
<>
<Separator className="my-4" />
<div className="space-y-4">
<div className="flex items-center gap-2">
<Car className="h-5 w-5 text-primary" />
<h3 className="text-sm font-semibold">/ </h3>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="vehicleNumber"></Label>
<Input
id="vehicleNumber"
value={driverFormData.vehicleNumber}
onChange={(e) => onDriverFormChange("vehicleNumber", e.target.value)}
placeholder="12가1234"
/>
</div>
<div className="space-y-2">
<Label htmlFor="vehicleType"></Label>
<Input
id="vehicleType"
value={driverFormData.vehicleType}
onChange={(e) => onDriverFormChange("vehicleType", e.target.value)}
placeholder="1톤 카고"
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="driverPhone"></Label>
<Input
id="driverPhone"
value={driverFormData.phoneNumber}
onChange={(e) => onDriverFormChange("phoneNumber", e.target.value)}
placeholder="010-1234-5678"
/>
</div>
<div className="space-y-2">
<Label htmlFor="licenseNumber"></Label>
<Input
id="licenseNumber"
value={driverFormData.licenseNumber}
onChange={(e) => onDriverFormChange("licenseNumber", e.target.value)}
placeholder="12-34-567890-12"
/>
</div>
</div>
{/* 차량 상태 */}
{driverInfo && onDriverStatusChange && (
<div className="space-y-2">
<Label> </Label>
<div className="flex items-center gap-4">
<span className="text-sm font-medium px-3 py-1 rounded-full bg-muted">
{getStatusLabel(driverInfo.vehicleStatus)}
</span>
<div className="flex gap-2">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => onDriverStatusChange("off")}
disabled={driverInfo.vehicleStatus === "off"}
className="flex items-center gap-1"
>
<Clock className="h-3 w-3" />
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => onDriverStatusChange("maintenance")}
disabled={driverInfo.vehicleStatus === "maintenance"}
className="flex items-center gap-1"
>
<Wrench className="h-3 w-3" />
</Button>
</div>
</div>
<p className="text-xs text-muted-foreground">
* /
</p>
</div>
)}
</div>
</>
)}
</div>
<ResizableDialogFooter>