81 lines
1.8 KiB
TypeScript
81 lines
1.8 KiB
TypeScript
'use client';
|
|||
|
|
|
||
|
|
import { useEffect } from 'react';
|
||
|
|
import { useRouter } from 'next/navigation';
|
||
|
|
|
||
|
|
|
||
|
|
interface UseNavigationBlockerProps {
|
||
|
|
shouldBlock: boolean;
|
||
|
|
message?: string;
|
||
|
|
onConfirm?: () => void;
|
||
|
|
onCancel?: () => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const useNavigationBlocker = ({
|
||
|
|
shouldBlock,
|
||
|
|
message,
|
||
|
|
onConfirm,
|
||
|
|
onCancel
|
||
|
|
}: UseNavigationBlockerProps) => {
|
||
|
|
const router = useRouter();
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!shouldBlock) return;
|
||
|
|
|
||
|
|
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||
|
|
e.preventDefault();
|
||
|
|
e.returnValue = message;
|
||
|
|
return message;
|
||
|
|
};
|
||
|
|
|
||
|
|
const handleClick = (e: MouseEvent) => {
|
||
|
|
const target = e.target as HTMLElement;
|
||
|
|
const link = target.closest('a');
|
||
|
|
|
||
|
|
if (link && link.href) {
|
||
|
|
const currentUrl = window.location.href;
|
||
|
|
if (link.href !== currentUrl && !link.href.startsWith('#')) {
|
||
|
|
e.preventDefault();
|
||
|
|
e.stopPropagation();
|
||
|
|
|
||
|
|
const confirmed = window.confirm(message);
|
||
|
|
if (confirmed) {
|
||
|
|
onConfirm?.();
|
||
|
|
window.location.href = link.href;
|
||
|
|
} else {
|
||
|
|
onCancel?.();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
window.addEventListener('beforeunload', handleBeforeUnload);
|
||
|
|
document.addEventListener('click', handleClick, true);
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
window.removeEventListener('beforeunload', handleBeforeUnload);
|
||
|
|
document.removeEventListener('click', handleClick, true);
|
||
|
|
};
|
||
|
|
}, [shouldBlock, message, onConfirm, onCancel]);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
if (!shouldBlock) return;
|
||
|
|
|
||
|
|
const originalPush = router.push;
|
||
|
|
|
||
|
|
router.push = async (...args) => {
|
||
|
|
const confirmed = window.confirm(message);
|
||
|
|
if (confirmed) {
|
||
|
|
onConfirm?.();
|
||
|
|
return originalPush.apply(router, args);
|
||
|
|
} else {
|
||
|
|
onCancel?.();
|
||
|
|
return Promise.resolve(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return () => {
|
||
|
|
router.push = originalPush;
|
||
|
|
};
|
||
|
|
}, [shouldBlock, message, router, onConfirm, onCancel]);
|
||
|
|
};
|