ERP-node/frontend/components/report/ReportCopyModal.tsx

103 lines
3.5 KiB
TypeScript
Raw Normal View History

"use client";
import { useState, useCallback, useRef } from "react";
import { ReportMaster } from "@/types/report";
import { reportApi } from "@/lib/api/reportApi";
import { useToast } from "@/hooks/use-toast";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { useUnsavedChangesGuard, UnsavedChangesDialog } from "@/components/common/UnsavedChangesGuard";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Loader2 } from "lucide-react";
interface ReportCopyModalProps {
report: ReportMaster;
onClose: () => void;
onSuccess: () => void;
}
export function ReportCopyModal({ report, onClose, onSuccess }: ReportCopyModalProps) {
const [newName, setNewName] = useState(`${report.report_name_kor} (복사)`);
const [isCopying, setIsCopying] = useState(false);
const initialNameRef = useRef(`${report.report_name_kor} (복사)`);
const { toast } = useToast();
const guard = useUnsavedChangesGuard({
hasChanges: () => !isCopying && newName !== initialNameRef.current,
onClose,
title: "입력된 내용이 있습니다",
description: "입력된 내용이 저장되지 않습니다. 정말 닫으시겠습니까?",
});
const handleCopy = async () => {
const trimmed = newName.trim();
if (!trimmed) {
toast({ title: "오류", description: "리포트 이름을 입력해주세요.", variant: "destructive" });
return;
}
setIsCopying(true);
try {
const response = await reportApi.copyReport(report.report_id, trimmed);
if (response.success) {
toast({ title: "성공", description: "리포트가 복사되었습니다." });
onSuccess();
}
} catch (error: any) {
toast({
title: "오류",
description: error.message || "리포트 복사에 실패했습니다.",
variant: "destructive",
});
} finally {
setIsCopying(false);
}
};
return (
<>
<Dialog open onOpenChange={guard.handleOpenChange}>
<DialogContent className="sm:max-w-lg">
<DialogHeader>
<DialogTitle className="text-lg"> </DialogTitle>
</DialogHeader>
<div className="space-y-5 py-3">
<div className="space-y-2.5">
<Label htmlFor="copy-name" className="text-base">
</Label>
<Input
id="copy-name"
value={newName}
onChange={(e) => setNewName(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && !isCopying && handleCopy()}
placeholder="리포트 이름 입력"
className="h-11 text-base"
autoFocus
/>
</div>
</div>
<DialogFooter>
<Button variant="outline" onClick={guard.tryClose} disabled={isCopying} className="text-base">
</Button>
<Button onClick={handleCopy} disabled={isCopying} className="text-base">
{isCopying ? (
<>
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
...
</>
) : (
"복사"
)}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<UnsavedChangesDialog guard={guard} />
</>
);
}