feat: pre-existing local changes — fischerei, verband, modules, members, packages
Some checks failed
Workflow / ʦ TypeScript (push) Failing after 6m20s
Workflow / ⚫️ Test (push) Has been skipped

Commits all remaining uncommitted local work:

- apps/web: fischerei, verband, modules, members-cms, documents,
  newsletter, meetings, site-builder, courses, bookings, events,
  finance pages and components
- apps/web: marketing page updates, layout, paths config,
  next.config.mjs, styles/makerkit.css
- apps/web/i18n: documents, fischerei, marketing, verband (de+en)
- packages/features: finance, fischerei, member-management,
  module-builder, newsletter, sitzungsprotokolle, verbandsverwaltung
  server APIs and components
- packages/ui: button.tsx updates
- pnpm-lock.yaml
This commit is contained in:
Zaid Marzguioui
2026-04-02 01:19:54 +02:00
parent a1719671df
commit b26e5aaafa
153 changed files with 2329 additions and 1227 deletions

View File

@@ -12,6 +12,7 @@ import {
Activity,
BedDouble,
} from 'lucide-react';
import { getTranslations } from 'next-intl/server';
import { createBookingManagementApi } from '@kit/booking-management/api';
import { createCourseManagementApi } from '@kit/course-management/api';
@@ -44,6 +45,7 @@ export default async function TeamAccountHomePage({
}: TeamAccountHomePageProps) {
const { account } = await params;
const client = getSupabaseServerClient();
const t = await getTranslations('common');
const { data: acct } = await client
.from('accounts')
@@ -111,41 +113,47 @@ export default async function TeamAccountHomePage({
{/* Stats Row */}
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
<StatsCard
title="Mitglieder"
title={t('dashboard.members')}
value={memberStats.active}
icon={<UserCheck className="h-5 w-5" />}
description={`${memberStats.total} gesamt, ${memberStats.pending} ausstehend`}
icon={<UserCheck className="h-5 w-5" aria-hidden="true" />}
description={t('dashboard.membersDescription', {
total: memberStats.total,
pending: memberStats.pending,
})}
/>
<StatsCard
title="Kurse"
title={t('dashboard.courses')}
value={courseStats.openCourses}
icon={<GraduationCap className="h-5 w-5" />}
description={`${courseStats.totalCourses} gesamt, ${courseStats.totalParticipants} Teilnehmer`}
icon={<GraduationCap className="h-5 w-5" aria-hidden="true" />}
description={t('dashboard.coursesDescription', {
total: courseStats.totalCourses,
participants: courseStats.totalParticipants,
})}
/>
<StatsCard
title="Offene Rechnungen"
title={t('dashboard.openInvoices')}
value={openInvoices.length}
icon={<FileText className="h-5 w-5" />}
description="Entwürfe zum Versenden"
icon={<FileText className="h-5 w-5" aria-hidden="true" />}
description={t('dashboard.openInvoicesDescription')}
/>
<StatsCard
title="Newsletter"
title={t('dashboard.newsletters')}
value={newsletters.length}
icon={<Mail className="h-5 w-5" />}
description="Erstellt"
icon={<Mail className="h-5 w-5" aria-hidden="true" />}
description={t('dashboard.newslettersDescription')}
/>
</div>
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
{/* Letzte Aktivität */}
{/* Recent Activity */}
<Card className="lg:col-span-2">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Activity className="h-5 w-5" />
Letzte Aktivität
<Activity className="h-5 w-5" aria-hidden="true" />
{t('dashboard.recentActivity')}
</CardTitle>
<CardDescription>
Aktuelle Buchungen und Veranstaltungen
{t('dashboard.recentActivityDescription')}
</CardDescription>
</CardHeader>
<CardContent>
@@ -160,14 +168,14 @@ export default async function TeamAccountHomePage({
>
<div className="flex items-center gap-3">
<div className="rounded-full bg-blue-500/10 p-2 text-blue-600">
<BedDouble className="h-4 w-4" />
<BedDouble className="h-4 w-4" aria-hidden="true" />
</div>
<div>
<Link
href={`/home/${account}/bookings/${String(booking.id)}`}
className="text-sm font-medium hover:underline"
>
Buchung{' '}
{t('dashboard.bookingFrom')}{' '}
{booking.check_in
? formatDate(booking.check_in as string)
: '—'}
@@ -194,7 +202,10 @@ export default async function TeamAccountHomePage({
>
<div className="flex items-center gap-3">
<div className="rounded-full bg-amber-500/10 p-2 text-amber-600">
<CalendarDays className="h-4 w-4" />
<CalendarDays
className="h-4 w-4"
aria-hidden="true"
/>
</div>
<div>
<Link
@@ -216,20 +227,22 @@ export default async function TeamAccountHomePage({
{bookings.data.length === 0 && events.data.length === 0 && (
<EmptyState
icon={<Activity className="h-8 w-8" />}
title="Noch keine Aktivitäten"
description="Aktuelle Buchungen und Veranstaltungen werden hier angezeigt."
icon={<Activity className="h-8 w-8" aria-hidden="true" />}
title={t('dashboard.recentActivityEmpty')}
description={t('dashboard.recentActivityEmptyDescription')}
/>
)}
</div>
</CardContent>
</Card>
{/* Schnellaktionen */}
{/* Quick Actions */}
<Card>
<CardHeader>
<CardTitle>Schnellaktionen</CardTitle>
<CardDescription>Häufig verwendete Aktionen</CardDescription>
<CardTitle>{t('dashboard.quickActions')}</CardTitle>
<CardDescription>
{t('dashboard.quickActionsDescription')}
</CardDescription>
</CardHeader>
<CardContent className="flex flex-col gap-2">
<Link
@@ -237,10 +250,10 @@ export default async function TeamAccountHomePage({
className="border-border bg-background hover:bg-muted hover:text-foreground inline-flex w-full items-center justify-between gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-all"
>
<span className="flex items-center gap-2">
<UserPlus className="h-4 w-4" />
Neues Mitglied
<UserPlus className="h-4 w-4" aria-hidden="true" />
{t('dashboard.newMember')}
</span>
<ArrowRight className="h-4 w-4" />
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
<Link
@@ -248,10 +261,10 @@ export default async function TeamAccountHomePage({
className="border-border bg-background hover:bg-muted hover:text-foreground inline-flex w-full items-center justify-between gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-all"
>
<span className="flex items-center gap-2">
<GraduationCap className="h-4 w-4" />
Neuer Kurs
<GraduationCap className="h-4 w-4" aria-hidden="true" />
{t('dashboard.newCourse')}
</span>
<ArrowRight className="h-4 w-4" />
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
<Link
@@ -260,9 +273,9 @@ export default async function TeamAccountHomePage({
>
<span className="flex items-center gap-2">
<Mail className="h-4 w-4" />
Newsletter erstellen
{t('dashboard.createNewsletter')}
</span>
<ArrowRight className="h-4 w-4" />
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
<Link
@@ -270,10 +283,10 @@ export default async function TeamAccountHomePage({
className="border-border bg-background hover:bg-muted hover:text-foreground inline-flex w-full items-center justify-between gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-all"
>
<span className="flex items-center gap-2">
<BedDouble className="h-4 w-4" />
Neue Buchung
<BedDouble className="h-4 w-4" aria-hidden="true" />
{t('dashboard.newBooking')}
</span>
<ArrowRight className="h-4 w-4" />
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
<Link
@@ -281,98 +294,14 @@ export default async function TeamAccountHomePage({
className="border-border bg-background hover:bg-muted hover:text-foreground inline-flex w-full items-center justify-between gap-2 rounded-lg border px-4 py-2 text-sm font-medium transition-all"
>
<span className="flex items-center gap-2">
<Plus className="h-4 w-4" />
Neue Veranstaltung
<Plus className="h-4 w-4" aria-hidden="true" />
{t('dashboard.newEvent')}
</span>
<ArrowRight className="h-4 w-4" />
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
</CardContent>
</Card>
</div>
{/* Module Overview Row */}
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
<Card>
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-muted-foreground text-sm font-medium">
Buchungen
</p>
<p className="text-2xl font-bold">{bookings.total}</p>
<p className="text-muted-foreground text-xs">
{
bookings.data.filter(
(b: Record<string, unknown>) =>
b.status === 'confirmed' || b.status === 'checked_in',
).length
}{' '}
aktiv
</p>
</div>
<Link
href={`/home/${account}/bookings`}
className="hover:bg-muted hover:text-foreground inline-flex h-9 w-9 items-center justify-center rounded-lg text-sm font-medium transition-all"
>
<ArrowRight className="h-4 w-4" />
</Link>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-muted-foreground text-sm font-medium">
Veranstaltungen
</p>
<p className="text-2xl font-bold">{events.total}</p>
<p className="text-muted-foreground text-xs">
{
events.data.filter(
(e: Record<string, unknown>) =>
e.status === 'published' ||
e.status === 'registration_open',
).length
}{' '}
aktiv
</p>
</div>
<Link
href={`/home/${account}/events`}
className="hover:bg-muted hover:text-foreground inline-flex h-9 w-9 items-center justify-center rounded-lg text-sm font-medium transition-all"
>
<ArrowRight className="h-4 w-4" />
</Link>
</div>
</CardContent>
</Card>
<Card>
<CardContent className="p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-muted-foreground text-sm font-medium">
Kurse abgeschlossen
</p>
<p className="text-2xl font-bold">
{courseStats.completedCourses}
</p>
<p className="text-muted-foreground text-xs">
von {courseStats.totalCourses} insgesamt
</p>
</div>
<Link
href={`/home/${account}/courses`}
className="hover:bg-muted hover:text-foreground inline-flex h-9 w-9 items-center justify-center rounded-lg text-sm font-medium transition-all"
>
<ArrowRight className="h-4 w-4" />
</Link>
</div>
</CardContent>
</Card>
</div>
</div>
</CmsPageShell>
);