diff --git a/client/pages/dashboards/GameForgeDashboard.tsx b/client/pages/dashboards/GameForgeDashboard.tsx index abd7f5d2..deadf8b3 100644 --- a/client/pages/dashboards/GameForgeDashboard.tsx +++ b/client/pages/dashboards/GameForgeDashboard.tsx @@ -1,92 +1,311 @@ +import { useState, useEffect, useMemo } from "react"; import { useNavigate } from "react-router-dom"; import Layout from "@/components/Layout"; import { Button } from "@/components/ui/button"; -import { Card, CardContent } from "@/components/ui/card"; -import { Rocket, ArrowRight, Gamepad2, Users, Zap } from "lucide-react"; +import { useAuth } from "@/contexts/AuthContext"; +import { supabase } from "@/lib/supabase"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import LoadingScreen from "@/components/LoadingScreen"; +import { Gamepad2, Users, Clock, CheckCircle, AlertCircle, Rocket, Send, Home } from "lucide-react"; + +const API_BASE = import.meta.env.VITE_API_BASE || ""; export default function GameForgeDashboard() { const navigate = useNavigate(); + const { user, loading: authLoading } = useAuth(); + const [activeTab, setActiveTab] = useState("overview"); + const [sprint, setSprint] = useState(null); + const [team, setTeam] = useState([]); + const [tasks, setTasks] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (!authLoading && user) { + loadDashboardData(); + const interval = setInterval(() => setActiveTab(activeTab), 1000); + return () => clearInterval(interval); + } + }, [user, authLoading]); + + const loadDashboardData = async () => { + try { + setLoading(true); + const { data: { session } } = await supabase.auth.getSession(); + const token = session?.access_token; + if (!token) throw new Error("No auth token"); + + const sprintRes = await fetch(`${API_BASE}/api/gameforge/sprint`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (sprintRes.ok) setSprint(await sprintRes.json()); + + const teamRes = await fetch(`${API_BASE}/api/gameforge/team`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (teamRes.ok) setTeam(await teamRes.json()); + + const tasksRes = await fetch(`${API_BASE}/api/gameforge/tasks`, { + headers: { Authorization: `Bearer ${token}` }, + }); + if (tasksRes.ok) setTasks(await tasksRes.json()); + } catch (error) { + console.error("Failed to load GAMEFORGE data", error); + } finally { + setLoading(false); + } + }; + + const timeRemaining = useMemo(() => { + if (!sprint?.deadline) return null; + const now = new Date(); + const deadline = new Date(sprint.deadline); + const diff = deadline.getTime() - now.getTime(); + const days = Math.floor(diff / (1000 * 60 * 60 * 24)); + const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((diff % (1000 * 60)) / 1000); + return { days, hours, minutes, seconds }; + }, [sprint]); + + const tasksByStatus = { + todo: tasks.filter(t => t.status === "todo"), + inprogress: tasks.filter(t => t.status === "in_progress"), + done: tasks.filter(t => t.status === "done"), + }; + + if (authLoading || loading) { + return ; + } + + if (!user) { + return ( + +
+
+

+ GAMEFORGE Studio +

+

Build, collaborate, ship games

+ +
+
+
+ ); + } return ( -
-
- {/* Header */} -
-
-
-
- -
+
+
+ {sprint ? ( + <> + {/* Active Sprint Header */} +
+

+ Mission Control +

+

Project: {sprint.title}

+ + {/* Countdown Timer */} + {timeRemaining && ( + + +
+

Time Remaining in Sprint

+
+
+

{timeRemaining.days}

+

Days

+
+
+

{String(timeRemaining.hours).padStart(2, '0')}

+

Hours

+
+
+

{String(timeRemaining.minutes).padStart(2, '0')}

+

Minutes

+
+
+

{String(timeRemaining.seconds).padStart(2, '0')}

+

Seconds

+
+
+
+
+
+ )}
-

- GAMEFORGE Project Studio -

-

- This is the future home for your active game sprints, team Kanban boards, and build submissions per our GameForge Plan. -

-
- {/* Coming Soon Card */} - - - {/* Status */} -
-
-

Coming Soon

-
-

- The full bespoke GAMEFORGE dashboard with project management, team boards, and build tracking is currently in development per our Phase 3 Roadmap. -

-
+ {/* Tabs */} + + + Overview + Scope + Team + Tasks + - {/* Guiding CTA */} -
-
-

- - Join the Next Sprint! -

-

- The GAMEFORGE is already active! Go to the FOUNDATION's community hub to apply for a mentor and join the next 1-month game jam. -

+ {/* Overview Tab */} + +
+ + +

Sprint Phase

+

{sprint.phase}

+
+
+ + +

Team Size

+

{team.length}

+
+
+ + +

Tasks Completed

+

{tasksByStatus.done.length}/{tasks.length}

+
+
- -
+ + {/* Submit Build CTA */} + + +

Ready to Ship?

+

Submit your final build for evaluation

+ +
+
+ + + {/* Scope Tab */} + + + + The Scope Anchor (KND-001) + Your north star - prevent feature creep + + +
+

{sprint.gdd || "Game Design Document not available"}

+
+
+
+
+ + {/* Team Tab */} + + + + My Sprint Team + Forge Master + Mentees + + +
+ {team.map((member: any) => ( +
navigate(`/passport/${member.username}`)}> +
+ {member.full_name} +
+

{member.full_name}

+ {member.role === "mentor" ? "🏆 Forge Master" : "Mentee"} +

{member.role_title}

+
+
+
+ ))} +
+
+
+
+ + {/* Tasks Tab - Kanban */} + +
+ {/* To Do */} + + + To Do ({tasksByStatus.todo.length}) + + + {tasksByStatus.todo.length === 0 ? ( +

No tasks

+ ) : ( + tasksByStatus.todo.map((task: any) => ( +
+

{task.title}

+

{task.assigned_to?.full_name}

+
+ )) + )} +
+
+ + {/* In Progress */} + + + In Progress ({tasksByStatus.inprogress.length}) + + + {tasksByStatus.inprogress.length === 0 ? ( +

No tasks

+ ) : ( + tasksByStatus.inprogress.map((task: any) => ( +
+

{task.title}

+

{task.assigned_to?.full_name}

+
+ )) + )} +
+
+ + {/* Done */} + + + Done ({tasksByStatus.done.length}) + + + {tasksByStatus.done.length === 0 ? ( +

No tasks

+ ) : ( + tasksByStatus.done.map((task: any) => ( +
+
+ +
+

{task.title}

+

{task.assigned_to?.full_name}

+
+
+
+ )) + )} +
+
+
+
+ + + ) : ( + + + +

No active sprint. Join one to get started!

+
- - {/* Features Coming */} -
- - -

🎮

-

Active Sprints

-

1-month game development cycles

-
-
- - -

👥

-

Team Collaboration

-

Kanban boards & sprint planning

-
-
- - -

🚀

-

Build Submissions

-

Ship your final game builds

-
-
-
-
+ )}