From bc12238937436daa0060db20114ee9d570098cf1 Mon Sep 17 00:00:00 2001 From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com> Date: Sun, 21 Dec 2025 02:53:33 -0800 Subject: [PATCH] feat(frontend): Implement Onboarding Welcome Flow --- frontend/app/welcome/page.tsx | 241 ++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 frontend/app/welcome/page.tsx diff --git a/frontend/app/welcome/page.tsx b/frontend/app/welcome/page.tsx new file mode 100644 index 0000000..34f5b00 --- /dev/null +++ b/frontend/app/welcome/page.tsx @@ -0,0 +1,241 @@ +"use client" + +import { useState } from "react" +import { motion, AnimatePresence } from "framer-motion" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Card, CardContent, CardFooter, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" +import { Switch } from "@/components/ui/switch" +import { PartyPopper, UserCircle, Settings, CheckCircle2, ArrowRight, ArrowLeft } from "lucide-react" +import { useRouter } from "next/navigation" +import { getApiUrl } from "@/lib/api-config" + +const STEPS = [ + { + id: "intro", + title: "Welcome to Elmeg", + description: "Let's get you set up to discover and track your favorite shows.", + icon: PartyPopper + }, + { + id: "profile", + title: "Create Your Profile", + description: "How should we call you in the community?", + icon: UserCircle + }, + { + id: "preferences", + title: "Customize Experience", + description: "Choose how you want to interact with the platform.", + icon: Settings + }, + { + id: "finish", + title: "You're All Set!", + description: "Ready to dive in?", + icon: CheckCircle2 + } +] + +export default function WelcomePage() { + const router = useRouter() + const [currentStep, setCurrentStep] = useState(0) + const [loading, setLoading] = useState(false) + + // Form State + const [username, setUsername] = useState("") + const [displayName, setDisplayName] = useState("") + const [wikiMode, setWikiMode] = useState(false) + const [publicProfile, setPublicProfile] = useState(true) + + const handleNext = async () => { + if (currentStep === STEPS.length - 1) { + router.push("/profile") // Redirect to Dashboard + return + } + + // Validation & Saving per step + if (currentStep === 1) { + if (!username) return alert("Username required") + setLoading(true) + try { + const token = localStorage.getItem("token") + const res = await fetch(`${getApiUrl()}/users/me`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + username, + display_name: displayName || username + }) + }) + if (!res.ok) throw new Error("Failed to save profile") + } catch (err) { + console.error(err) + alert("Failed to save profile. Username might be taken.") + setLoading(false) + return + } + setLoading(false) + } else if (currentStep === 2) { + setLoading(true) + try { + const token = localStorage.getItem("token") + const res = await fetch(`${getApiUrl()}/users/me/preferences`, { + method: "PATCH", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + wiki_mode: wikiMode, + // If wikiMode is true, hide social stuff + show_comments: !wikiMode, + show_ratings: !wikiMode + }) + }) + if (!res.ok) throw new Error("Failed to save preferences") + } catch (err) { + console.error(err) + setLoading(false) + return + } + setLoading(false) + } + + setCurrentStep(prev => prev + 1) + } + + const handleBack = () => { + setCurrentStep(prev => Math.max(0, prev - 1)) + } + + const StepIcon = STEPS[currentStep].icon + + return ( +
+ + +
+ +
+ {STEPS[currentStep].title} + {STEPS[currentStep].description} +
+ + + + + {currentStep === 0 && ( +
+

+ We're glad you're here. This quick setup will help us personalize your experience. +

+
+ )} + + {currentStep === 1 && ( +
+
+ + setUsername(e.target.value)} + /> +

Unique handle for mentions and profile URL.

+
+
+ + setDisplayName(e.target.value)} + /> +
+
+ )} + + {currentStep === 2 && ( +
+
+
+ +

+ Hide all social features (comments, ratings, leaderboards). Just data. +

+
+ +
+ +
+
+ +

+ Allow others to see your stats and attendence. +

+
+ +
+

You can change these later in settings.

+
+ )} + + {currentStep === 3 && ( +
+

Your profile is ready!

+
+

@{username}

+

{wikiMode ? "Wiki Mode: ON" : "Community Mode: ON"}

+
+
+ )} +
+
+
+ + + + + + +
+ + {/* Progress Dots */} +
+ {STEPS.map((_, index) => ( +
+ ))} +
+
+ ) +}