initial commit
Build & Deployment / Build & Deploy (push) Failing after 5s

This commit is contained in:
Raul Lugo
2026-08-10 17:55:26 +02:00
parent 6429ed3fa3
commit 4ced446c9c
74 changed files with 9242 additions and 30 deletions
+139
View File
@@ -0,0 +1,139 @@
import Link from "next/link"
import { CopyInviteButton } from "@/components/admin/copy-invite-button"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { listInvitations } from "@/lib/db/queries/invitations"
import { getLanguageLabel } from "@/lib/i18n/config"
export const dynamic = "force-dynamic"
function getInviteUrl(token: string) {
return new URL(`/invite/${token}`, process.env.APP_URL ?? "http://localhost:3000").toString()
}
function getStatusVariant(status: string): "default" | "secondary" | "outline" {
if (status === "Attending") return "default"
if (status === "Pending") return "secondary"
return "outline"
}
export default async function GuestsPage() {
const invitations = await listInvitations()
return (
<div className="space-y-6">
<div className="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between">
<div>
<h1 className="text-3xl font-semibold tracking-tight">Guests</h1>
<p className="text-muted-foreground">
Manage invitation groups and private invite links.
</p>
</div>
<Button asChild>
<Link href="/admin/guests/new">Create invitation</Link>
</Button>
</div>
<Card>
<CardHeader>
<CardTitle>Invitation list</CardTitle>
<CardDescription>
One row per invitation group, household, couple, family, or individual guest.
</CardDescription>
</CardHeader>
<CardContent>
{invitations.length === 0 ? (
<div className="flex flex-col items-center justify-center gap-3 rounded-lg border border-dashed p-10 text-center">
<p className="font-medium">No invitations yet</p>
<p className="max-w-sm text-sm text-muted-foreground">
Create the first invitation to generate a private guest link.
</p>
<Button asChild>
<Link href="/admin/guests/new">Create invitation</Link>
</Button>
</div>
) : (
<Table>
<TableHeader>
<TableRow>
<TableHead>Invitation</TableHead>
<TableHead>Language</TableHead>
<TableHead>Members</TableHead>
<TableHead>Status</TableHead>
<TableHead>Contact</TableHead>
<TableHead className="text-right">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{invitations.map((invitation) => {
const inviteUrl = getInviteUrl(invitation.token)
return (
<TableRow key={invitation.id}>
<TableCell>
<div className="space-y-1">
<Button asChild variant="link" className="h-auto p-0 font-medium">
<Link href={`/admin/guests/${invitation.id}`}>
{invitation.displayName}
</Link>
</Button>
<p className="text-xs text-muted-foreground">
Max party size: {invitation.maxPartySize}
</p>
</div>
</TableCell>
<TableCell>{getLanguageLabel(invitation.language)}</TableCell>
<TableCell>
<div className="space-y-1">
<p>{invitation.membersCount}</p>
<p className="text-xs text-muted-foreground">
{invitation.attendingCount} attending · {invitation.pendingCount} pending
</p>
</div>
</TableCell>
<TableCell>
<Badge variant={getStatusVariant(invitation.derivedStatus)}>
{invitation.derivedStatus}
</Badge>
</TableCell>
<TableCell>
<div className="space-y-1 text-sm">
<p>{invitation.contactEmail ?? "—"}</p>
<p className="text-muted-foreground">{invitation.contactPhone ?? "—"}</p>
</div>
</TableCell>
<TableCell>
<div className="flex justify-end gap-2">
<CopyInviteButton inviteUrl={inviteUrl} />
<Button asChild size="sm">
<Link href={`/admin/guests/${invitation.id}`}>View</Link>
</Button>
</div>
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
)}
</CardContent>
</Card>
</div>
)
}