Add account hierarchy framework with migrations, RLS policies, and UI components

This commit is contained in:
T. Zehetbauer
2026-03-31 22:18:04 +02:00
parent 7e7da0b465
commit 59546ad6d2
262 changed files with 11671 additions and 3927 deletions

View File

@@ -1,9 +1,12 @@
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { createMeetingsApi } from '@kit/sitzungsprotokolle/api';
import { MeetingsTabNavigation, MeetingsDashboard } from '@kit/sitzungsprotokolle/components';
import {
MeetingsTabNavigation,
MeetingsDashboard,
} from '@kit/sitzungsprotokolle/components';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
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 }>;

View File

@@ -2,18 +2,20 @@ import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';
import { formatDateFull } from '@kit/shared/dates';
import { createMeetingsApi } from '@kit/sitzungsprotokolle/api';
import {
MeetingsTabNavigation,
ProtocolItemsList,
} from '@kit/sitzungsprotokolle/components';
import { MEETING_TYPE_LABELS } from '@kit/sitzungsprotokolle/lib/meetings-constants';
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 { getSupabaseServerClient } from '@kit/supabase/server-client';
import { createMeetingsApi } from '@kit/sitzungsprotokolle/api';
import { MeetingsTabNavigation, ProtocolItemsList } from '@kit/sitzungsprotokolle/components';
import { CmsPageShell } from '~/components/cms-page-shell';
import { MEETING_TYPE_LABELS } from '@kit/sitzungsprotokolle/lib/meetings-constants';
import { AccountNotFound } from '~/components/account-not-found';
import { CmsPageShell } from '~/components/cms-page-shell';
interface PageProps {
params: Promise<{ account: string; protocolId: string }>;
@@ -39,9 +41,12 @@ export default async function ProtocolDetailPage({ params }: PageProps) {
} catch {
return (
<CmsPageShell account={account} title="Sitzungsprotokolle">
<div className="text-center py-12">
<div className="py-12 text-center">
<h2 className="text-lg font-semibold">Protokoll nicht gefunden</h2>
<Link href={`/home/${account}/meetings/protocols`} className="mt-4 inline-block">
<Link
href={`/home/${account}/meetings/protocols`}
className="mt-4 inline-block"
>
<Button variant="outline">Zurück zur Übersicht</Button>
</Link>
</div>
@@ -72,18 +77,12 @@ export default async function ProtocolDetailPage({ params }: PageProps) {
<div className="flex items-start justify-between">
<div>
<CardTitle className="text-xl">{protocol.title}</CardTitle>
<div className="mt-2 flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
<span>
{new Date(protocol.meeting_date).toLocaleDateString('de-DE', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
})}
</span>
<div className="text-muted-foreground mt-2 flex flex-wrap items-center gap-2 text-sm">
<span>{formatDateFull(protocol.meeting_date)}</span>
<span>·</span>
<Badge variant="secondary">
{MEETING_TYPE_LABELS[protocol.meeting_type] ?? protocol.meeting_type}
{MEETING_TYPE_LABELS[protocol.meeting_type] ??
protocol.meeting_type}
</Badge>
{protocol.is_published ? (
<Badge variant="default">Veröffentlicht</Badge>
@@ -97,20 +96,28 @@ export default async function ProtocolDetailPage({ params }: PageProps) {
<CardContent className="grid grid-cols-1 gap-4 sm:grid-cols-2">
{protocol.location && (
<div>
<p className="text-sm font-medium text-muted-foreground">Ort</p>
<p className="text-muted-foreground text-sm font-medium">Ort</p>
<p className="text-sm">{protocol.location}</p>
</div>
)}
{protocol.attendees && (
<div className="sm:col-span-2">
<p className="text-sm font-medium text-muted-foreground">Teilnehmer</p>
<p className="text-sm whitespace-pre-line">{protocol.attendees}</p>
<p className="text-muted-foreground text-sm font-medium">
Teilnehmer
</p>
<p className="text-sm whitespace-pre-line">
{protocol.attendees}
</p>
</div>
)}
{protocol.remarks && (
<div className="sm:col-span-2">
<p className="text-sm font-medium text-muted-foreground">Anmerkungen</p>
<p className="text-sm whitespace-pre-line">{protocol.remarks}</p>
<p className="text-muted-foreground text-sm font-medium">
Anmerkungen
</p>
<p className="text-sm whitespace-pre-line">
{protocol.remarks}
</p>
</div>
)}
</CardContent>

View File

@@ -1,8 +1,11 @@
import {
MeetingsTabNavigation,
CreateProtocolForm,
} from '@kit/sitzungsprotokolle/components';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { MeetingsTabNavigation, CreateProtocolForm } from '@kit/sitzungsprotokolle/components';
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 }>;

View File

@@ -1,16 +1,22 @@
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { createMeetingsApi } from '@kit/sitzungsprotokolle/api';
import { MeetingsTabNavigation, ProtocolsDataTable } from '@kit/sitzungsprotokolle/components';
import {
MeetingsTabNavigation,
ProtocolsDataTable,
} from '@kit/sitzungsprotokolle/components';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
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 }>;
searchParams: Promise<Record<string, string | string[] | undefined>>;
}
export default async function ProtocolsPage({ params, searchParams }: PageProps) {
export default async function ProtocolsPage({
params,
searchParams,
}: PageProps) {
const { account } = await params;
const sp = await searchParams;
const client = getSupabaseServerClient();

View File

@@ -1,9 +1,12 @@
import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { createMeetingsApi } from '@kit/sitzungsprotokolle/api';
import { MeetingsTabNavigation, OpenTasksView } from '@kit/sitzungsprotokolle/components';
import {
MeetingsTabNavigation,
OpenTasksView,
} from '@kit/sitzungsprotokolle/components';
import { getSupabaseServerClient } from '@kit/supabase/server-client';
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 }>;
@@ -36,7 +39,8 @@ export default async function TasksPage({ params, searchParams }: PageProps) {
<div>
<h1 className="text-2xl font-bold">Offene Aufgaben</h1>
<p className="text-muted-foreground">
Alle offenen und in Bearbeitung befindlichen Tagesordnungspunkte über alle Protokolle.
Alle offenen und in Bearbeitung befindlichen Tagesordnungspunkte
über alle Protokolle.
</p>
</div>
<OpenTasksView