"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}
닫기
취소
);
}