import { useEffect, useMemo, useState } from "react"; import { useNavigate, useParams, Link } from "react-router-dom"; import Layout from "@/components/Layout"; import LoadingScreen from "@/components/LoadingScreen"; import PassportSummary from "@/components/passport/PassportSummary"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; import { aethexUserService, aethexAchievementService, aethexProjectService, type AethexUserProfile, type AethexAchievement, } from "@/lib/aethex-database-adapter"; import { useAuth } from "@/contexts/AuthContext"; import FourOhFourPage from "@/pages/404"; import { Clock, Rocket, Target, ExternalLink, Award } from "lucide-react"; interface ProjectPreview { id: string; title: string; status: string; description?: string | null; created_at?: string; } const formatDate = (value?: string | null) => { if (!value) return "Recent"; const date = new Date(value); if (Number.isNaN(date.getTime())) return "Recent"; return new Intl.DateTimeFormat(undefined, { dateStyle: "medium", }).format(date); }; const ProfilePassport = () => { const params = useParams<{ id?: string }>(); const navigate = useNavigate(); const { user, linkedProviders } = useAuth(); const [profile, setProfile] = useState< (AethexUserProfile & { email?: string | null }) | null >(null); const [achievements, setAchievements] = useState([]); const [projects, setProjects] = useState([]); const [interests, setInterests] = useState([]); const [loading, setLoading] = useState(true); const [notFound, setNotFound] = useState(false); const targetUserId = useMemo(() => { if (params.id === "me" || !params.id) { return user?.id ?? null; } return params.id; }, [params.id, user?.id]); const isSelf = user?.id && profile?.id ? user.id === profile.id : false; useEffect(() => { if (!targetUserId) { if (!user) { navigate("/login"); } setLoading(false); return; } const loadProfile = async () => { try { setLoading(true); const [profileData, achievementList, interestList, projectList] = await Promise.all([ params.id === "me" && profile && profile.id === targetUserId ? Promise.resolve(profile) : aethexUserService.getProfileById(targetUserId), aethexAchievementService.getUserAchievements(targetUserId), aethexUserService.getUserInterests(targetUserId), aethexProjectService.getUserProjects(targetUserId).catch(() => []), ]); if (!profileData) { setNotFound(true); return; } setProfile(profileData as any); setAchievements(achievementList ?? []); setInterests(interestList ?? []); setProjects( (projectList ?? []).slice(0, 4).map((project: any) => ({ id: project.id, title: project.title, status: project.status, description: project.description, created_at: project.created_at, })), ); setNotFound(false); } catch (error) { console.error("Failed to load passport", error); setNotFound(true); } finally { setLoading(false); } }; loadProfile(); // We intentionally exclude profile from dependencies to avoid refetch loops when local state updates // eslint-disable-next-line react-hooks/exhaustive-deps }, [targetUserId, params.id]); if (loading) { return ; } if (notFound || !profile) { return ; } const passportInterests = interests.length ? interests : ((profile as any)?.interests as string[]) || []; return (
{projects.length > 0 && (

Highlighted missions

A snapshot of what this creator has shipped inside AeThex.

{isSelf && ( )}
{projects.map((project) => (
{project.title} {project.description || "AeThex project"}
{project.status?.replace("_", " ") ?? "active"}
{" "} {formatDate(project.created_at)}
))}
)}

Achievements

Passport stamps earned across AeThex experiences.

{isSelf && ( {achievements.length}{" "} badges )}
{achievements.length === 0 ? ( No achievements yet. Complete onboarding and participate in missions to earn AeThex badges. ) : (
{achievements.map((achievement) => (
{achievement.icon || "🏅"}

{achievement.name}

{achievement.description || "AeThex honor"}

XP Reward • {achievement.xp_reward ?? 0} Passport stamped
))}
)}

Stay connected

Reach out, collaborate, and shape the next AeThex release together.

{isSelf ? ( ) : ( )}
{profile.github_url && ( )} {profile.linkedin_url && ( )} {profile.twitter_url && ( )} {profile.website_url && ( )} {profile.bio && ( {profile.bio} )}
); }; export default ProfilePassport;