feat: make orders list clearer and put navbar globally except for admin area
All checks were successful
Staging Build / build (push) Successful in 2m14s

This commit is contained in:
DanielS
2026-06-24 01:37:01 +02:00
parent e829006b77
commit 4a17ea378e
5 changed files with 320 additions and 166 deletions

View File

@@ -1,19 +1,13 @@
import { createClient } from '@/lib/supabase/server'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { FileText, Download, ExternalLink } from 'lucide-react'
import Link from 'next/link'
import { OrdersTable } from '@/components/admin/orders-table'
import { Suspense } from 'react'
export default async function AdminOrdersPage() {
return (
<div className="space-y-6">
<div className="p-8 space-y-6">
<div className="flex justify-between items-center">
<div>
<h1 className="text-3xl font-bold tracking-tight text-white">Bestellungen & Rechnungen</h1>
<h1 className="text-3xl font-bold tracking-tight text-gradient">Bestellungen & Rechnungen</h1>
<p className="text-slate-400">Verwalten Sie alle Kundenbestellungen und greifen Sie auf generierte PDFs zu.</p>
</div>
</div>
@@ -34,75 +28,8 @@ async function OrdersData() {
.order('created_at', { ascending: false })
if (error) {
return <div>Fehler beim Laden der Bestellungen: {error.message}</div>
return <div className="text-red-500">Fehler beim Laden der Bestellungen: {error.message}</div>
}
return (
<Card className="glass-dark border-white/10">
<CardContent className="p-0">
<Table>
<TableHeader>
<TableRow className="border-white/10 hover:bg-transparent">
<TableHead className="w-[140px] text-slate-200">Bestellnr.</TableHead>
<TableHead className="text-slate-200">Datum</TableHead>
<TableHead className="text-slate-200">Kunde</TableHead>
<TableHead className="text-slate-200">Betrag</TableHead>
<TableHead className="text-slate-200">Status</TableHead>
<TableHead className="text-right text-slate-200">Rechnung</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{orders?.length === 0 ? (
<TableRow>
<TableCell colSpan={6} className="text-center py-12 text-muted-foreground">
Noch keine Bestellungen vorhanden.
</TableCell>
</TableRow>
) : (
orders?.map((order) => (
<TableRow key={order.id} className="border-white/5 hover:bg-white/5">
<TableCell className="font-mono text-xs text-primary font-semibold">
{order.order_number ?? order.id.slice(0, 8) + '...'}
</TableCell>
<TableCell className="text-slate-300">
{new Date(order.created_at).toLocaleDateString('de-DE')}
</TableCell>
<TableCell>
<div className="font-medium text-white">{order.customer_data?.company_name || 'Privatkunde'}</div>
<div className="text-xs text-slate-400">{order.customer_data?.first_name} {order.customer_data?.last_name}</div>
</TableCell>
<TableCell className="font-semibold text-white">
{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(order.total_price)}
</TableCell>
<TableCell>
<Badge variant={order.status === 'completed' ? 'default' : 'secondary'} className="capitalize">
{order.status}
</Badge>
</TableCell>
<TableCell className="text-right">
{order.pdf_url ? (
<div className="flex justify-end gap-2">
<Button variant="outline" size="sm" asChild className="h-8 border-white/10 hover:bg-primary/20">
<a href={order.pdf_url} target="_blank" rel="noopener noreferrer">
<ExternalLink className="w-4 h-4 mr-2" /> Ansehen
</a>
</Button>
<Button variant="secondary" size="sm" asChild className="h-8">
<a href={order.pdf_url} download>
<Download className="w-4 h-4" />
</a>
</Button>
</div>
) : (
<span className="text-xs text-muted-foreground italic">Kein PDF</span>
)}
</TableCell>
</TableRow>
))
)}
</TableBody>
</Table>
</CardContent>
</Card>
)
return <OrdersTable initialOrders={orders || []} />
}

View File

@@ -2,6 +2,8 @@ import type { Metadata } from "next";
import { Geist } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { InactivityTracker } from "@/components/inactivity-tracker";
import { HeaderWrapper } from "@/components/HeaderWrapper";
import { Navbar } from "@/components/Navbar";
import "./globals.css";
const defaultUrl = process.env.VERCEL_URL
@@ -35,7 +37,9 @@ export default function RootLayout({
disableTransitionOnChange
>
<InactivityTracker />
{children}
<HeaderWrapper navbar={<Navbar />}>
{children}
</HeaderWrapper>
</ThemeProvider>
</body>
</html>

View File

@@ -5,106 +5,97 @@ import { Navbar } from '@/components/Navbar'
export default function Home() {
return (
<div className="flex flex-col min-h-screen bg-slate-50 text-slate-900 dark:bg-[#020617] dark:text-white">
{/* Demo Banner */}
<div id="demo-banner" className="bg-amber-500/10 border-b border-amber-500/20 py-2 px-4 text-center text-xs text-amber-600 dark:text-amber-400 font-medium tracking-wide z-50">
Dies ist eine **Demo-Webseite (Dummy-Shop)**. Es werden keine echten Bestellungen verarbeitet oder Zahlungen abgewickelt.
</div>
<Navbar />
<main className="flex-1">
{/* 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>
<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.
</p>
<>
{/* 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>
<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.
</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>
{/* 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>
</section>
</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">
{/* 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">
<Cpu className="h-8 w-8 text-blue-600 dark:text-blue-500" />
</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>
{/* 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">
<Cpu className="h-8 w-8 text-blue-600 dark:text-blue-500" />
</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">
<Zap className="h-8 w-8 text-blue-600 dark:text-blue-500" />
</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>
{/* 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">
<Zap className="h-8 w-8 text-blue-600 dark:text-blue-500" />
</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">
<Shield className="h-8 w-8 text-blue-600 dark:text-blue-500" />
</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>
{/* 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">
<Shield className="h-8 w-8 text-blue-600 dark:text-blue-500" />
</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>
</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>
</main>
</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]">
@@ -114,6 +105,6 @@ export default function Home() {
<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>
</div>
</>
)
}