"use client"; /** * UnsavedChangesGuard * * 모달에서 저장하지 않은 변경사항이 있을 때 닫기를 시도하면 * 확인 다이얼로그를 띄우는 공통 모듈. * * 사용법: * 1. useUnsavedChangesGuard 훅으로 상태 관리 * 2. UnsavedChangesDialog 컴포넌트로 확인 다이얼로그 렌더링 * * @example * const guard = useUnsavedChangesGuard({ * hasChanges: () => JSON.stringify(data) !== initialSnapshot, * onClose: () => onOpenChange(false), * }); * * * ... * * * */ import { useState, useCallback } from "react"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; interface UseUnsavedChangesGuardOptions { hasChanges: () => boolean; onClose: () => void; title?: string; description?: string; } export interface UnsavedChangesGuardState { showConfirm: boolean; setShowConfirm: (v: boolean) => void; tryClose: () => void; doClose: () => void; handleOpenChange: (open: boolean) => void; title: string; description: string; } export function useUnsavedChangesGuard({ hasChanges, onClose, title = "저장하지 않은 변경사항", description = "저장하지 않은 변경사항이 있습니다. 저장하지 않고 닫으시겠습니까?", }: UseUnsavedChangesGuardOptions): UnsavedChangesGuardState { const [showConfirm, setShowConfirm] = useState(false); const doClose = useCallback(() => { setShowConfirm(false); onClose(); }, [onClose]); const tryClose = useCallback(() => { if (hasChanges()) { setShowConfirm(true); return; } doClose(); }, [hasChanges, doClose]); const handleOpenChange = useCallback( (open: boolean) => { if (!open) tryClose(); }, [tryClose], ); return { showConfirm, setShowConfirm, tryClose, doClose, handleOpenChange, title, description }; } interface UnsavedChangesDialogProps { guard: UnsavedChangesGuardState; } export function UnsavedChangesDialog({ guard }: UnsavedChangesDialogProps) { return ( {guard.title} {guard.description} 닫기 취소 ); }