/** * Dashboard Component * 텔레그램 대시보드 관련 상태 및 메서드 */ import { MOCK_SERVERS, MOCK_STATS, MOCK_NOTIFICATIONS } from './config.js'; /** * 대시보드 메서드 생성 */ export function createDashboardMethods() { return { // 대시보드 상태 dashboardMode: false, // true면 대시보드, false면 랜딩 currentView: 'servers', // 'servers' | 'stats' | 'notifications' // 텔레그램 연동 telegram: { isAvailable: false, // 텔레그램 환경인지 user: null, // 사용자 정보 initData: null // 검증용 데이터 }, // 웹 로그인 사용자 (텔레그램 로그인 위젯 사용) webUser: null, // 현재 로그인된 사용자 (텔레그램 또는 웹) get currentUser() { return this.telegram.user || this.webUser; }, // 서버 목록 servers: [], loadingServers: false, // 통계 stats: { totalCost: 0, totalServers: 0, runningServers: 0, costBreakdown: [] }, // 알림 notifications: [], unreadCount: 0, // API 상태 apiLoading: false, apiError: null, // 초기화 (텔레그램 연동 + 대시보드) init() { if (window.Telegram?.WebApp) { const tg = window.Telegram.WebApp; tg.ready(); tg.expand(); this.telegram.isAvailable = true; this.telegram.user = tg.initDataUnsafe.user || null; this.telegram.initData = tg.initData; console.log('[Telegram] Mini App initialized', { user: this.telegram.user, platform: tg.platform }); // 텔레그램 환경이면 대시보드 모드 활성화 this.dashboardMode = true; this.loadDashboard(); console.log('[Telegram] Dashboard mode activated', { isAvailable: this.telegram.isAvailable, hasUser: !!this.telegram.user }); } else { console.log('[Telegram] Running in web browser mode'); } }, // 미니앱 전용 초기화 (/app 페이지용) initMiniApp() { const tg = window.Telegram?.WebApp; // 실제 텔레그램 환경인지 확인 (initData가 있어야 진짜 텔레그램) const isRealTelegram = tg && tg.initData && tg.initData.length > 0; if (isRealTelegram) { tg.ready(); tg.expand(); this.telegram.isAvailable = true; this.telegram.user = tg.initDataUnsafe.user || null; this.telegram.initData = tg.initData; console.log('[MiniApp] Telegram environment detected', { user: this.telegram.user, platform: tg.platform }); // 미니앱은 무조건 대시보드 로드 this.loadDashboard(); } else { console.log('[MiniApp] Not in Telegram environment'); this.telegram.isAvailable = false; // 웹 브라우저: localStorage에서 webUser 복원 const savedUser = localStorage.getItem('anvil_web_user'); if (savedUser) { try { this.webUser = JSON.parse(savedUser); console.log('[MiniApp] Web user restored from localStorage:', this.webUser); this.loadDashboard(); } catch (e) { console.error('[MiniApp] Failed to parse saved user:', e); localStorage.removeItem('anvil_web_user'); // 복원 실패시 로그인 위젯 표시 this.loadTelegramLoginWidget(); } } else { // 로그인 필요 - 텔레그램 로그인 위젯 로드 this.loadTelegramLoginWidget(); } } }, // 텔레그램 로그인 위젯 동적 로드 loadTelegramLoginWidget() { // Alpine이 DOM을 렌더링할 시간을 주기 위해 약간 지연 setTimeout(() => { const container = document.getElementById('telegram-login-container'); if (!container) { console.log('[MiniApp] Login container not found, retrying...'); setTimeout(() => this.loadTelegramLoginWidget(), 100); return; } // 이미 위젯이 있으면 스킵 if (container.querySelector('iframe')) { console.log('[MiniApp] Login widget already loaded'); return; } console.log('[MiniApp] Loading Telegram Login Widget...'); // 텔레그램 위젯 스크립트 동적 생성 const script = document.createElement('script'); script.src = 'https://telegram.org/js/telegram-widget.js?22'; script.setAttribute('data-telegram-login', 'AnvilForgeBot'); script.setAttribute('data-size', 'large'); script.setAttribute('data-radius', '12'); script.setAttribute('data-onauth', 'onTelegramAuth(user)'); script.setAttribute('data-request-access', 'write'); script.async = true; container.appendChild(script); console.log('[MiniApp] Telegram Login Widget script added'); }, 50); }, // 웹 텔레그램 로그인 핸들러 handleWebLogin(user) { console.log('[MiniApp] Web login received:', user); // 사용자 정보 저장 this.webUser = { id: user.id, first_name: user.first_name, last_name: user.last_name || '', username: user.username || '', photo_url: user.photo_url || '', auth_date: user.auth_date }; // localStorage에 저장 (세션 유지) localStorage.setItem('anvil_web_user', JSON.stringify(this.webUser)); console.log('[MiniApp] Web user logged in:', this.webUser); // 대시보드 로드 this.loadDashboard(); }, // 로그아웃 logout() { console.log('[MiniApp] Logging out...'); // webUser 초기화 this.webUser = null; localStorage.removeItem('anvil_web_user'); // 서버/통계/알림 초기화 this.servers = []; this.stats = { totalCost: 0, totalServers: 0, runningServers: 0, costBreakdown: [] }; this.notifications = []; this.unreadCount = 0; console.log('[MiniApp] Logged out successfully'); }, // 대시보드 초기 로드 async loadDashboard() { console.log('[Dashboard] Loading dashboard data...'); await Promise.all([ this.fetchServers(), this.fetchStats(), this.fetchNotifications() ]); }, // 서버 목록 조회 async fetchServers() { this.loadingServers = true; this.apiError = null; try { // TODO: 실제 API 호출로 교체 // const response = await fetch('/api/servers', { // headers: { 'X-Telegram-Init-Data': this.telegram.initData } // }); // this.servers = await response.json(); // Mock 데이터 사용 await new Promise(resolve => setTimeout(resolve, 500)); this.servers = [...MOCK_SERVERS]; console.log('[Dashboard] Servers loaded:', this.servers.length); } catch (error) { console.error('[Dashboard] Failed to fetch servers:', error); this.apiError = '서버 목록을 불러오는데 실패했습니다.'; } finally { this.loadingServers = false; } }, // 통계 조회 async fetchStats() { try { // TODO: 실제 API 호출로 교체 await new Promise(resolve => setTimeout(resolve, 300)); this.stats = { ...MOCK_STATS }; console.log('[Dashboard] Stats loaded:', this.stats); } catch (error) { console.error('[Dashboard] Failed to fetch stats:', error); } }, // 알림 조회 async fetchNotifications() { try { // TODO: 실제 API 호출로 교체 await new Promise(resolve => setTimeout(resolve, 400)); this.notifications = [...MOCK_NOTIFICATIONS]; this.unreadCount = this.notifications.filter(n => !n.read).length; console.log('[Dashboard] Notifications loaded:', this.notifications.length); } catch (error) { console.error('[Dashboard] Failed to fetch notifications:', error); } }, // 서버 시작 async startServer(serverId) { const server = this.servers.find(s => s.id === serverId); if (!server) return; console.log('[Dashboard] Starting server:', serverId); this.apiLoading = true; try { // TODO: 실제 API 호출로 교체 await new Promise(resolve => setTimeout(resolve, 1000)); server.status = 'running'; this.stats.runningServers++; console.log('[Dashboard] Server started:', serverId); } catch (error) { console.error('[Dashboard] Failed to start server:', error); alert('서버를 시작하는데 실패했습니다.'); } finally { this.apiLoading = false; } }, // 서버 중지 async stopServer(serverId) { const server = this.servers.find(s => s.id === serverId); if (!server) return; console.log('[Dashboard] Stopping server:', serverId); this.apiLoading = true; try { // TODO: 실제 API 호출로 교체 await new Promise(resolve => setTimeout(resolve, 1000)); server.status = 'stopped'; this.stats.runningServers--; console.log('[Dashboard] Server stopped:', serverId); } catch (error) { console.error('[Dashboard] Failed to stop server:', error); alert('서버를 중지하는데 실패했습니다.'); } finally { this.apiLoading = false; } }, // 서버 삭제 async deleteServer(serverId) { if (!confirm('정말로 이 서버를 삭제하시겠습니까?')) return; console.log('[Dashboard] Deleting server:', serverId); this.apiLoading = true; try { // TODO: 실제 API 호출로 교체 await new Promise(resolve => setTimeout(resolve, 800)); const serverIndex = this.servers.findIndex(s => s.id === serverId); if (serverIndex !== -1) { const deletedServer = this.servers[serverIndex]; this.servers.splice(serverIndex, 1); // 통계 업데이트 this.stats.totalServers--; this.stats.totalCost -= deletedServer.cost; if (deletedServer.status === 'running') { this.stats.runningServers--; } console.log('[Dashboard] Server deleted:', serverId); } } catch (error) { console.error('[Dashboard] Failed to delete server:', error); alert('서버를 삭제하는데 실패했습니다.'); } finally { this.apiLoading = false; } }, // 모든 알림 읽음 처리 markAllRead() { this.notifications.forEach(n => n.read = true); this.unreadCount = 0; console.log('[Dashboard] All notifications marked as read'); }, // 뷰 전환 switchView(view) { this.currentView = view; console.log('[Dashboard] View switched to:', view); } }; }