64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';
|
|
import { NotificationModal } from '../components/NotificationModal';
|
|
|
|
interface NotificationOptions {
|
|
title: string;
|
|
message: string;
|
|
type?: 'success' | 'error' | 'info';
|
|
}
|
|
|
|
const NotificationContext = createContext<((options: NotificationOptions) => void) | undefined>(undefined);
|
|
|
|
export const NotificationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const [state, setState] = useState<{
|
|
isOpen: boolean;
|
|
title?: string;
|
|
message?: string;
|
|
type?: 'success' | 'error' | 'info';
|
|
}>({ isOpen: false });
|
|
|
|
const notify = useCallback(({ title, message, type = 'info' }: NotificationOptions) => {
|
|
setState({
|
|
isOpen: true,
|
|
title,
|
|
message,
|
|
type,
|
|
});
|
|
}, []);
|
|
|
|
const handleClose = useCallback(() => {
|
|
setState(prev => ({ ...prev, isOpen: false }));
|
|
}, []);
|
|
|
|
// Tự động đóng sau 3 giây nếu modal đang mở
|
|
useEffect(() => {
|
|
if (state.isOpen) {
|
|
const timer = setTimeout(() => {
|
|
handleClose();
|
|
}, 3000);
|
|
|
|
return () => clearTimeout(timer); // Xóa timer nếu người dùng bấm nút đóng trước 3 giây hoặc thông báo mới đè lên
|
|
}
|
|
}, [state.isOpen, handleClose]);
|
|
|
|
return (
|
|
<NotificationContext.Provider value={notify}>
|
|
{children}
|
|
<NotificationModal
|
|
isOpen={state.isOpen}
|
|
title={state.title}
|
|
message={state.message}
|
|
type={state.type}
|
|
onConfirm={handleClose}
|
|
/>
|
|
</NotificationContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useNotification = () => {
|
|
const context = useContext(NotificationContext);
|
|
if (!context) {
|
|
throw new Error('useNotification must be used within a NotificationProvider');
|
|
}
|
|
return context;
|
|
}; |