/**
* 프로필 페이지
* 프로필 정보 및 마인크래프트 계정 연동
*/
import React, { useState, useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import { ArrowLeft, Copy, Check, Gamepad2, Link as LinkIcon, Unlink, RefreshCw, User, Mail } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
export default function ProfilePage() {
const navigate = useNavigate();
const { user, isLoggedIn, loading, checkAuth } = useAuth();
const [linkStatus, setLinkStatus] = useState(null);
const [linkToken, setLinkToken] = useState(null);
const [command, setCommand] = useState('');
const [copied, setCopied] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [polling, setPolling] = useState(false);
const [showUnlinkDialog, setShowUnlinkDialog] = useState(false);
// 로그인 체크 (loading 완료 후에만)
useEffect(() => {
if (!loading && !isLoggedIn) {
navigate('/login');
}
}, [loading, isLoggedIn, navigate]);
// 연동 상태 확인
useEffect(() => {
fetchLinkStatus();
}, []);
// 폴링 (연동 대기 중일 때)
useEffect(() => {
if (!polling) return;
const interval = setInterval(async () => {
const status = await fetchLinkStatus();
if (status?.linked) {
setPolling(false);
setLinkToken(null);
setCommand('');
// 유저 정보 새로고침
await checkAuth();
}
}, 3000);
return () => clearInterval(interval);
}, [polling]);
// 연동 대기 중 새로고침 방지 + 토큰 무효화
useEffect(() => {
if (!linkToken) return;
const handleBeforeUnload = (e) => {
// 토큰 무효화 API 호출 (sendBeacon으로 페이지 이탈 전 전송)
const token = localStorage.getItem('token');
navigator.sendBeacon('/link/cancel', JSON.stringify({ authToken: token }));
e.preventDefault();
e.returnValue = '연동이 진행 중입니다. 페이지를 떠나시겠습니까?';
return e.returnValue;
};
window.addEventListener('beforeunload', handleBeforeUnload);
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
}, [linkToken]);
const fetchLinkStatus = async () => {
try {
const token = localStorage.getItem('token');
const res = await fetch('/link/status', {
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await res.json();
setLinkStatus(data);
return data;
} catch (error) {
console.error('연동 상태 확인 실패:', error);
return null;
}
};
const handleRequestLink = async () => {
setIsLoading(true);
try {
const token = localStorage.getItem('token');
const res = await fetch('/link/request', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }
});
const data = await res.json();
if (data.linked) {
setLinkStatus({ linked: true, minecraftName: data.minecraftName });
} else {
setLinkToken(data.token);
setCommand(data.command);
setPolling(true);
}
} catch (error) {
console.error('연동 요청 실패:', error);
} finally {
setIsLoading(false);
}
};
const handleCopyCommand = () => {
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const handleUnlink = async () => {
try {
const token = localStorage.getItem('token');
await fetch('/link/unlink', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` }
});
setLinkStatus({ linked: false });
setShowUnlinkDialog(false);
await checkAuth();
} catch (error) {
console.error('연동 해제 실패:', error);
}
};
if (!user) return null;
return (
{/* 헤더 */}
{/* 프로필 정보 카드 */}
기본 정보

{ e.target.src = 'https://via.placeholder.com/96'; }}
/>
{/* 마인크래프트 연동 카드 */}
마인크래프트 계정 연동
{linkStatus?.linked ? (
// 연동 완료 상태
연동 완료
마인크래프트 계정: {linkStatus.minecraftName}
) : linkToken ? (
// 연동 대기 상태
마인크래프트에서 아래 명령어를 입력하세요:
{command}
연동 대기 중... (10분 후 만료)
) : (
// 연동 안됨 상태
마인크래프트 계정을 연동하면 게임 내 닉네임과 스킨이 프로필에 적용됩니다.
)}
{/* 연동 해제 다이얼로그 */}
{showUnlinkDialog && (
<>
setShowUnlinkDialog(false)}
/>
연동 해제
마인크래프트 계정 연동을 해제하시겠습니까?
>
)}
);
}