ERP-node/frontend/lib/v2-core/services/ScheduleConfirmDialog.tsx

209 lines
7.8 KiB
TypeScript
Raw Normal View History

/**
*
*
* .
*/
"use client";
import React from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Calendar, Plus, Trash2, RefreshCw } from "lucide-react";
import type { SchedulePreviewResult } from "./ScheduleGeneratorService";
interface ScheduleConfirmDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
preview: SchedulePreviewResult | null;
onConfirm: () => void;
onCancel: () => void;
isLoading?: boolean;
}
export function ScheduleConfirmDialog({
open,
onOpenChange,
preview,
onConfirm,
onCancel,
isLoading = false,
}: ScheduleConfirmDialogProps) {
if (!preview) return null;
const { summary, toCreate, toDelete, toUpdate } = preview;
return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent className="max-w-[95vw] sm:max-w-[600px]">
<AlertDialogHeader>
<AlertDialogTitle className="flex items-center gap-2 text-base sm:text-lg">
<Calendar className="h-5 w-5" />
</AlertDialogTitle>
<AlertDialogDescription className="text-xs sm:text-sm">
. ?
</AlertDialogDescription>
</AlertDialogHeader>
{/* 요약 정보 */}
<div className="grid grid-cols-3 gap-3 py-4">
<div className="flex flex-col items-center rounded-lg border bg-green-50 p-3 dark:bg-green-900/20">
<Plus className="mb-1 h-5 w-5 text-green-600" />
<span className="text-2xl font-bold text-green-600">
{summary.createCount}
</span>
<span className="text-xs text-muted-foreground"></span>
</div>
<div className="flex flex-col items-center rounded-lg border bg-red-50 p-3 dark:bg-red-900/20">
<Trash2 className="mb-1 h-5 w-5 text-red-600" />
<span className="text-2xl font-bold text-red-600">
{summary.deleteCount}
</span>
<span className="text-xs text-muted-foreground"></span>
</div>
<div className="flex flex-col items-center rounded-lg border bg-blue-50 p-3 dark:bg-blue-900/20">
<RefreshCw className="mb-1 h-5 w-5 text-blue-600" />
<span className="text-2xl font-bold text-blue-600">
{summary.updateCount}
</span>
<span className="text-xs text-muted-foreground"></span>
</div>
</div>
{/* 상세 정보 */}
<ScrollArea className="max-h-[300px]">
<div className="space-y-4">
{/* 생성될 스케줄 */}
{toCreate.length > 0 && (
<div>
<h4 className="mb-2 flex items-center gap-2 text-sm font-medium">
<Badge variant="default" className="bg-green-600">
</Badge>
{toCreate.length}
</h4>
<div className="space-y-1 rounded-md border p-2">
{toCreate.slice(0, 5).map((item, index) => (
<div
key={index}
className="flex items-center justify-between text-xs"
>
<span className="font-medium">
{item.resource_name || item.resource_id}
</span>
<span className="text-muted-foreground">
{item.start_date} ~ {item.end_date} / {item.plan_qty}
</span>
</div>
))}
{toCreate.length > 5 && (
<div className="text-center text-xs text-muted-foreground">
... {toCreate.length - 5}
</div>
)}
</div>
</div>
)}
{/* 삭제될 스케줄 */}
{toDelete.length > 0 && (
<div>
<h4 className="mb-2 flex items-center gap-2 text-sm font-medium">
<Badge variant="destructive"></Badge>
{toDelete.length}
</h4>
<div className="space-y-1 rounded-md border border-red-200 bg-red-50/50 p-2 dark:border-red-800 dark:bg-red-900/10">
{toDelete.slice(0, 5).map((item, index) => (
<div
key={index}
className="flex items-center justify-between text-xs"
>
<span className="font-medium">
{item.resource_name || item.resource_id}
</span>
<span className="text-muted-foreground">
{item.start_date} ~ {item.end_date}
</span>
</div>
))}
{toDelete.length > 5 && (
<div className="text-center text-xs text-muted-foreground">
... {toDelete.length - 5}
</div>
)}
</div>
</div>
)}
{/* 수정될 스케줄 */}
{toUpdate.length > 0 && (
<div>
<h4 className="mb-2 flex items-center gap-2 text-sm font-medium">
<Badge variant="secondary"></Badge>
{toUpdate.length}
</h4>
<div className="space-y-1 rounded-md border border-blue-200 bg-blue-50/50 p-2 dark:border-blue-800 dark:bg-blue-900/10">
{toUpdate.slice(0, 5).map((item, index) => (
<div
key={index}
className="flex items-center justify-between text-xs"
>
<span className="font-medium">
{item.resource_name || item.resource_id}
</span>
<span className="text-muted-foreground">
{item.start_date} ~ {item.end_date}
</span>
</div>
))}
{toUpdate.length > 5 && (
<div className="text-center text-xs text-muted-foreground">
... {toUpdate.length - 5}
</div>
)}
</div>
</div>
)}
</div>
</ScrollArea>
{/* 총 수량 */}
<div className="flex items-center justify-between rounded-md bg-muted p-3">
<span className="text-sm font-medium"> </span>
<span className="text-lg font-bold">
{summary.totalQty.toLocaleString()}
</span>
</div>
<AlertDialogFooter className="gap-2 sm:gap-0">
<AlertDialogCancel
onClick={onCancel}
disabled={isLoading}
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
>
</AlertDialogCancel>
<AlertDialogAction
onClick={onConfirm}
disabled={isLoading}
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
>
{isLoading ? "처리 중..." : "확인 및 적용"}
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}