174 lines
6.2 KiB
TypeScript
174 lines
6.2 KiB
TypeScript
import Link from 'next/link';
|
|
|
|
import { User, Mail, Phone, MapPin, CreditCard, Pencil, Ban } from 'lucide-react';
|
|
|
|
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
|
import { Badge } from '@kit/ui/badge';
|
|
import { Button } from '@kit/ui/button';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
|
|
|
|
import { createMemberManagementApi } from '@kit/member-management/api';
|
|
|
|
import { CmsPageShell } from '~/components/cms-page-shell';
|
|
|
|
interface PageProps {
|
|
params: Promise<{ account: string; memberId: string }>;
|
|
}
|
|
|
|
const STATUS_LABEL: Record<string, string> = {
|
|
active: 'Aktiv',
|
|
inactive: 'Inaktiv',
|
|
pending: 'Ausstehend',
|
|
cancelled: 'Gekündigt',
|
|
};
|
|
|
|
const STATUS_VARIANT: Record<string, 'default' | 'secondary' | 'destructive' | 'outline'> = {
|
|
active: 'default',
|
|
inactive: 'secondary',
|
|
pending: 'outline',
|
|
cancelled: 'destructive',
|
|
};
|
|
|
|
function DetailRow({ label, value }: { label: string; value: string }) {
|
|
return (
|
|
<div className="flex flex-col gap-0.5">
|
|
<span className="text-xs text-muted-foreground">{label}</span>
|
|
<span className="text-sm font-medium">{value || '—'}</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default async function MemberDetailPage({ params }: PageProps) {
|
|
const { account, memberId } = await params;
|
|
const client = getSupabaseServerClient();
|
|
const api = createMemberManagementApi(client);
|
|
|
|
const member = await api.getMember(memberId);
|
|
|
|
if (!member) return <div>Mitglied nicht gefunden</div>;
|
|
|
|
const m = member as Record<string, unknown>;
|
|
|
|
return (
|
|
<CmsPageShell account={account} title={`${String(m.first_name)} ${String(m.last_name)}`}>
|
|
<div className="flex w-full flex-col gap-6">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-bold">
|
|
{String(m.first_name)} {String(m.last_name)}
|
|
</h1>
|
|
<div className="mt-1 flex items-center gap-2">
|
|
<Badge variant={STATUS_VARIANT[String(m.status)] ?? 'secondary'}>
|
|
{STATUS_LABEL[String(m.status)] ?? String(m.status)}
|
|
</Badge>
|
|
{m.member_number ? (
|
|
<span className="text-sm text-muted-foreground">
|
|
Nr. {String(m.member_number)}
|
|
</span>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
<div className="flex gap-2">
|
|
<Button variant="outline">
|
|
<Pencil className="mr-2 h-4 w-4" />
|
|
Bearbeiten
|
|
</Button>
|
|
<Button variant="destructive">
|
|
<Ban className="mr-2 h-4 w-4" />
|
|
Kündigen
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
|
{/* Persönliche Daten */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<User className="h-4 w-4" />
|
|
Persönliche Daten
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-2 gap-4">
|
|
<DetailRow label="Vorname" value={String(m.first_name ?? '')} />
|
|
<DetailRow label="Nachname" value={String(m.last_name ?? '')} />
|
|
<DetailRow
|
|
label="Geburtsdatum"
|
|
value={m.date_of_birth ? new Date(String(m.date_of_birth)).toLocaleDateString('de-DE') : ''}
|
|
/>
|
|
<DetailRow label="Geschlecht" value={String(m.gender ?? '')} />
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Kontakt */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<Mail className="h-4 w-4" />
|
|
Kontakt
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-2 gap-4">
|
|
<DetailRow label="E-Mail" value={String(m.email ?? '')} />
|
|
<DetailRow label="Telefon" value={String(m.phone ?? '')} />
|
|
<DetailRow label="Mobil" value={String(m.mobile ?? '')} />
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Adresse */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<MapPin className="h-4 w-4" />
|
|
Adresse
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-2 gap-4">
|
|
<DetailRow label="Straße" value={`${String(m.street ?? '')} ${String(m.house_number ?? '')}`} />
|
|
<DetailRow label="PLZ / Ort" value={`${String(m.postal_code ?? '')} ${String(m.city ?? '')}`} />
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Mitgliedschaft */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<User className="h-4 w-4" />
|
|
Mitgliedschaft
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-2 gap-4">
|
|
<DetailRow label="Mitgliedsnr." value={String(m.member_number ?? '')} />
|
|
<DetailRow label="Status" value={STATUS_LABEL[String(m.status)] ?? String(m.status ?? '')} />
|
|
<DetailRow
|
|
label="Eintrittsdatum"
|
|
value={m.entry_date ? new Date(String(m.entry_date)).toLocaleDateString('de-DE') : ''}
|
|
/>
|
|
<DetailRow
|
|
label="Austrittsdatum"
|
|
value={m.exit_date ? new Date(String(m.exit_date)).toLocaleDateString('de-DE') : ''}
|
|
/>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* SEPA */}
|
|
<Card className="lg:col-span-2">
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center gap-2">
|
|
<CreditCard className="h-4 w-4" />
|
|
SEPA-Bankverbindung
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="grid grid-cols-2 gap-4 sm:grid-cols-3">
|
|
<DetailRow label="IBAN" value={String(m.iban ?? '')} />
|
|
<DetailRow label="BIC" value={String(m.bic ?? '')} />
|
|
<DetailRow label="Kontoinhaber" value={String(m.account_holder ?? '')} />
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
</CmsPageShell>
|
|
);
|
|
}
|