broadcastProvider.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. 'use client';
  2. import { createContext, useContext, useEffect, useState, useCallback } from 'react';
  3. import { BroadcastInfo, BroadcastState } from '@/types/broadcast';
  4. import { liveStreams, generateNewBroadcast, getTopPopularStreams } from '@/data/mockBroadcasts';
  5. // 방송 정보 Context 타입
  6. interface BroadcastContextType {
  7. // 상태
  8. popularBroadcasts: BroadcastInfo[];
  9. liveBroadcasts: BroadcastInfo[];
  10. isLoading: boolean;
  11. error: string | null;
  12. currentPage: number;
  13. hasMore: boolean;
  14. // 액션
  15. fetchPopularBroadcasts: () => void;
  16. fetchLiveBroadcasts: () => void;
  17. loadMoreBroadcasts: () => void;
  18. refreshBroadcasts: () => void;
  19. updateBroadcast: (broadcast: BroadcastInfo) => void;
  20. removeBroadcast: (broadcastId: string) => void;
  21. }
  22. // Context 생성
  23. const BroadcastContext = createContext<BroadcastContextType>({
  24. popularBroadcasts: [],
  25. liveBroadcasts: [],
  26. isLoading: false,
  27. error: null,
  28. currentPage: 1,
  29. hasMore: true,
  30. fetchPopularBroadcasts: () => {},
  31. fetchLiveBroadcasts: () => {},
  32. loadMoreBroadcasts: () => {},
  33. refreshBroadcasts: () => {},
  34. updateBroadcast: () => {},
  35. removeBroadcast: () => {},
  36. });
  37. // Context Provider
  38. export function BroadcastProvider({ children }: { children: React.ReactNode }) {
  39. const [state, setState] = useState<BroadcastState>({
  40. popularBroadcasts: [],
  41. liveBroadcasts: [],
  42. isLoading: false,
  43. error: null,
  44. currentPage: 1,
  45. hasMore: true,
  46. });
  47. // 인기 방송 목록 로드
  48. const fetchPopularBroadcasts = useCallback(() => {
  49. setState(prev => ({ ...prev, isLoading: true, error: null }));
  50. // 실시간 LIVE에서 시청자수 기준 top5 가져오기
  51. setState(prev => ({
  52. ...prev,
  53. popularBroadcasts: getTopPopularStreams(5),
  54. isLoading: false,
  55. }));
  56. }, []);
  57. // 실시간 방송 목록 로드
  58. const fetchLiveBroadcasts = useCallback(() => {
  59. setState(prev => ({ ...prev, isLoading: true, error: null }));
  60. // 더미 데이터에서 실시간 방송 목록 가져오기
  61. setState(prev => ({
  62. ...prev,
  63. liveBroadcasts: [...liveStreams],
  64. isLoading: false,
  65. }));
  66. }, []);
  67. // 더 많은 방송 로드 (무한스크롤용)
  68. const loadMoreBroadcasts = useCallback(() => {
  69. if (!state.hasMore || state.isLoading) return;
  70. setState(prev => ({ ...prev, isLoading: true }));
  71. // 헬퍼 함수를 사용하여 새로운 방송 생성
  72. const newBroadcast = generateNewBroadcast(state.currentPage + 1);
  73. setState(prev => ({
  74. ...prev,
  75. liveBroadcasts: [...prev.liveBroadcasts, newBroadcast],
  76. currentPage: prev.currentPage + 1,
  77. hasMore: prev.currentPage < 5,
  78. isLoading: false,
  79. }));
  80. }, [state.hasMore, state.isLoading, state.currentPage]);
  81. // 방송 목록 새로고침
  82. const refreshBroadcasts = useCallback(() => {
  83. setState(prev => ({ ...prev, currentPage: 1, hasMore: true }));
  84. fetchPopularBroadcasts();
  85. fetchLiveBroadcasts();
  86. }, [fetchPopularBroadcasts, fetchLiveBroadcasts]);
  87. // 방송 정보 업데이트
  88. const updateBroadcast = useCallback((updatedBroadcast: BroadcastInfo) => {
  89. setState(prev => ({
  90. ...prev,
  91. popularBroadcasts: prev.popularBroadcasts.map(broadcast =>
  92. broadcast.id === updatedBroadcast.id ? updatedBroadcast : broadcast
  93. ),
  94. liveBroadcasts: prev.liveBroadcasts.map(broadcast =>
  95. broadcast.id === updatedBroadcast.id ? updatedBroadcast : broadcast
  96. ),
  97. }));
  98. }, []);
  99. // 방송 제거
  100. const removeBroadcast = useCallback((broadcastId: string) => {
  101. setState(prev => ({
  102. ...prev,
  103. popularBroadcasts: prev.popularBroadcasts.filter(broadcast => broadcast.id !== broadcastId),
  104. liveBroadcasts: prev.liveBroadcasts.filter(broadcast => broadcast.id !== broadcastId),
  105. }));
  106. }, []);
  107. // 초기 데이터 로드
  108. useEffect(() => {
  109. fetchPopularBroadcasts();
  110. fetchLiveBroadcasts();
  111. }, [fetchPopularBroadcasts, fetchLiveBroadcasts]);
  112. const value: BroadcastContextType = {
  113. ...state,
  114. fetchPopularBroadcasts,
  115. fetchLiveBroadcasts,
  116. loadMoreBroadcasts,
  117. refreshBroadcasts,
  118. updateBroadcast,
  119. removeBroadcast,
  120. };
  121. return (
  122. <BroadcastContext.Provider value={value}>
  123. {children}
  124. </BroadcastContext.Provider>
  125. );
  126. }
  127. // Context 사용을 위한 커스텀 훅
  128. export function useBroadcastContext() {
  129. const context = useContext(BroadcastContext);
  130. if (!context) {
  131. throw new Error('useBroadcastContext must be used within a BroadcastProvider');
  132. }
  133. return context;
  134. }