플로우 페이지네이션 안보임
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* 저장 확인 다이얼로그
|
||||
*
|
||||
* 경고가 있을 때 저장 전 확인을 받습니다
|
||||
*/
|
||||
|
||||
import { memo } from "react";
|
||||
import { AlertTriangle, AlertCircle, Info } from "lucide-react";
|
||||
import type { FlowValidation } from "@/lib/utils/flowValidation";
|
||||
import { summarizeValidations } from "@/lib/utils/flowValidation";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
|
||||
interface SaveConfirmDialogProps {
|
||||
open: boolean;
|
||||
validations: FlowValidation[];
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
export const SaveConfirmDialog = memo(
|
||||
({ open, validations, onConfirm, onCancel }: SaveConfirmDialogProps) => {
|
||||
const summary = summarizeValidations(validations);
|
||||
|
||||
// 오류가 있으면 저장 불가
|
||||
if (summary.hasBlockingIssues) {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onCancel}>
|
||||
<DialogContent className="max-w-[95vw] sm:max-w-[500px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2 text-base sm:text-lg">
|
||||
<AlertCircle className="h-5 w-5 text-red-500" />
|
||||
저장할 수 없습니다
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-xs sm:text-sm">
|
||||
오류를 수정한 후 다시 시도하세요
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant="destructive" className="gap-1">
|
||||
<AlertCircle className="h-3 w-3" />
|
||||
오류 {summary.errorCount}
|
||||
</Badge>
|
||||
{summary.warningCount > 0 && (
|
||||
<Badge className="gap-1 bg-yellow-500 hover:bg-yellow-600">
|
||||
<AlertTriangle className="h-3 w-3" />
|
||||
경고 {summary.warningCount}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ScrollArea className="max-h-[300px]">
|
||||
<div className="space-y-2">
|
||||
{validations
|
||||
.filter((v) => v.severity === "error")
|
||||
.map((validation, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="rounded-lg border-2 border-red-200 bg-red-50 p-3"
|
||||
>
|
||||
<div className="mb-1 text-xs font-medium text-red-600">
|
||||
{validation.type}
|
||||
</div>
|
||||
<div className="text-sm text-red-800">
|
||||
{validation.message}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
<p className="text-xs text-gray-500">
|
||||
위의 오류를 먼저 해결해주세요. 경고는 저장 후에도 확인할 수
|
||||
있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="gap-2 sm:gap-0">
|
||||
<Button
|
||||
onClick={onCancel}
|
||||
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
|
||||
>
|
||||
확인
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
// 경고만 있는 경우 - 저장 가능하지만 확인 필요
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onCancel}>
|
||||
<DialogContent className="max-w-[95vw] sm:max-w-[500px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2 text-base sm:text-lg">
|
||||
<AlertTriangle className="h-5 w-5 text-yellow-500" />
|
||||
경고가 있습니다
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-xs sm:text-sm">
|
||||
플로우에 {summary.warningCount + summary.infoCount}개의 경고가
|
||||
발견되었습니다
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
{summary.warningCount > 0 && (
|
||||
<Badge className="gap-1 bg-yellow-500 hover:bg-yellow-600">
|
||||
<AlertTriangle className="h-3 w-3" />
|
||||
경고 {summary.warningCount}
|
||||
</Badge>
|
||||
)}
|
||||
{summary.infoCount > 0 && (
|
||||
<Badge variant="secondary" className="gap-1">
|
||||
<Info className="h-3 w-3" />
|
||||
정보 {summary.infoCount}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<ScrollArea className="max-h-[300px]">
|
||||
<div className="space-y-2">
|
||||
{validations
|
||||
.filter((v) => v.severity === "warning")
|
||||
.map((validation, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="rounded-lg border-2 border-yellow-200 bg-yellow-50 p-3"
|
||||
>
|
||||
<div className="mb-1 text-xs font-medium text-yellow-600">
|
||||
{validation.type}
|
||||
</div>
|
||||
<div className="text-sm text-yellow-800">
|
||||
{validation.message}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{validations
|
||||
.filter((v) => v.severity === "info")
|
||||
.map((validation, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="rounded-lg border-2 border-blue-200 bg-blue-50 p-3"
|
||||
>
|
||||
<div className="mb-1 text-xs font-medium text-blue-600">
|
||||
{validation.type}
|
||||
</div>
|
||||
<div className="text-sm text-blue-800">
|
||||
{validation.message}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
|
||||
<div className="rounded-lg bg-gray-50 p-3">
|
||||
<p className="text-xs text-gray-600">
|
||||
⚠️ 이 경고들은 플로우의 동작에 영향을 줄 수 있습니다.
|
||||
<br />
|
||||
그래도 저장하시겠습니까?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="gap-2 sm:gap-0">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={onCancel}
|
||||
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
|
||||
>
|
||||
취소
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onConfirm}
|
||||
className="h-8 flex-1 bg-yellow-500 text-xs hover:bg-yellow-600 sm:h-10 sm:flex-none sm:text-sm"
|
||||
>
|
||||
경고 무시하고 저장
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
SaveConfirmDialog.displayName = "SaveConfirmDialog";
|
||||
|
||||
Reference in New Issue
Block a user