113 lines
4.0 KiB
TypeScript
113 lines
4.0 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import { useState } from "react";
|
|
import { ThemeToggle } from "@/components/theme-toggle";
|
|
|
|
const INTERESTS = [
|
|
{ id: "fashion", label: "Streetwear", emoji: "👟" },
|
|
{ id: "travel", label: "Travel & Places", emoji: "✈️" },
|
|
{ id: "architecture", label: "Architecture", emoji: "🏛️" },
|
|
{ id: "food", label: "Food & Drink", emoji: "🍔" },
|
|
{ id: "tech", label: "Technology", emoji: "💻" },
|
|
{ id: "art", label: "Digital Art", emoji: "🎨" },
|
|
{ id: "music", label: "Music & Audio", emoji: "🎵" },
|
|
{ id: "nature", label: "Nature", emoji: "🌲" },
|
|
{ id: "fitness", label: "Health & Fitness", emoji: "🏋️" },
|
|
{ id: "cars", label: "Automotive", emoji: "🚗" },
|
|
];
|
|
|
|
export default function OnboardingPage() {
|
|
const [selected, setSelected] = useState<string[]>([]);
|
|
|
|
const toggleInterest = (id: string) => {
|
|
setSelected(prev =>
|
|
prev.includes(id) ? prev.filter(i => i !== id) : [...prev, id]
|
|
);
|
|
};
|
|
|
|
const container = {
|
|
hidden: { opacity: 0 },
|
|
show: {
|
|
opacity: 1,
|
|
transition: {
|
|
staggerChildren: 0.1
|
|
}
|
|
}
|
|
};
|
|
|
|
const item: import("framer-motion").Variants = {
|
|
hidden: { opacity: 0, scale: 0.8, y: 20 },
|
|
show: { opacity: 1, scale: 1, y: 0, transition: { type: "spring", stiffness: 300, damping: 20 } }
|
|
};
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background text-foreground flex flex-col items-center justify-center p-8 relative">
|
|
<div className="absolute top-4 right-4 z-50">
|
|
<ThemeToggle />
|
|
</div>
|
|
|
|
<div className="max-w-4xl w-full z-10 flex flex-col items-center">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
className="text-center space-y-4 mb-12"
|
|
>
|
|
<h1 className="text-5xl font-extrabold tracking-tight">What are you into?</h1>
|
|
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
|
Pick 3 or more topics to personalize your feed. We'll curate the best content just for you.
|
|
</p>
|
|
</motion.div>
|
|
|
|
<motion.div
|
|
variants={container}
|
|
initial="hidden"
|
|
animate="show"
|
|
className="flex flex-wrap justify-center gap-4 max-w-3xl"
|
|
>
|
|
{INTERESTS.map((interest) => {
|
|
const isSelected = selected.includes(interest.id);
|
|
return (
|
|
<motion.button
|
|
key={interest.id}
|
|
variants={item}
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
onClick={() => toggleInterest(interest.id)}
|
|
className={`flex items-center gap-3 px-6 py-4 rounded-full text-lg font-medium transition-all shadow-sm
|
|
${isSelected
|
|
? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 ring-2 ring-primary ring-offset-2 ring-offset-background"
|
|
: "glass hover:bg-white/50 dark:hover:bg-black/50"
|
|
}
|
|
`}
|
|
>
|
|
<span className="text-2xl">{interest.emoji}</span>
|
|
{interest.label}
|
|
</motion.button>
|
|
);
|
|
})}
|
|
</motion.div>
|
|
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: selected.length > 0 ? 1 : 0 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="mt-16"
|
|
>
|
|
<button
|
|
disabled={selected.length < 3}
|
|
onClick={() => window.location.href = "/feed"}
|
|
className={`px-12 py-4 rounded-full font-bold text-lg shadow-xl transition-all ${
|
|
selected.length >= 3
|
|
? "bg-primary text-primary-foreground hover:scale-105 active:scale-95"
|
|
: "bg-muted text-muted-foreground cursor-not-allowed opacity-50"
|
|
}`}
|
|
>
|
|
{selected.length < 3 ? `Pick ${3 - selected.length} more` : "Continue to Feed →"}
|
|
</button>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|