import Layout from "@/components/Layout"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { cn } from "@/lib/utils"; import { useEffect, useMemo, useState } from "react"; import { useAuth } from "@/contexts/AuthContext"; import { aethexToast } from "@/lib/aethex-toast"; import { Sparkles, Lock, Gift, Rocket, Target, Flame, Eye, CheckCircle2, TimerReset, } from "lucide-react"; import Timeline from "@/components/roadmap/Timeline"; import GalaxyMap from "@/components/roadmap/GalaxyMap"; import Achievements from "@/components/roadmap/Achievements"; import VoteWidget from "@/components/roadmap/VoteWidget"; interface Quest { id: string; title: string; xp: number; phase: "now" | "month1" | "month2" | "month3"; description: string; } interface Peek { id: string; title: string; phase: Quest["phase"]; teaser: string; image?: string; } const QUESTS: Quest[] = [ { id: "realm-gating", title: "Finalize realm gating", xp: 120, phase: "now", description: "Tight access across routes with glossy redirects.", }, { id: "nav-ia", title: "Unify navigation", xp: 80, phase: "now", description: "Consistent top-level labels, fewer detours.", }, { id: "mentor-admin", title: "Mentorship admin flows", xp: 100, phase: "now", description: "Accept / reject, filters, analytics.", }, { id: "mentor-polish", title: "Mentor directory polish", xp: 120, phase: "month1", description: "Filters, profiles, and smoother requests.", }, { id: "featured-studios", title: "Featured studios persistence", xp: 90, phase: "month1", description: "Curation + partner spotlight.", }, { id: "blog-seo", title: "Blog editor + SEO", xp: 130, phase: "month1", description: "Meta/OG, list pages, Supabase sync.", }, { id: "opps-tooling", title: "Opportunities tooling", xp: 140, phase: "month2", description: "Applicant review, statuses, filters.", }, { id: "pricing-funnels", title: "Engage/pricing funnels", xp: 120, phase: "month2", description: "Plans and conversion events.", }, { id: "observability", title: "Observability + Sentry", xp: 110, phase: "month2", description: "Errors, alerts, status surfacing.", }, { id: "collab-teams", title: "Teams & projects enhancements", xp: 150, phase: "month3", description: "Membership, board UX, notifications.", }, { id: "advanced-mentoring", title: "Advanced mentoring flows", xp: 150, phase: "month3", description: "Availability, pricing, scheduling hooks.", }, { id: "public-roadmap", title: "Public roadmap page", xp: 100, phase: "month3", description: "This page—interactive and fun.", }, ]; const PEEKS: Peek[] = [ { id: "peek-1", title: "Squads mode UI", phase: "month1", teaser: "Form elite pods, tackle quests, earn badges.", image: "https://images.unsplash.com/photo-1518779578993-ec3579fee39f?q=80&w=1600&auto=format&fit=crop", }, { id: "peek-2", title: "Realtime collab canvas", phase: "month2", teaser: "Sketch systems and flows together, live.", image: "https://images.unsplash.com/photo-1542831371-29b0f74f9713?q=80&w=1600&auto=format&fit=crop", }, { id: "peek-3", title: "Mentor marketplace", phase: "month3", teaser: "Book sessions, verified tracks, loot drops.", image: "https://images.unsplash.com/photo-1553877522-43269d4ea984?q=80&w=1600&auto=format&fit=crop", }, ]; const storageKey = "aethex_roadmap_unlocks_v1"; export default function Roadmap() { const [claimed, setClaimed] = useState>({}); const [unlocked, setUnlocked] = useState>({}); const [focusedPhase, setFocusedPhase] = useState(null); const { user } = useAuth(); useEffect(() => { try { const raw = localStorage.getItem(storageKey); if (raw) setUnlocked(JSON.parse(raw)); } catch {} }, []); useEffect(() => { try { localStorage.setItem(storageKey, JSON.stringify(unlocked)); } catch {} }, [unlocked]); const totalXp = useMemo(() => QUESTS.reduce((s, q) => s + q.xp, 0), []); const earnedXp = useMemo( () => QUESTS.reduce((s, q) => s + (claimed[q.id] ? q.xp : 0), 0), [claimed], ); const progress = Math.min(100, Math.round((earnedXp / totalXp) * 100)); const phaseTotals = useMemo(() => { const res: Record< string, { total: number; earned: number; count: number } > = {}; for (const q of QUESTS) { const key = q.phase; res[key] = res[key] || { total: 0, earned: 0, count: 0 }; res[key].total += q.xp; res[key].count += 1; if (claimed[q.id]) res[key].earned += q.xp; } return res; }, [claimed]); const phaseClaims: Record = useMemo(() => { const res: Record = {}; for (const q of QUESTS) { if (claimed[q.id]) res[q.phase] = (res[q.phase] || 0) + 1; } return res; }, [claimed]); const toggleClaim = (id: string) => setClaimed((m) => ({ ...m, [id]: !m[id] })); const toggleUnlock = (id: string) => { if (!user) { try { aethexToast.info({ title: "Sign in required", description: "Create an account to unlock Dev Drops and save progress.", }); } catch {} return; } setUnlocked((m) => ({ ...m, [id]: !m[id] })); }; const PhaseIcon: Record = { now: Target, month1: Flame, month2: Rocket, month3: Sparkles, }; return (
Roadmap

The AeThex Roadmap

Follow along, earn XP, and unlock sneak peeks. New drops roll out regularly.

Community XP

{earnedXp} / {totalXp} XP

Now Next Later Legendary
({ id: id as Quest["phase"], label: id === "now" ? "Now" : id === "month1" ? "Month 1" : id === "month2" ? "Month 2" : "Month 3", percent: phaseTotals[id]?.total ? Math.round( (phaseTotals[id].earned / phaseTotals[id].total) * 100, ) : 0, }))} onSelect={(id) => setFocusedPhase(id)} /> ({ id: q.id, title: q.title, phase: q.phase, xp: q.xp, claimed: !!claimed[q.id], }))} onSelectPhase={(p) => setFocusedPhase(p)} onToggleClaim={(id) => toggleClaim(id)} />
{/* Phases */}
{(focusedPhase ? [focusedPhase] : ["now", "month1", "month2", "month3"] ).map((phase) => { const Icon = PhaseIcon[phase] || Target; const items = QUESTS.filter((q) => q.phase === phase); const title = phase === "now" ? "Now" : phase === "month1" ? "Month 1" : phase === "month2" ? "Month 2" : "Month 3"; return (
{title}
{items.length} quests
{items.map((q) => (
{q.title}
{q.description}
{q.xp} XP
))}
); })}
{/* Sneak peeks */}
Sneak peeks

Dev Drops

Unlock previews as we get closer. Collect them all.

{PEEKS.map((p) => (
{p.title} {!unlocked[p.id] && (
Locked
)}
{p.title}
{p.teaser}
{p.phase === "now" ? "Now" : p.phase === "month1" ? "Month 1" : p.phase === "month2" ? "Month 2" : "Month 3"}
))}
({ id: p.id, label: p.title }))} />
); }