Files
webshop/shop/components/HomeClient.tsx
DanielS ec264e2680
All checks were successful
Staging Build / build (push) Successful in 2m59s
feat(home): integrate motion components in home page
2026-08-06 17:21:52 +02:00

278 lines
12 KiB
TypeScript

"use client"
import { useState, useEffect } from 'react'
import { createClient } from '@/lib/supabase/client'
import { Button } from '@/components/ui/button'
import Link from 'next/link'
import { motion } from 'framer-motion'
import { type User } from '@supabase/supabase-js'
import {
ArrowRight,
CheckCircle2,
MessageSquare,
BookOpen,
Layers,
LifeBuoy,
Users,
ClipboardList,
Zap,
ArrowUpRight,
ShieldCheck,
Calendar,
Sparkles,
Activity
} from 'lucide-react'
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
} from '@/components/ui/dialog'
import { AsciiShaderBackground } from '@/components/AsciiShaderBackground'
import { ProcessSteps } from '@/components/ProcessSteps'
import { ScrollIndicator } from '@/components/ScrollIndicator'
import { WorkspaceZentrale } from '@/components/WorkspaceZentrale'
interface HomeClientProps {
initialUser: User | null
}
export function HomeClient({ initialUser }: HomeClientProps) {
const [user, setUser] = useState<User | null>(initialUser)
const [mounted, setMounted] = useState(false)
const [calendarOpen, setCalendarOpen] = useState(false)
useEffect(() => {
setMounted(true)
const supabase = createClient()
// Listen to client-side auth state changes to stay in sync
const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
setUser(session?.user ?? null)
})
return () => {
subscription.unsubscribe()
}
}, [])
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.15
}
}
}
const itemVariants = {
hidden: { y: 20, opacity: 0 },
visible: {
y: 0,
opacity: 1,
transition: {
type: "spring" as const,
stiffness: 100,
damping: 15
}
}
}
return (
<div className="min-h-screen bg-transparent text-slate-100 overflow-hidden relative selection:bg-blue-500/30 selection:text-blue-200">
<AsciiShaderBackground />
{/* Hero Section */}
<section className="w-full pt-16 pb-12 md:pt-28 md:pb-20 px-4 relative flex flex-col items-center">
<motion.div
initial="hidden"
animate="visible"
variants={containerVariants}
className="container max-w-6xl mx-auto flex flex-col items-center text-center space-y-8"
>
{/* Headline */}
<div className="space-y-4 max-w-4xl">
<motion.h1
variants={itemVariants}
className="text-4xl font-extrabold tracking-tight sm:text-5xl md:text-6xl lg:text-7xl/tight text-white"
>
CASPOS Software <span className="text-blue-500 font-black">Lizenzen & Module</span>
</motion.h1>
<motion.p
variants={itemVariants}
className="mx-auto max-w-[750px] text-slate-400 text-base sm:text-lg md:text-xl font-normal leading-relaxed"
>
Erwerben und verwalten Sie Lizenzen für CASPOS Kassensysteme.
</motion.p>
</div>
{/* Hero CTAs */}
<motion.div
variants={itemVariants}
className="flex flex-col sm:flex-row items-center justify-center gap-4 w-full max-w-md pt-4"
>
<Link href="/order" className="w-full sm:w-auto">
<Button size="lg" className="w-full sm:w-auto h-12 px-8 text-base font-semibold bg-blue-600 hover:bg-blue-500 text-white border border-blue-700/50 rounded-xl transition-all duration-200">
Lizenz anfragen <ArrowRight className="ml-2 h-4 w-4" />
</Button>
</Link>
<Link href="https://caspos.de/kontakt/" target="_blank" rel="noopener noreferrer" className="w-full sm:w-auto">
<Button size="lg" variant="outline" className="w-full sm:w-auto h-12 px-8 text-base font-semibold transition-all duration-300 hover:bg-white/5 border-slate-800 hover:border-slate-700 text-slate-300 hover:text-white rounded-xl backdrop-blur-sm">
Fragen? Kontakt
</Button>
</Link>
</motion.div>
{/* Quick Access Actions Bar */}
{mounted && user && (
<motion.div
variants={itemVariants}
className="w-full max-w-3xl pt-12"
>
<div className="relative p-6 rounded-2xl border border-slate-800 bg-slate-900/40 backdrop-blur-md shadow-lg">
<p className="text-xs font-semibold uppercase tracking-widest text-slate-500 mb-5 text-left sm:text-center px-2">
Mein Dashboard Schnellzugriff
</p>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<Link href="/my-customers" className="group">
<motion.div
whileHover={{ y: -2 }}
whileTap={{ scale: 0.98 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200 h-full"
>
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors shrink-0">
<Users className="w-5 h-5" />
</div>
<div className="text-left">
<span className="block font-bold text-sm text-slate-200 group-hover:text-white transition-colors">Kundenliste</span>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Verwalten</span>
</div>
</div>
<ArrowUpRight className="w-4 h-4 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all shrink-0" />
</motion.div>
</Link>
<Link href="/my-orders" className="group">
<motion.div
whileHover={{ y: -2 }}
whileTap={{ scale: 0.98 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200 h-full"
>
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors shrink-0">
<ClipboardList className="w-5 h-5" />
</div>
<div className="text-left">
<span className="block font-bold text-sm text-slate-200 group-hover:text-white transition-colors">Bestellungen</span>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Status einsehen</span>
</div>
</div>
<ArrowUpRight className="w-4 h-4 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all shrink-0" />
</motion.div>
</Link>
<button type="button" onClick={() => setCalendarOpen(true)} className="group text-left w-full">
<motion.div
whileHover={{ y: -2 }}
whileTap={{ scale: 0.98 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-800 bg-slate-950 hover:bg-slate-900 hover:border-slate-700 transition-all duration-200 h-full"
>
<div className="flex items-center gap-3">
<div className="p-2.5 rounded-lg bg-blue-500/10 text-blue-400 group-hover:bg-blue-500/20 group-hover:text-blue-300 transition-colors shrink-0">
<Calendar className="w-5 h-5" />
</div>
<div className="text-left">
<div className="flex items-center gap-1.5">
<span className="block font-bold text-sm text-slate-200 group-hover:text-white transition-colors">Termine</span>
<span className="px-1.5 py-0.5 text-[10px] font-medium bg-amber-500/10 text-amber-400 border border-amber-500/20 rounded-md">Geplant</span>
</div>
<span className="block text-xs text-slate-500 group-hover:text-slate-400 transition-colors">Terminkalender</span>
</div>
</div>
<ArrowUpRight className="w-4 h-4 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all shrink-0" />
</motion.div>
</button>
</div>
</div>
</motion.div>
)}
</motion.div>
</section>
{/* Dialog / Popup für Termin-Kalender (Geplant) */}
<Dialog open={calendarOpen} onOpenChange={setCalendarOpen}>
<DialogContent className="bg-slate-900 border-slate-800 text-slate-100 max-w-md">
<DialogHeader>
<div className="flex items-center gap-3 mb-2">
<div className="p-2.5 rounded-xl bg-blue-500/10 text-blue-400 border border-blue-500/20">
<Calendar className="w-6 h-6" />
</div>
<div>
<DialogTitle className="text-xl font-bold text-white flex items-center gap-2">
Termin-Kalender
<span className="px-2 py-0.5 text-xs font-semibold bg-amber-500/10 text-amber-400 border border-amber-500/20 rounded-full">
In Planung
</span>
</DialogTitle>
</div>
</div>
<DialogDescription className="text-slate-400 text-sm leading-relaxed pt-2">
Der Termin-Kalender bietet in Kürze eine Übersicht für anstehende Schulungen, Online- & Vor-Ort-Workshops sowie Termine für Blauer-Mittwoch-Partner zur direkten Anmeldung.
</DialogDescription>
</DialogHeader>
<div className="p-4 my-2 rounded-xl bg-slate-950 border border-slate-800 text-xs text-slate-400 space-y-2">
<div className="flex items-center justify-between text-slate-300 font-medium">
<span>Geplante Features & Angebote:</span>
</div>
<ul className="list-disc list-inside space-y-1 text-slate-400">
<li>Anmeldung zu Online- & Vor-Ort-Workshops</li>
<li>Anstehende Schulungstermine auf einen Blick</li>
<li>Spezielle Schulungen für Blauer-Mittwoch-Partner</li>
<li>Kalender-Export (.ics / Google / Outlook)</li>
</ul>
</div>
<DialogFooter>
<Button
variant="outline"
onClick={() => setCalendarOpen(false)}
className="w-full sm:w-auto border-slate-700 bg-slate-800 text-slate-200 hover:bg-slate-700 hover:text-white"
>
Schließen
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
{/* Grid of modules / Workspace-Zentrale */}
<WorkspaceZentrale />
{/* Stepper info */}
<ProcessSteps />
{/* Footer */}
<footer className="w-full border-t border-slate-900 bg-slate-950 py-8 px-4 md:px-6 relative z-10">
<div className="container max-w-6xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-4">
<p className="text-xs text-slate-500">© 2026 CASPOS GmbH. Alle Rechte vorbehalten.</p>
<nav className="flex gap-6">
<Link className="text-xs text-slate-500 hover:text-slate-300 transition-colors" href="/impressum">Impressum</Link>
<Link className="text-xs text-slate-500 hover:text-slate-300 transition-colors" href="/datenschutz">Datenschutz</Link>
</nav>
</div>
</footer>
</div>
)
}