| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- 'use client';
- import { useState, useEffect, useRef } from 'react';
- import type { BroadcastInfo } from '@/types/broadcast';
- import DonationModal from './DonationModal';
- interface ChatMessage {
- id: string;
- username: string;
- message: string;
- timestamp: Date;
- isStreamer?: boolean;
- isDonation?: boolean;
- donationAmount?: number;
- }
- interface ChatWindowProps {
- broadcast: BroadcastInfo;
- }
- export default function ChatWindow({ broadcast }: ChatWindowProps) {
- const [messages, setMessages] = useState<ChatMessage[]>([]);
- const [inputMessage, setInputMessage] = useState('');
- const [isConnected, setIsConnected] = useState(true);
- const [isDonationModalOpen, setIsDonationModalOpen] = useState(false);
- const chatEndRef = useRef<HTMLDivElement>(null);
- // 채팅 메시지 더미 데이터
- const dummyMessages: ChatMessage[] = [
- {
- id: '1',
- username: broadcast.channel,
- message: '안녕하세요! 방송 시작합니다 🎉',
- timestamp: new Date(Date.now() - 300000),
- isStreamer: true
- },
- {
- id: '2',
- username: '시청자123',
- message: '안녕하세요~!',
- timestamp: new Date(Date.now() - 250000)
- },
- {
- id: '3',
- username: '라이브러버',
- message: '오늘도 재밌는 방송 부탁드려요!',
- timestamp: new Date(Date.now() - 200000)
- },
- {
- id: '4',
- username: '후원왕',
- message: '응원합니다! 화이팅!',
- timestamp: new Date(Date.now() - 150000),
- isDonation: true,
- donationAmount: 5000
- },
- {
- id: '5',
- username: '열심팬',
- message: 'ㅋㅋㅋㅋㅋ 재밌네요',
- timestamp: new Date(Date.now() - 100000)
- }
- ];
- // 실시간 채팅 시뮬레이션
- useEffect(() => {
- setMessages(dummyMessages);
- const interval = setInterval(() => {
- const randomMessages = [
- '와 대박',
- 'ㅋㅋㅋㅋㅋ',
- '재밌어요!',
- '최고!',
- '👏👏👏',
- '하이~',
- '안녕하세요',
- '오늘 방송 재밌네요',
- '팔로우 했어요!',
- '응원합니다'
- ];
- const randomUsernames = [
- '시청자' + Math.floor(Math.random() * 999),
- '라이브팬' + Math.floor(Math.random() * 999),
- '스트림러버' + Math.floor(Math.random() * 999),
- '채팅왕' + Math.floor(Math.random() * 999)
- ];
- const newMessage: ChatMessage = {
- id: Date.now().toString(),
- username: randomUsernames[Math.floor(Math.random() * randomUsernames.length)],
- message: randomMessages[Math.floor(Math.random() * randomMessages.length)],
- timestamp: new Date(),
- isDonation: Math.random() > 0.9,
- donationAmount: Math.random() > 0.9 ? (Math.floor(Math.random() * 10) + 1) * 1000 : undefined
- };
- setMessages(prev => [...prev.slice(-20), newMessage]);
- }, 3000 + Math.random() * 5000);
- return () => clearInterval(interval);
- }, []);
- // 자동 스크롤
- useEffect(() => {
- chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
- }, [messages]);
- const handleSendMessage = () => {
- if (!inputMessage.trim()) return;
- const newMessage: ChatMessage = {
- id: Date.now().toString(),
- username: '나',
- message: inputMessage,
- timestamp: new Date()
- };
- setMessages(prev => [...prev, newMessage]);
- setInputMessage('');
- };
- const handleKeyPress = (e: React.KeyboardEvent) => {
- if (e.key === 'Enter' && !e.shiftKey) {
- e.preventDefault();
- handleSendMessage();
- }
- };
- const handleDonationComplete = (donationData: {
- amount: number;
- message: string;
- isAnonymous: boolean;
- username: string;
- }) => {
- const donationMessage: ChatMessage = {
- id: Date.now().toString(),
- username: donationData.username,
- message: donationData.message,
- timestamp: new Date(),
- isDonation: true,
- donationAmount: donationData.amount
- };
- setMessages(prev => [...prev, donationMessage]);
- };
- return (
- <div className="h-full flex flex-col bg-white border-l border-gray-200">
- {/* 채팅 헤더 */}
- <div className="bg-white p-4 border-b border-gray-200">
- <div className="flex items-center justify-between">
- <h3 className="text-gray-900 font-bold text-sm">채팅</h3>
- <div className="flex items-center space-x-2">
- <div className={`w-2 h-2 rounded-full ${isConnected ? 'bg-green-400' : 'bg-red-400'}`}></div>
- <span className="text-xs text-gray-500">
- {isConnected ? '연결됨' : '연결 끊김'}
- </span>
- </div>
- </div>
- </div>
- {/* 채팅 메시지 영역 */}
- <div className="flex-1 overflow-y-auto p-3 space-y-2 bg-gray-50">
- {messages.map((message) => (
- <div
- key={message.id}
- className={`${
- message.isDonation
- ? 'bg-amber-50 border border-amber-200 rounded-lg p-2'
- : ''
- }`}
- >
- {/* 후원 메시지 */}
- {message.isDonation && (
- <div className="flex items-center space-x-2 mb-1">
- <span className="text-amber-600 text-xs">💰 후원</span>
- <span className="text-amber-700 text-xs font-bold">
- {message.donationAmount?.toLocaleString()}원
- </span>
- </div>
- )}
- {/* 메시지 내용 */}
- <div className="flex flex-col space-y-1">
- <div className="flex items-start space-x-1">
- <span
- className={`text-xs font-bold flex-shrink-0 ${
- message.isStreamer
- ? 'text-purple-600'
- : message.isDonation
- ? 'text-amber-700'
- : 'text-blue-600'
- }`}
- >
- {message.username}
- {message.isStreamer && (
- <span className="ml-1 text-xs bg-purple-100 text-purple-600 px-1 rounded">스트리머</span>
- )}
- </span>
- </div>
- <p className="text-gray-800 text-sm break-words leading-relaxed">{message.message}</p>
- </div>
- </div>
- ))}
- <div ref={chatEndRef} />
- </div>
- {/* 채팅 입력 영역 */}
- <div className="bg-white p-3 border-t border-gray-200">
- <div className="flex space-x-2 mb-3">
- <input
- type="text"
- value={inputMessage}
- onChange={(e) => setInputMessage(e.target.value)}
- onKeyPress={handleKeyPress}
- placeholder="채팅을 입력하세요..."
- className="flex-1 bg-white border border-gray-300 text-gray-900 px-3 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm"
- maxLength={200}
- />
- <button
- onClick={handleSendMessage}
- disabled={!inputMessage.trim()}
- className="bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed text-white px-4 py-2 rounded-lg transition-colors text-sm font-medium"
- >
- <svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24">
- <path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
- </svg>
- </button>
- </div>
- {/* 후원하기 버튼 */}
- <button
- onClick={() => setIsDonationModalOpen(true)}
- className="w-full bg-black hover:bg-gray-800 text-white font-medium py-3 px-4 rounded-lg transition-colors text-sm"
- >
- 후원하기
- </button>
- </div>
- {/* 후원 모달 */}
- <DonationModal
- isOpen={isDonationModalOpen}
- onClose={() => setIsDonationModalOpen(false)}
- broadcast={broadcast}
- onDonationComplete={handleDonationComplete}
- />
- </div>
- );
- }
|