| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- 'use client';
- import { useEffect, useRef, useState, useCallback } from 'react';
- import * as signalR from '@microsoft/signalr';
- import { GoalProgress, CrewRankItem } from '@/types/donation';
- /**
- * DonationHub 공통 Hook — 목표/순위/크루 위젯에서 공유
- */
- export function useDonationHub(widgetToken: string, hubUrl: string) {
- const connectionRef = useRef<signalR.HubConnection|null>(null);
- const [connected, setConnected] = useState(false);
- // 목표
- const [goalProgress, setGoalProgress] = useState<GoalProgress|null>(null);
- // 순위
- const [ranking, setRanking] = useState<{ rank: number; sponsorMemberID: number; sponsorName: string; totalAmount: number; donationCount: number }[]>([]);
- // 크루
- const [crewRanking, setCrewRanking] = useState<CrewRankItem[]>([]);
- const [crewTotalAmount, setCrewTotalAmount] = useState(0);
- useEffect(() => {
- const conn = new signalR.HubConnectionBuilder()
- .withUrl(hubUrl)
- .withAutomaticReconnect()
- .build();
- conn.on('ReceiveGoalUpdate', (data: GoalProgress) => {
- setGoalProgress(data);
- });
- conn.on('ReceiveRankUpdate', (data: { list: typeof ranking }) => {
- setRanking(data.list);
- });
- conn.on('ReceiveCrewUpdate', (data: { list: CrewRankItem[]; totalAmount: number }) => {
- setCrewRanking(data.list);
- setCrewTotalAmount(data.totalAmount);
- });
- conn.start().then(() => {
- conn.invoke('JoinChannel', widgetToken);
- setConnected(true);
- }).catch(err => console.error('[DonationHub]', err));
- conn.onreconnected(() => {
- conn.invoke('JoinChannel', widgetToken);
- setConnected(true);
- });
- conn.onclose(() => setConnected(false));
- connectionRef.current = conn;
- return () => { conn.stop(); };
- }, [widgetToken, hubUrl]);
- return { connected, goalProgress, setGoalProgress, ranking, setRanking, crewRanking, crewTotalAmount };
- }
|