Add account hierarchy framework with migrations, RLS policies, and UI components
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
User,
|
||||
} from 'lucide-react';
|
||||
|
||||
import { formatDate } from '@kit/shared/dates';
|
||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
import { Badge } from '@kit/ui/badge';
|
||||
import { Button } from '@kit/ui/button';
|
||||
@@ -21,8 +22,8 @@ import {
|
||||
CardTitle,
|
||||
} from '@kit/ui/card';
|
||||
|
||||
import { CmsPageShell } from '~/components/cms-page-shell';
|
||||
import { AccountNotFound } from '~/components/account-not-found';
|
||||
import { CmsPageShell } from '~/components/cms-page-shell';
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{ account: string; bookingId: string }>;
|
||||
@@ -124,9 +125,7 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
{STATUS_LABEL[status] ?? status}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
ID: {bookingId}
|
||||
</p>
|
||||
<p className="text-muted-foreground text-sm">ID: {bookingId}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -144,7 +143,7 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
{room ? (
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Zimmernummer
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
@@ -153,14 +152,14 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
</div>
|
||||
{room.name && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Name
|
||||
</span>
|
||||
<span className="font-medium">{String(room.name)}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">Typ</span>
|
||||
<span className="text-muted-foreground text-sm">Typ</span>
|
||||
<span className="font-medium">
|
||||
{String(room.room_type ?? '—')}
|
||||
</span>
|
||||
@@ -186,29 +185,25 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
{guest ? (
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">Name</span>
|
||||
<span className="text-muted-foreground text-sm">Name</span>
|
||||
<span className="font-medium">
|
||||
{String(guest.first_name)} {String(guest.last_name)}
|
||||
</span>
|
||||
</div>
|
||||
{guest.email && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
E-Mail
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{String(guest.email)}
|
||||
</span>
|
||||
<span className="font-medium">{String(guest.email)}</span>
|
||||
</div>
|
||||
)}
|
||||
{guest.phone && (
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Telefon
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{String(guest.phone)}
|
||||
</span>
|
||||
<span className="font-medium">{String(guest.phone)}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -231,56 +226,30 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
<CardContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Check-in
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{booking.check_in
|
||||
? new Date(String(booking.check_in)).toLocaleDateString(
|
||||
'de-DE',
|
||||
{
|
||||
weekday: 'short',
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
},
|
||||
)
|
||||
: '—'}
|
||||
{formatDate(booking.check_in)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Check-out
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{booking.check_out
|
||||
? new Date(String(booking.check_out)).toLocaleDateString(
|
||||
'de-DE',
|
||||
{
|
||||
weekday: 'short',
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
},
|
||||
)
|
||||
: '—'}
|
||||
{formatDate(booking.check_out)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Erwachsene
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{booking.adults ?? '—'}
|
||||
</span>
|
||||
<span className="font-medium">{booking.adults ?? '—'}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
Kinder
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{booking.children ?? 0}
|
||||
</span>
|
||||
<span className="text-muted-foreground text-sm">Kinder</span>
|
||||
<span className="font-medium">{booking.children ?? 0}</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -294,7 +263,7 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
<CardContent>
|
||||
<div className="space-y-2">
|
||||
<div className="flex justify-between">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Gesamtpreis
|
||||
</span>
|
||||
<span className="text-2xl font-bold">
|
||||
@@ -305,7 +274,7 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
</div>
|
||||
{booking.notes && (
|
||||
<div className="border-t pt-2">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
Notizen
|
||||
</span>
|
||||
<p className="mt-1 text-sm">{String(booking.notes)}</p>
|
||||
@@ -320,9 +289,7 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Aktionen</CardTitle>
|
||||
<CardDescription>
|
||||
Status der Buchung ändern
|
||||
</CardDescription>
|
||||
<CardDescription>Status der Buchung ändern</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex flex-wrap gap-3">
|
||||
@@ -350,10 +317,10 @@ export default async function BookingDetailPage({ params }: PageProps) {
|
||||
)}
|
||||
|
||||
{status === 'cancelled' || status === 'checked_out' ? (
|
||||
<p className="text-sm text-muted-foreground py-2">
|
||||
<p className="text-muted-foreground py-2 text-sm">
|
||||
Diese Buchung ist{' '}
|
||||
{status === 'cancelled' ? 'storniert' : 'abgeschlossen'} — keine
|
||||
weiteren Aktionen verfügbar.
|
||||
{status === 'cancelled' ? 'storniert' : 'abgeschlossen'} —
|
||||
keine weiteren Aktionen verfügbar.
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user