elmeg-demo/frontend/app/not-found.tsx

127 lines
5.4 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { Home, Search, Shuffle, ArrowLeft, Music, Disc3 } from "lucide-react"
import { useState, useEffect } from "react"
const GOOSE_QUOTES = [
"Looks like this page flew the coop!",
"Honk if you're lost too!",
"This page has migrated to parts unknown.",
"The jam you seek is not in this location.",
"404: Page not found. But hey, at least the vibes are good.",
"This URL took a wrong turn at Tumble.",
"Flodown? More like FlowGONE.",
"Seems this page is still in the Dripfield.",
"The set break got a little too long...",
"Whoops! Someone put this page in the wrong set.",
]
const SONG_SUGGESTIONS = [
{ title: "Tumble", slug: "tumble" },
{ title: "Arcadia", slug: "arcadia" },
{ title: "Hungersite", slug: "hungersite" },
{ title: "Atlas Dogs", slug: "atlas-dogs" },
{ title: "Rockdale", slug: "rockdale" },
]
export default function NotFound() {
const [quote, setQuote] = useState("")
const [suggestion, setSuggestion] = useState(SONG_SUGGESTIONS[0])
const [isSpinning, setIsSpinning] = useState(false)
useEffect(() => {
// Random quote on mount
setQuote(GOOSE_QUOTES[Math.floor(Math.random() * GOOSE_QUOTES.length)])
setSuggestion(SONG_SUGGESTIONS[Math.floor(Math.random() * SONG_SUGGESTIONS.length)])
}, [])
const shuffleQuote = () => {
setIsSpinning(true)
setTimeout(() => {
setQuote(GOOSE_QUOTES[Math.floor(Math.random() * GOOSE_QUOTES.length)])
setSuggestion(SONG_SUGGESTIONS[Math.floor(Math.random() * SONG_SUGGESTIONS.length)])
setIsSpinning(false)
}, 300)
}
return (
<div className="flex flex-col items-center justify-center min-h-[70vh] text-center px-4">
{/* Animated Goose/Music Icon */}
<div className="relative mb-6 group cursor-pointer" onClick={shuffleQuote}>
<div className={`transition-transform duration-300 ${isSpinning ? 'rotate-180 scale-110' : ''}`}>
<Disc3 className="h-32 w-32 text-primary/20 group-hover:text-primary/40 transition-colors" />
</div>
<span className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-6xl group-hover:scale-110 transition-transform">
🦆
</span>
</div>
{/* 404 Header */}
<div className="mb-4">
<span className="text-8xl font-black bg-gradient-to-r from-primary via-purple-500 to-pink-500 bg-clip-text text-transparent">
404
</span>
</div>
{/* Playful Quote */}
<p className="text-xl font-medium mb-2 max-w-md min-h-[2em] transition-opacity duration-300"
style={{ opacity: isSpinning ? 0 : 1 }}>
{quote}
</p>
<p className="text-muted-foreground text-sm mb-8">
Click the goose for a new message
</p>
{/* Action Buttons */}
<div className="flex flex-wrap gap-3 justify-center mb-8">
<Link href="/">
<Button size="lg" className="gap-2 font-semibold">
<Home className="h-4 w-4" />
Back to Safety
</Button>
</Link>
<Link href="/shows">
<Button variant="outline" size="lg" className="gap-2">
<Search className="h-4 w-4" />
Find a Show
</Button>
</Link>
<Button variant="ghost" size="lg" className="gap-2" onClick={shuffleQuote}>
<Shuffle className="h-4 w-4" />
Shuffle Quote
</Button>
</div>
{/* Song Suggestion Card */}
<div className="bg-muted/50 rounded-xl p-6 max-w-sm border border-border/50">
<p className="text-sm text-muted-foreground mb-3">
While you&apos;re here, maybe check out:
</p>
<Link
href={`/songs/${suggestion.slug}`}
className="flex items-center gap-3 p-3 rounded-lg bg-background hover:bg-primary/5 border border-border/50 transition-all hover:border-primary/20 group"
>
<div className="h-10 w-10 rounded-lg bg-primary/10 flex items-center justify-center group-hover:bg-primary/20 transition-colors">
<Music className="h-5 w-5 text-primary" />
</div>
<div className="text-left">
<p className="font-semibold group-hover:text-primary transition-colors">{suggestion.title}</p>
<p className="text-xs text-muted-foreground">Random song suggestion</p>
</div>
</Link>
</div>
{/* Back Link */}
<button
onClick={() => window.history.back()}
className="mt-8 text-sm text-muted-foreground hover:text-primary transition-colors flex items-center gap-1 group"
>
<ArrowLeft className="h-3 w-3 group-hover:-translate-x-1 transition-transform" />
Take me back where I came from
</button>
</div>
)
}