feat: modernize landing page design, localize login/forgot password forms, and add public privacy/imprint pages
All checks were successful
Staging Build / build (push) Successful in 2m42s

This commit is contained in:
DanielS
2026-06-25 22:25:11 +02:00
parent 08382ff4a1
commit e93cf7805c
8 changed files with 525 additions and 114 deletions

View File

@@ -0,0 +1,59 @@
import Link from 'next/link'
import { ArrowLeft, Lock } from 'lucide-react'
import { Button } from '@/components/ui/button'
export default function Datenschutz() {
return (
<div className="min-h-screen bg-slate-950 text-slate-100 py-16 px-4">
<div className="container max-w-3xl mx-auto space-y-8">
<Link href="/">
<Button variant="ghost" size="sm" className="gap-2 text-slate-400 hover:text-white">
<ArrowLeft className="w-4 h-4" /> Zurück zur Startseite
</Button>
</Link>
<div className="space-y-4">
<div className="inline-flex p-3 bg-blue-500/10 rounded-xl text-blue-400">
<Lock className="w-6 h-6" />
</div>
<h1 className="text-4xl font-extrabold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-100 to-slate-400">
Datenschutzerklärung
</h1>
<p className="text-slate-400">Informationen über die Verarbeitung Ihrer personenbezogenen Daten.</p>
</div>
<hr className="border-slate-900" />
<div className="space-y-6 text-slate-300">
<section className="space-y-2">
<h2 className="text-xl font-bold text-white">1. Datenschutz auf einen Blick</h2>
<p className="text-sm text-slate-400 leading-relaxed">
Wir nehmen den Schutz Ihrer persönlichen Daten sehr ernst. Personenbezogene Daten werden auf dieser Webseite nur im technisch notwendigen Umfang erhoben und verarbeitet. Die nachfolgenden Erklärungen geben Ihnen einen Überblick darüber, wie wir diesen Schutz gewährleisten und welche Art von Daten zu welchem Zweck erhoben werden.
</p>
</section>
<section className="space-y-2">
<h2 className="text-xl font-bold text-white">2. Verantwortliche Stelle</h2>
<p className="text-sm text-slate-400 leading-relaxed">
Verantwortlich für die Datenverarbeitung auf dieser Website ist die CASPOS GmbH (Anschrift siehe Impressum).
</p>
</section>
<section className="space-y-2">
<h2 className="text-xl font-bold text-white">3. Datenerfassung auf unserer Website</h2>
<p className="text-sm text-slate-400 leading-relaxed">
Ihre Daten werden zum einen dadurch erhoben, dass Sie uns diese mitteilen. Hierbei kann es sich z. B. um Daten handeln, die Sie in ein Kontakt- oder Bestellformular eingeben. Andere Daten werden automatisch beim Besuch der Website durch unsere IT-Systeme erfasst. Das sind vor allem technische Daten (z. B. Internetbrowser, Betriebssystem oder Uhrzeit des Seitenaufrufs).
</p>
</section>
<section className="space-y-2">
<h2 className="text-xl font-bold text-white">4. Ihre Rechte</h2>
<p className="text-sm text-slate-400 leading-relaxed">
Sie haben jederzeit das Recht, unentgeltlich Auskunft über Herkunft, Empfänger und Zweck Ihrer gespeicherten personenbezogenen Daten zu erhalten. Sie haben außerdem ein Recht, die Berichtigung, Sperrung oder Löschung dieser Daten zu verlangen.
</p>
</section>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,69 @@
import Link from 'next/link'
import { ArrowLeft, Shield } from 'lucide-react'
import { Button } from '@/components/ui/button'
export default function Impressum() {
return (
<div className="min-h-screen bg-slate-950 text-slate-100 py-16 px-4">
<div className="container max-w-3xl mx-auto space-y-8">
<Link href="/">
<Button variant="ghost" size="sm" className="gap-2 text-slate-400 hover:text-white">
<ArrowLeft className="w-4 h-4" /> Zurück zur Startseite
</Button>
</Link>
<div className="space-y-4">
<div className="inline-flex p-3 bg-blue-500/10 rounded-xl text-blue-400">
<Shield className="w-6 h-6" />
</div>
<h1 className="text-4xl font-extrabold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-100 to-slate-400">
Impressum
</h1>
<p className="text-slate-400">Angaben gemäß § 5 TMG.</p>
</div>
<hr className="border-slate-900" />
<div className="space-y-6 text-slate-300">
<section className="space-y-2">
<h2 className="text-lg font-bold text-white">CASPOS GmbH</h2>
<p className="text-sm text-slate-400">
Musterstraße 123<br />
12345 Musterstadt
</p>
</section>
<section className="space-y-2">
<h2 className="text-lg font-bold text-white">Vertreten durch:</h2>
<p className="text-sm text-slate-400">Max Mustermann (Geschäftsführer)</p>
</section>
<section className="space-y-2">
<h2 className="text-lg font-bold text-white">Kontakt:</h2>
<p className="text-sm text-slate-400">
Telefon: +49 (0) 123 456789<br />
E-Mail: info@caspos.de
</p>
</section>
<section className="space-y-2">
<h2 className="text-lg font-bold text-white">Registereintrag:</h2>
<p className="text-sm text-slate-400">
Eintragung im Handelsregister.<br />
Registergericht: Amtsgericht Musterstadt<br />
Registernummer: HRB 12345
</p>
</section>
<section className="space-y-2">
<h2 className="text-lg font-bold text-white">Umsatzsteuer-ID:</h2>
<p className="text-sm text-slate-400">
Umsatzsteuer-Identifikationsnummer gemäß §27 a Umsatzsteuergesetz:<br />
DE 123456789
</p>
</section>
</div>
</div>
</div>
)
}

View File

@@ -1,110 +1,391 @@
"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 { ArrowRight, CheckCircle2, ShoppingCart, Utensils, Layers } from 'lucide-react'
import { Navbar } from '@/components/Navbar'
import { motion } from 'framer-motion'
import {
ArrowRight,
CheckCircle2,
ShoppingCart,
Utensils,
Layers,
Users,
ClipboardList,
Zap,
ArrowUpRight,
ShieldCheck,
Sparkles,
Activity
} from 'lucide-react'
export default function Home() {
const [user, setUser] = useState<any>(null)
const [mounted, setMounted] = useState(false)
useEffect(() => {
setMounted(true)
const supabase = createClient()
supabase.auth.getUser().then(({ data: { user } }) => {
setUser(user)
})
}, [])
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 (
<>
{/* Hero Section: Zielgerichtet auf Lizenzen */}
<section className="w-full py-12 md:py-24 lg:py-32 xl:py-48 px-4 overflow-hidden relative">
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[1000px] h-[600px] bg-blue-600/10 blur-[120px] rounded-full -z-10 opacity-30" />
<div className="container mx-auto">
<div className="flex flex-col items-center space-y-4 text-center">
<div className="space-y-2">
<div className="inline-block rounded-full bg-blue-500/10 px-3 py-1 text-sm text-blue-600 dark:text-blue-400 font-medium border border-blue-500/20 mb-4">
CASPOS Lizenz-Management-Server
<div className="min-h-screen bg-slate-950 text-slate-100 overflow-hidden relative selection:bg-blue-500/30 selection:text-blue-200">
{/* Background Decorative Animated Blobs */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-full max-w-7xl h-[600px] pointer-events-none -z-10 overflow-hidden">
<motion.div
animate={{
scale: [1, 1.15, 0.95, 1],
rotate: [0, 90, 180, 270, 360],
x: [0, 40, -30, 0],
y: [0, -20, 50, 0]
}}
transition={{
duration: 20,
repeat: Infinity,
ease: "easeInOut"
}}
className="absolute -top-[10%] left-[10%] w-[350px] sm:w-[500px] h-[350px] sm:h-[500px] bg-blue-600/15 blur-[120px] sm:blur-[160px] rounded-full"
/>
<motion.div
animate={{
scale: [1, 0.9, 1.1, 1],
rotate: [0, -90, -180, -270, -360],
x: [0, -30, 40, 0],
y: [0, 50, -30, 0]
}}
transition={{
duration: 25,
repeat: Infinity,
ease: "easeInOut"
}}
className="absolute -top-[5%] right-[15%] w-[300px] sm:w-[450px] h-[300px] sm:h-[450px] bg-purple-600/10 blur-[100px] sm:blur-[140px] rounded-full"
/>
</div>
{/* 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"
>
{/* Badge */}
<motion.div
variants={itemVariants}
className="inline-flex items-center gap-2 rounded-full bg-blue-500/10 border border-blue-500/20 px-4 py-1.5 text-xs sm:text-sm text-blue-400 font-semibold tracking-wide backdrop-blur-md shadow-[0_0_15px_rgba(59,130,246,0.1)]"
>
<motion.div
animate={{ opacity: [0.5, 1, 0.5] }}
transition={{ repeat: Infinity, duration: 2, ease: "easeInOut" }}
>
<Zap className="w-3.5 h-3.5 text-blue-400 fill-blue-400/20" />
</motion.div>
CASPOS Lizenz-Order-Portal
</motion.div>
{/* 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 bg-clip-text text-transparent bg-gradient-to-b from-white via-slate-100 to-slate-400"
>
POS Software <span className="bg-clip-text text-transparent bg-gradient-to-r from-blue-400 via-indigo-400 to-purple-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 digitale Lizenzen für CASPOS Kassensysteme.
Sofortige Aktivierung und automatische Bereitstellung für Ihre Kunden.
</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-bold transition-all duration-300 hover:scale-[1.02] bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-500 hover:to-indigo-500 text-white shadow-[0_0_25px_rgba(37,99,235,0.25)] hover:shadow-[0_0_35px_rgba(37,99,235,0.45)] border-none rounded-xl">
Lizenz bestellen <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-900/80 bg-slate-950/40 backdrop-blur-xl shadow-2xl">
{/* Card border glow decoration */}
<div className="absolute inset-0 rounded-2xl border border-blue-500/10 pointer-events-none" />
<p className="text-xs font-bold 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 sm:grid-cols-2 gap-4">
<Link href="/my-customers" className="group">
<motion.div
whileHover={{ y: -4, scale: 1.01 }}
whileTap={{ scale: 0.99 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-900 bg-slate-950/60 hover:bg-slate-900/30 hover:border-blue-500/20 transition-all duration-300"
>
<div className="flex items-center gap-4">
<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">
<Users className="w-5.5 h-5.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">Kunden & Lizenzen verwalten</span>
</div>
</div>
<ArrowUpRight className="w-4.5 h-4.5 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all" />
</motion.div>
</Link>
<Link href="/my-orders" className="group">
<motion.div
whileHover={{ y: -4, scale: 1.01 }}
whileTap={{ scale: 0.99 }}
className="flex items-center justify-between p-4 rounded-xl border border-slate-900 bg-slate-950/60 hover:bg-slate-900/30 hover:border-blue-500/20 transition-all duration-300"
>
<div className="flex items-center gap-4">
<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">
<ClipboardList className="w-5.5 h-5.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">Aufträge & Status einsehen</span>
</div>
</div>
<ArrowUpRight className="w-4.5 h-4.5 text-slate-600 group-hover:text-blue-400 group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-all" />
</motion.div>
</Link>
</div>
</div>
<h1 className="text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl lg:text-7xl/none">
POS Software <span className="text-blue-600 dark:text-blue-500">Lizenzen & Module</span>
</h1>
<p className="mx-auto max-w-[700px] text-slate-600 dark:text-slate-400 md:text-xl mt-6">
Erwerben und verwalten Sie digitale Lizenzen für CASPOS Kassensysteme. Sofortige Aktivierung und automatische Bereitstellung für Ihre Kunden.
</motion.div>
)}
</motion.div>
</section>
{/* Grid of modules */}
<section className="w-full py-16 md:py-24 border-t border-slate-900 bg-slate-950/50 relative">
<div className="container max-w-6xl mx-auto px-4 relative">
<div className="absolute top-1/4 right-0 w-[400px] h-[400px] bg-indigo-600/5 blur-[120px] rounded-full -z-10 pointer-events-none" />
<div className="text-center space-y-3 mb-16">
<div className="inline-flex items-center gap-1.5 text-xs font-bold text-indigo-400 uppercase tracking-widest bg-indigo-500/10 border border-indigo-500/20 px-3 py-1 rounded-full">
<Sparkles className="w-3 h-3" /> System-Module
</div>
<h2 className="text-3xl sm:text-4xl font-bold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-100 to-slate-400">
Verfügbare System-Module
</h2>
<p className="text-slate-400 max-w-[600px] mx-auto text-sm sm:text-base">
Wählen Sie das passende Modul für das Kassensystem Ihres Kunden.
</p>
</div>
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
{/* Card 1 */}
<motion.div
whileHover={{ y: -6 }}
className="group relative flex flex-col p-6 rounded-2xl border border-slate-900 bg-slate-950/70 hover:bg-slate-900/40 hover:border-slate-800/80 transition-all duration-300 shadow-xl overflow-hidden"
>
{/* Highlight line hover effect */}
<div className="absolute top-0 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-blue-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
<div className="space-y-4 relative">
<div className="inline-flex p-3 bg-blue-500/10 rounded-xl text-blue-400 group-hover:bg-blue-500/20 group-hover:scale-110 transition-all duration-300">
<ShoppingCart className="h-6 w-6" />
</div>
<h3 className="text-xl font-bold text-slate-200 group-hover:text-white transition-colors">Handel & ERP</h3>
<p className="text-slate-400 text-sm leading-relaxed">
Erweiterungen für Handelskassen, Bestandsführung und vollwertige Warenwirtschaftssysteme (ERP).
</p>
</div>
</motion.div>
{/* Card 2 */}
<motion.div
whileHover={{ y: -6 }}
className="group relative flex flex-col p-6 rounded-2xl border border-slate-900 bg-slate-950/70 hover:bg-slate-900/40 hover:border-slate-800/80 transition-all duration-300 shadow-xl overflow-hidden"
>
{/* Highlight line hover effect */}
<div className="absolute top-0 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-indigo-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
<div className="space-y-4 relative">
<div className="inline-flex p-3 bg-indigo-500/10 rounded-xl text-indigo-400 group-hover:bg-indigo-500/20 group-hover:scale-110 transition-all duration-300">
<Utensils className="h-6 w-6" />
</div>
<h3 className="text-xl font-bold text-slate-200 group-hover:text-white transition-colors">Gastronomie</h3>
<p className="text-slate-400 text-sm leading-relaxed">
Lizenzen für mobiles Bestellen (Orderman), digitale Küchen-Monitore und interaktive Abhol-Boards.
</p>
</div>
</motion.div>
{/* Card 3 */}
<motion.div
whileHover={{ y: -6 }}
className="group relative flex flex-col p-6 rounded-2xl border border-slate-900 bg-slate-950/70 hover:bg-slate-900/40 hover:border-slate-800/80 transition-all duration-300 shadow-xl overflow-hidden"
>
{/* Highlight line hover effect */}
<div className="absolute top-0 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-purple-500 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
<div className="space-y-4 relative">
<div className="inline-flex p-3 bg-purple-500/10 rounded-xl text-purple-400 group-hover:bg-purple-500/20 group-hover:scale-110 transition-all duration-300">
<Layers className="h-6 w-6" />
</div>
<h3 className="text-xl font-bold text-slate-200 group-hover:text-white transition-colors">Hybride Systeme</h3>
<p className="text-slate-400 text-sm leading-relaxed">
Das Beste aus beiden Welten. Nahtlose Kombination von Handel- und Gastronomie-Funktionalitäten.
</p>
</div>
</motion.div>
</div>
</div>
</section>
{/* Stepper info */}
<section className="w-full py-16 md:py-24 border-t border-slate-900 bg-slate-950/30">
<div className="container max-w-5xl mx-auto px-4">
<div className="text-center space-y-3 mb-16">
<div className="inline-flex items-center gap-1.5 text-xs font-bold text-blue-400 uppercase tracking-widest bg-blue-500/10 border border-blue-500/20 px-3 py-1 rounded-full">
<Activity className="w-3 h-3" /> Ablauf
</div>
<h2 className="text-2xl sm:text-3xl font-bold tracking-tight text-center bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-200 to-slate-400">
Wie funktioniert die Bereitstellung?
</h2>
</div>
<div className="relative">
{/* Connection line for Desktop */}
<div className="hidden md:block absolute top-[28px] left-[15%] right-[15%] h-[1px] bg-gradient-to-r from-blue-500/10 via-blue-500/30 to-blue-500/10 z-0" />
<div className="grid gap-8 md:grid-cols-3 relative z-10">
{/* Step 1 */}
<div className="flex flex-col items-center text-center space-y-4 p-4 group">
<div className="flex items-center justify-center w-14 h-14 rounded-2xl bg-slate-900 border border-slate-800 text-blue-400 font-black text-lg shadow-lg group-hover:border-blue-500/40 group-hover:shadow-[0_0_15px_rgba(59,130,246,0.15)] transition-all duration-300">
1
</div>
<h4 className="text-lg font-bold text-slate-200 group-hover:text-white transition-colors">Kunde wählen</h4>
<p className="text-sm text-slate-400 leading-relaxed max-w-[250px]">
Gewünschten Kunden auswählen, der die Lizenz erhalten soll.
</p>
</div>
{/* Step 2 */}
<div className="flex flex-col items-center text-center space-y-4 p-4 group">
<div className="flex items-center justify-center w-14 h-14 rounded-2xl bg-slate-900 border border-slate-800 text-blue-400 font-black text-lg shadow-lg group-hover:border-blue-500/40 group-hover:shadow-[0_0_15px_rgba(59,130,246,0.15)] transition-all duration-300">
2
</div>
<h4 className="text-lg font-bold text-slate-200 group-hover:text-white transition-colors">Lizenz wählen</h4>
<p className="text-sm text-slate-400 leading-relaxed max-w-[250px]">
Gewünschte Lizenzen für den Kunden auswählen und den Bestellung abschließen.
</p>
</div>
{/* Step 3 */}
<div className="flex flex-col items-center text-center space-y-4 p-4 group">
<div className="flex items-center justify-center w-14 h-14 rounded-2xl bg-slate-900 border border-slate-800 text-blue-400 font-black text-lg shadow-lg group-hover:border-blue-500/40 group-hover:shadow-[0_0_15px_rgba(59,130,246,0.15)] transition-all duration-300">
3
</div>
<h4 className="text-lg font-bold text-slate-200 group-hover:text-white transition-colors">Live gehen</h4>
<p className="text-sm text-slate-400 leading-relaxed max-w-[250px]">
Nach dem Erhalt der Lizenz Live gehen.
</p>
</div>
</div>
</div>
</div>
</section>
{/* Core values / Features list */}
<section className="w-full py-16 md:py-24 border-t border-slate-900 bg-slate-950/50">
<div className="container max-w-5xl mx-auto px-4">
<div className="grid gap-8 md:grid-cols-2 items-center">
<div className="space-y-6">
<div className="inline-flex items-center gap-1.5 text-xs font-bold text-blue-400 uppercase tracking-widest bg-blue-500/10 border border-blue-500/20 px-3 py-1 rounded-full">
<ShieldCheck className="w-3.5 h-3.5" /> Sicherheit & Stabilität
</div>
<h3 className="text-3xl font-extrabold tracking-tight bg-clip-text text-transparent bg-gradient-to-r from-white via-slate-100 to-slate-400">
Verlässliche Plattform für Lizenz-Aktivierungen
</h3>
<p className="text-slate-400 text-sm sm:text-base leading-relaxed">
Unsere Kassenlösungen sind GoBD-konform und offline-fähig. Über den Lizenz-Management-Server werden alle Lizenzen und Module verschlüsselt übertragen und sind innerhalb weniger Millisekunden auf der Kasse aktiv.
</p>
</div>
{/* High-Contrast Buttons (Light/Dark Ready) */}
<div className="space-x-4 mt-8">
<Link href="/order">
<Button size="lg" className="h-12 px-8 text-lg font-bold transition-all hover:scale-105 bg-slate-900 text-white hover:bg-slate-800 border border-slate-200 dark:bg-white dark:text-black dark:hover:bg-slate-200 dark:border-none">
Lizenz bestellen <ArrowRight className="ml-2 h-5 w-5" />
</Button>
</Link>
<Link href="https://caspos.de/kontakt/" target="_blank" rel="noopener noreferrer">
<Button size="lg" variant="outline" className="h-12 px-8 text-lg font-semibold bg-transparent border-slate-400 text-slate-900 hover:bg-slate-100 dark:border-white/40 dark:text-white dark:hover:bg-white/10">
Fragen? Kontaktieren Sie uns
</Button>
</Link>
</div>
</div>
</div>
</section>
{/* Feature Grid: Aufgeteilt nach echten POS-Modulen */}
<section className="w-full py-12 md:py-24 lg:py-32 border-t border-slate-200 dark:border-white/5 bg-slate-50 dark:bg-white/[0.02]">
<div className="container mx-auto px-4 md:px-6">
<div className="grid gap-12 lg:grid-cols-3">
{/* Modul 1 */}
<div className="flex flex-col items-center space-y-4 text-center p-6 rounded-2xl border border-slate-200 dark:border-white/5 bg-white dark:bg-slate-900/50 shadow-sm">
<div className="p-3 bg-blue-600/10 rounded-xl">
<ShoppingCart className="h-8 w-8 text-blue-600 dark:text-blue-500" />
<div className="grid gap-4 sm:grid-cols-2">
<div className="p-5 rounded-xl border border-slate-900 bg-slate-950/70 space-y-2">
<CheckCircle2 className="w-5 h-5 text-blue-500" />
<h5 className="font-bold text-sm text-slate-200">GoBD Konformität</h5>
<p className="text-xs text-slate-400">Konform nach allen aktuellen steuerrechtlichen Anforderungen.</p>
</div>
<h3 className="text-xl font-bold">Handel & ERP</h3>
<p className="text-slate-600 dark:text-slate-400">Erweiterungen für Handelskassen, Bestandsführung und vollwertige Warenwirtschaftssysteme (ERP).</p>
</div>
{/* Modul 2 */}
<div className="flex flex-col items-center space-y-4 text-center p-6 rounded-2xl border border-slate-200 dark:border-white/5 bg-white dark:bg-slate-900/50 shadow-sm">
<div className="p-3 bg-blue-600/10 rounded-xl">
<Utensils className="h-8 w-8 text-blue-600 dark:text-blue-500" />
<div className="p-5 rounded-xl border border-slate-900 bg-slate-950/70 space-y-2">
<CheckCircle2 className="w-5 h-5 text-blue-500" />
<h5 className="font-bold text-sm text-slate-200">Same-Day-Bearbeitung</h5>
<p className="text-xs text-slate-400">Bearbeitung und Erstellung Ihrer Lizenzen noch am selben Werktag.</p>
</div>
<h3 className="text-xl font-bold">Gastronomie</h3>
<p className="text-slate-600 dark:text-slate-400">Lizenzen für mobiles Bestellen (Orderman), digitale Küchen-Monitore und interaktive Abhol-Boards.</p>
</div>
{/* Modul 3 */}
<div className="flex flex-col items-center space-y-4 text-center p-6 rounded-2xl border border-slate-200 dark:border-white/5 bg-white dark:bg-slate-900/50 shadow-sm">
<div className="p-3 bg-blue-600/10 rounded-xl">
<Layers className="h-8 w-8 text-blue-600 dark:text-blue-500" />
<div className="p-5 rounded-xl border border-slate-900 bg-slate-950/70 space-y-2">
<CheckCircle2 className="w-5 h-5 text-blue-500" />
<h5 className="font-bold text-sm text-slate-200">Verschlüsselte Keys</h5>
<p className="text-xs text-slate-400">Sichere Lizenz-Authentifizierung direkt auf der Kasse.</p>
</div>
<div className="p-5 rounded-xl border border-slate-900 bg-slate-950/70 space-y-2">
<CheckCircle2 className="w-5 h-5 text-blue-500" />
<h5 className="font-bold text-sm text-slate-200">Partner Support</h5>
<p className="text-xs text-slate-400">Schnelle Hilfe und kompetente Ansprechpartner für Händler.</p>
</div>
<h3 className="text-xl font-bold">Hybride Systeme</h3>
<p className="text-slate-600 dark:text-slate-400">Das beste aus beiden Welten. Handel mit Gastronomie und umgekehrt. </p>
</div>
</div>
</div>
</section>
{/* Kurze Info-Sektion für Partner / Händler */}
<section className="w-full py-12 md:py-24 border-t border-slate-200 dark:border-white/5">
<div className="container mx-auto px-4 max-w-4xl text-center">
<h2 className="text-2xl font-bold tracking-tight sm:text-3xl mb-6">Wie funktioniert die Bereitstellung?</h2>
<div className="grid gap-6 sm:grid-cols-3 text-left">
<div className="flex gap-2 items-start">
<CheckCircle2 className="h-5 w-5 text-blue-600 dark:text-blue-500 shrink-0 mt-0.5" />
<p className="text-sm text-slate-600 dark:text-slate-400"><strong>1. Lizenz wählen:</strong> Gewünschtes POS-Modul im Shop selektieren.</p>
</div>
<div className="flex gap-2 items-start">
<CheckCircle2 className="h-5 w-5 text-blue-600 dark:text-blue-500 shrink-0 mt-0.5" />
<p className="text-sm text-slate-600 dark:text-slate-400"><strong>2. Kunde zuweisen:</strong> Lizenz direkt einem Kunden-Account zuordnen.</p>
</div>
<div className="flex gap-2 items-start">
<CheckCircle2 className="h-5 w-5 text-blue-600 dark:text-blue-500 shrink-0 mt-0.5" />
<p className="text-sm text-slate-600 dark:text-slate-400"><strong>3. Live gehen:</strong> Lizenz-Key (`.key`) wird sofort serverseitig aktiviert.</p>
</div>
</div>
</div>
</section>
{/* Footer */}
<footer className="flex flex-col gap-2 sm:flex-row py-6 w-full shrink-0 items-center px-4 md:px-6 border-t border-slate-200 dark:border-white/5 bg-slate-50 dark:bg-[#020617]">
<p className="text-xs text-slate-500">© 2026 CASPOS GmbH. Alle Rechte vorbehalten.</p>
<nav className="sm:ml-auto flex gap-4 sm:gap-6">
<Link className="text-xs hover:underline underline-offset-4 text-slate-500" href="https://caspos.de/impressum/" target="_blank" rel="noopener noreferrer">Impressum</Link>
<Link className="text-xs hover:underline underline-offset-4 text-slate-500" href="https://caspos.de/datenschutz/" target="_blank" rel="noopener noreferrer">Datenschutz</Link>
</nav>
<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>
)
}

View File

@@ -98,7 +98,7 @@ export function NavbarClient({ user, role = "partner" }: NavbarClientProps) {
<>
<header className="px-4 lg:px-6 h-16 flex items-center justify-between border-b border-white/5 backdrop-blur-md sticky top-0 z-50 bg-[#020617]/85">
<Link className="flex items-center justify-center gap-2 group" href="/">
<span className="font-bold text-xl tracking-tighter text-white">CASPOS Store</span>
<span className="font-bold text-xl tracking-tighter text-white">CASPOS Shop</span>
<DemoWrapper>
<span className="text-[10px] bg-amber-500/20 text-amber-400 px-2 py-0.5 rounded-full font-semibold uppercase tracking-wider border border-amber-500/30">
Demo

View File

@@ -33,7 +33,7 @@ export function ForgotPasswordForm({
await resetPassword(email);
setSuccess(true);
} catch (error: unknown) {
setError(error instanceof Error ? error.message : "An error occurred");
setError(error instanceof Error ? error.message : "Ein Fehler ist aufgetreten.");
} finally {
setIsLoading(false);
}
@@ -44,34 +44,34 @@ export function ForgotPasswordForm({
{success ? (
<Card>
<CardHeader>
<CardTitle className="text-2xl">Check Your Email</CardTitle>
<CardDescription>Password reset instructions sent</CardDescription>
<CardTitle className="text-2xl">E-Mails prüfen</CardTitle>
<CardDescription>Link zum Zurücksetzen gesendet</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
If you registered using your email and password, you will receive
a password reset email.
Wenn Sie sich mit E-Mail und Passwort registriert haben, erhalten Sie
in Kürze eine E-Mail zum Zurücksetzen Ihres Passworts.
</p>
</CardContent>
</Card>
) : (
<Card>
<CardHeader>
<CardTitle className="text-2xl">Reset Your Password</CardTitle>
<CardTitle className="text-2xl">Passwort zurücksetzen</CardTitle>
<CardDescription>
Type in your email and we&apos;ll send you a link to reset your
password
Geben Sie Ihre E-Mail-Adresse ein. Wir senden Ihnen einen Link,
um Ihr Passwort zurückzusetzen.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleForgotPassword}>
<div className="flex flex-col gap-6">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Label htmlFor="email">E-Mail</Label>
<Input
id="email"
type="email"
placeholder="m@example.com"
placeholder="name@beispiel.de"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
@@ -79,16 +79,16 @@ export function ForgotPasswordForm({
</div>
{error && <p className="text-sm text-red-500">{error}</p>}
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? "Sending..." : "Send reset email"}
{isLoading ? "Wird gesendet..." : "Link senden"}
</Button>
</div>
<div className="mt-4 text-center text-sm">
Already have an account?{" "}
Bereits ein Konto vorhanden?{" "}
<Link
href="/auth/login"
className="underline underline-offset-4"
>
Login
Anmelden
</Link>
</div>
</form>

View File

@@ -44,7 +44,7 @@ export function LoginForm({
try {
const res = await signIn(email, password);
if (!res.success) {
setError(res.error || "An error occurred");
setError(res.error || "Ein Fehler ist aufgetreten.");
return;
}
if (nextParam) {
@@ -55,7 +55,7 @@ export function LoginForm({
router.push("/my-customers");
}
} catch (error: unknown) {
setError(error instanceof Error ? error.message : "An error occurred");
setError(error instanceof Error ? error.message : "Ein Fehler ist aufgetreten.");
} finally {
setIsLoading(false);
}
@@ -65,20 +65,20 @@ export function LoginForm({
<div className={cn("flex flex-col gap-6", className)} {...props}>
<Card>
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardTitle className="text-2xl">Anmelden</CardTitle>
<CardDescription>
Enter your email below to login to your account
Geben Sie Ihre E-Mail-Adresse und Ihr Passwort ein, um sich anzumelden.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleLogin}>
<div className="flex flex-col gap-6">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Label htmlFor="email">E-Mail</Label>
<Input
id="email"
type="email"
placeholder="m@example.com"
placeholder="name@beispiel.de"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
@@ -86,12 +86,12 @@ export function LoginForm({
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
<Label htmlFor="password">Passwort</Label>
<Link
href="/auth/forgot-password"
className="ml-auto inline-block text-sm underline-offset-4 hover:underline"
>
Forgot your password?
Passwort vergessen?
</Link>
</div>
<Input
@@ -114,7 +114,7 @@ export function LoginForm({
)}
{error && <p className="text-sm text-red-500">{error}</p>}
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? "Logging in..." : "Login"}
{isLoading ? "Wird angemeldet..." : "Anmelden"}
</Button>
</div>
</form>

View File

@@ -964,7 +964,7 @@ export function OrderWizard({
)}
<p className="text-xs text-slate-500 italic">
Mit dem Klick auf Kostenpflichtig bestellen" akzeptieren Sie unsere AGB und die{' '}
<a href="https://caspos.de/datenschutz/" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-400">
<a href="/datenschutz" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-400">
Datenschutzerklärung
</a>.
</p>

View File

@@ -53,6 +53,8 @@ export async function updateSession(request: NextRequest) {
if (
request.nextUrl.pathname !== "/" &&
request.nextUrl.pathname !== "/impressum" &&
request.nextUrl.pathname !== "/datenschutz" &&
!user &&
!request.nextUrl.pathname.startsWith("/login") &&
!request.nextUrl.pathname.startsWith("/auth")