Files
webshop/shop/app/my-orders/page.tsx

166 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'
import Link from 'next/link'
import { Download, ExternalLink, ShoppingBag, ArrowLeft, Package } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import type { Order } from '@/lib/types'
const statusLabel: Record<string, string> = {
pending: 'Eingegangen',
active: 'In Bearbeitung',
cancelled: 'Storniert',
}
const statusClass: Record<string, string> = {
pending: 'bg-amber-500/20 text-amber-400 border-amber-500/30',
active: 'bg-green-500/20 text-green-400 border-green-500/30',
cancelled: 'bg-red-500/20 text-red-400 border-red-500/30',
}
export default async function MyOrdersPage() {
const supabase = await createClient()
const { data: { user } } = await supabase.auth.getUser()
if (!user) redirect('/auth/login')
const { data: orders, error } = await supabase
.from('orders')
.select('*')
.eq('user_id', user.id)
.order('created_at', { ascending: false })
return (
<div className="min-h-screen bg-[#020617] text-white px-4 py-12">
<div className="max-w-4xl mx-auto space-y-8">
{/* Header */}
<div className="flex items-center gap-4">
<Link href="/">
<Button variant="ghost" size="sm" className="text-slate-400 hover:text-white">
<ArrowLeft className="w-4 h-4 mr-2" /> Startseite
</Button>
</Link>
<div>
<h1 className="text-3xl font-extrabold tracking-tight flex items-center gap-3">
<ShoppingBag className="w-8 h-8 text-primary" />
Meine Anfragen
</h1>
<p className="text-slate-400 text-sm mt-1">
Alle Ihre Anfragen auf einen Blick inkl. aktuellem Status.
</p>
</div>
</div>
{/* Fehler */}
{error && (
<div className="bg-red-500/10 border border-red-500/20 text-red-400 rounded-xl p-4 text-sm">
Fehler beim Laden der Anfragen: {error.message}
</div>
)}
{/* Keine Anfragen */}
{!error && (!orders || orders.length === 0) && (
<Card className="glass-dark border-white/10">
<CardContent className="flex flex-col items-center justify-center py-16 gap-4">
<Package className="w-12 h-12 text-slate-600" />
<p className="text-slate-400 text-lg">Sie haben noch keine Anfragen aufgegeben.</p>
<Link href="/order">
<Button>Jetzt konfigurieren</Button>
</Link>
</CardContent>
</Card>
)}
{/* Anfragenliste */}
<div className="space-y-4">
{(orders ?? []).map((order) => {
const o = order as Order
const items = o.order_data?.items ?? []
return (
<Card key={o.id} className="glass-dark border-white/10 hover:border-white/20 transition-colors">
<CardContent className="p-6 space-y-4">
{/* Kopfzeile */}
<div className="flex items-start justify-between gap-4 flex-wrap">
<div className="space-y-1">
<p className="text-xs text-slate-500 uppercase tracking-wider">Anfragenummer</p>
<p className="font-mono font-bold text-primary text-lg">#{o.order_number}</p>
</div>
<div className="space-y-1 text-right">
<p className="text-xs text-slate-500 uppercase tracking-wider">Datum</p>
<p className="text-white text-sm">
{new Date(o.created_at).toLocaleDateString('de-DE', {
day: '2-digit', month: '2-digit', year: 'numeric',
})}
</p>
</div>
<div className="space-y-1">
<p className="text-xs text-slate-500 uppercase tracking-wider">Status</p>
<Badge className={statusClass[o.status] ?? 'bg-slate-500/20 text-slate-300'}>
{statusLabel[o.status] ?? o.status}
</Badge>
</div>
<div className="space-y-1 text-right">
<p className="text-xs text-slate-500 uppercase tracking-wider">Gesamt</p>
<p className="font-bold text-white text-lg">
{new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(o.total_price)}
</p>
</div>
</div>
{/* Produkte kurz */}
{items.length > 0 && (
<div className="flex flex-wrap gap-2">
{items.map((item, i) => (
<span
key={item.product_id}
className="text-xs bg-white/5 border border-white/10 rounded-full px-3 py-1 text-slate-300"
>
{item.product_name}
{item.selected_modules.length > 0 && (
<span className="text-slate-500 ml-1">+{item.selected_modules.length} Module</span>
)}
</span>
))}
</div>
)}
{/* Aktionen */}
<div className="flex gap-2 flex-wrap pt-1">
<Link href={`/order/success?id=${o.id}`}>
<Button variant="outline" size="sm" className="border-white/10 hover:bg-white/10 text-xs">
Details ansehen
</Button>
</Link>
{o.status === 'pending' && (
<Link href={`/order?id=${o.id}`}>
<Button variant="outline" size="sm" className="border-amber-500/20 hover:bg-amber-500/10 hover:border-amber-500/40 text-amber-400 text-xs">
Bearbeiten
</Button>
</Link>
)}
{o.pdf_url && (
<>
<Button variant="ghost" size="sm" asChild className="text-xs text-slate-400 hover:text-white">
<a href={o.pdf_url} target="_blank" rel="noopener noreferrer">
<ExternalLink className="w-3 h-3 mr-1" /> Anfrage ansehen
</a>
</Button>
<Button variant="ghost" size="sm" asChild className="text-xs text-slate-400 hover:text-white">
<a href={o.pdf_url} download>
<Download className="w-3 h-3 mr-1" /> PDF
</a>
</Button>
</>
)}
</div>
</CardContent>
</Card>
)
})}
</div>
</div>
</div>
)
}