| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- 'use client';
- import { useState } from 'react';
- import type { BroadcastInfo } from '@/types/broadcast';
- interface DonationModalProps {
- isOpen: boolean;
- onClose: () => void;
- broadcast: BroadcastInfo;
- onDonationComplete?: (donationData: {
- amount: number;
- message: string;
- isAnonymous: boolean;
- username: string;
- }) => void;
- }
- export default function DonationModal({ isOpen, onClose, broadcast, onDonationComplete }: DonationModalProps) {
- const [selectedAmount, setSelectedAmount] = useState<number | null>(null);
- const [customAmount, setCustomAmount] = useState('');
- const [message, setMessage] = useState('');
- const [isAnonymous, setIsAnonymous] = useState(false);
- const presetAmounts = [1000, 3000, 5000, 10000, 20000, 50000];
- if (!isOpen) return null;
- const handleDonation = () => {
- const amount = selectedAmount || parseInt(customAmount);
- // 금액 유효성 검사 강화
- if (!amount || isNaN(amount) || amount < 1000) {
- alert('최소 후원 금액은 1,000원입니다.');
- return;
- }
- // 1,000원 단위로 반올림 (999원 입력 시 1,000원으로 조정)
- const roundedAmount = Math.max(1000, Math.round(amount / 1000) * 1000);
- if (roundedAmount !== amount) {
- alert(`입력하신 금액이 ${roundedAmount.toLocaleString()}원으로 조정되었습니다.`);
- }
- // 후원 처리 로직 (실제로는 결제 API 연동)
- const donationData = {
- broadcastId: broadcast.id,
- channel: broadcast.channel,
- amount: roundedAmount,
- message: message.trim(),
- isAnonymous,
- timestamp: new Date().toISOString()
- };
- console.log('후원 정보:', donationData);
- // 채팅창에 후원 메시지 추가
- if (onDonationComplete) {
- onDonationComplete({
- amount: roundedAmount,
- message: message.trim() || '후원해주셔서 감사합니다!',
- isAnonymous,
- username: isAnonymous ? '익명' : '나'
- });
- }
- alert(`${roundedAmount.toLocaleString()}원 후원이 완료되었습니다! 감사합니다.`);
- onClose();
- // 폼 초기화
- setSelectedAmount(null);
- setCustomAmount('');
- setMessage('');
- setIsAnonymous(false);
- };
- return (
- <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4">
- <div className="bg-gray-800 rounded-2xl max-w-md w-full max-h-[90vh] overflow-y-auto">
- {/* 헤더 */}
- <div className="bg-gradient-to-r from-yellow-500 to-orange-500 p-6 rounded-t-2xl">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-white text-xl font-bold">후원하기</h2>
- <p className="text-white/80 text-sm">{broadcast.channel}님을 응원해주세요!</p>
- </div>
- <button
- onClick={onClose}
- className="text-white/80 hover:text-white transition-colors"
- >
- <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
- </svg>
- </button>
- </div>
- </div>
- <div className="p-6 space-y-6">
- {/* 금액 선택 */}
- <div>
- <h3 className="text-white font-semibold mb-3">후원 금액 선택</h3>
- <div className="grid grid-cols-3 gap-2 mb-4">
- {presetAmounts.map((amount) => (
- <button
- key={amount}
- onClick={() => {
- setSelectedAmount(amount);
- setCustomAmount('');
- }}
- className={`p-3 rounded-lg border text-center transition-all ${
- selectedAmount === amount
- ? 'bg-yellow-500 border-yellow-500 text-white'
- : 'bg-gray-700 border-gray-600 text-gray-300 hover:border-yellow-500'
- }`}
- >
- {amount.toLocaleString()}원
- </button>
- ))}
- </div>
- {/* 직접 입력 */}
- <div>
- <label className="block text-gray-300 text-sm mb-2">직접 입력 (1,000원 단위)</label>
- <input
- type="number"
- value={customAmount}
- onChange={(e) => {
- const value = e.target.value;
- // 1,000원 단위로만 입력 허용
- if (value === '' || (parseInt(value) >= 1000 && parseInt(value) % 1000 === 0)) {
- setCustomAmount(value);
- setSelectedAmount(null);
- }
- }}
- placeholder="1,000원 이상 (천원 단위)"
- min="1000"
- step="1000"
- className="w-full bg-gray-700 text-white px-3 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-500"
- />
- <div className="text-xs text-gray-400 mt-1">
- * 1,000원 단위로만 입력 가능합니다
- </div>
- </div>
- </div>
- {/* 후원 메시지 */}
- <div>
- <h3 className="text-white font-semibold mb-3">후원 메시지 (선택)</h3>
- <textarea
- value={message}
- onChange={(e) => setMessage(e.target.value)}
- placeholder="스트리머에게 전할 메시지를 입력해주세요..."
- maxLength={100}
- rows={3}
- className="w-full bg-gray-700 text-white px-3 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-yellow-500 resize-none"
- />
- <div className="text-right text-xs text-gray-400 mt-1">
- {message.length}/100
- </div>
- </div>
- {/* 익명 후원 옵션 */}
- <div className="flex items-center space-x-3">
- <input
- type="checkbox"
- id="anonymous"
- checked={isAnonymous}
- onChange={(e) => setIsAnonymous(e.target.checked)}
- className="w-4 h-4 text-yellow-500 bg-gray-700 border-gray-600 rounded focus:ring-yellow-500"
- />
- <label htmlFor="anonymous" className="text-gray-300 text-sm">
- 익명으로 후원하기
- </label>
- </div>
- {/* 후원 금액 요약 */}
- <div className="bg-gray-700 rounded-lg p-4">
- <div className="flex justify-between items-center text-white">
- <span>후원 금액:</span>
- <span className="text-xl font-bold text-yellow-400">
- {(selectedAmount || parseInt(customAmount) || 0).toLocaleString()}원
- </span>
- </div>
- </div>
- {/* 후원 버튼 */}
- <button
- onClick={handleDonation}
- disabled={!selectedAmount && !customAmount}
- className="w-full bg-gradient-to-r from-yellow-500 to-orange-500 hover:from-yellow-600 hover:to-orange-600 disabled:from-gray-600 disabled:to-gray-600 text-white font-bold py-4 px-6 rounded-lg transition-all duration-200 transform hover:scale-105 disabled:transform-none disabled:cursor-not-allowed flex items-center justify-center space-x-2"
- >
- <span>후원하기</span>
- </button>
- {/* 주의사항 */}
- <div className="text-xs text-gray-400 text-center space-y-1">
- <p>• 후원은 취소가 불가능합니다.</p>
- <p>• 최소 후원 금액은 1,000원입니다.</p>
- <p>• 후원 메시지는 스트리머와 모든 시청자에게 공개됩니다.</p>
- </div>
- </div>
- </div>
- </div>
- );
- }
|