83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
/**
|
|
* 검증 이슈 등록·단계 변경 실시간 알림 (STOMP)
|
|
*/
|
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
import { subscribeStompTopic } from '../utils/stompChartBroker';
|
|
import {
|
|
VERIFICATION_ISSUE_EVENT_TOPIC,
|
|
eventToToast,
|
|
parseVerificationIssueEvent,
|
|
shouldShowVerificationIssueEvent,
|
|
type VerificationIssueToastItem,
|
|
} from '../utils/verificationIssueEvents';
|
|
|
|
interface ContextValue {
|
|
toasts: VerificationIssueToastItem[];
|
|
dismissToast: (id: string) => void;
|
|
dismissAll: () => void;
|
|
}
|
|
|
|
const VerificationIssueNotificationContext = createContext<ContextValue | null>(null);
|
|
|
|
interface ProviderProps {
|
|
/** 검증게시판 메뉴 접근 가능 */
|
|
enabled: boolean;
|
|
/** 일반 설정 — 검증 이슈 알림 ON */
|
|
notifyEnabled: boolean;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export const VerificationIssueNotificationProvider: React.FC<ProviderProps> = ({
|
|
enabled,
|
|
notifyEnabled,
|
|
children,
|
|
}) => {
|
|
const [toasts, setToasts] = useState<VerificationIssueToastItem[]>([]);
|
|
const active = enabled && notifyEnabled;
|
|
|
|
const dismissToast = useCallback((id: string) => {
|
|
setToasts(prev => prev.filter(t => t.id !== id));
|
|
}, []);
|
|
|
|
const dismissAll = useCallback(() => {
|
|
setToasts([]);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (!active) {
|
|
setToasts([]);
|
|
return;
|
|
}
|
|
|
|
return subscribeStompTopic(VERIFICATION_ISSUE_EVENT_TOPIC, msg => {
|
|
const event = parseVerificationIssueEvent(msg.body);
|
|
if (!event || !shouldShowVerificationIssueEvent(event)) return;
|
|
|
|
const toast = eventToToast(event);
|
|
setToasts(prev => {
|
|
const withoutDup = prev.filter(t => t.id !== toast.id);
|
|
return [toast, ...withoutDup].slice(0, 8);
|
|
});
|
|
});
|
|
}, [active]);
|
|
|
|
const value = useMemo(
|
|
() => ({ toasts, dismissToast, dismissAll }),
|
|
[toasts, dismissToast, dismissAll],
|
|
);
|
|
|
|
return (
|
|
<VerificationIssueNotificationContext.Provider value={value}>
|
|
{children}
|
|
</VerificationIssueNotificationContext.Provider>
|
|
);
|
|
};
|
|
|
|
export function useVerificationIssueNotification(): ContextValue {
|
|
const ctx = useContext(VerificationIssueNotificationContext);
|
|
if (!ctx) {
|
|
throw new Error('useVerificationIssueNotification must be used within VerificationIssueNotificationProvider');
|
|
}
|
|
return ctx;
|
|
}
|