Merge remote-tracking branch 'origin/main'

# Conflicts:
#	apps/web/app/[locale]/home/[account]/members-cms/[memberId]/page.tsx
This commit is contained in:
T. Zehetbauer
2026-04-02 23:37:19 +02:00
13 changed files with 127 additions and 71 deletions

View File

@@ -22,6 +22,7 @@ ARG NEXT_PUBLIC_ENABLE_FISCHEREI=true
ARG NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=true ARG NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=true
ARG NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=true ARG NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=true
ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
ARG NEXT_PUBLIC_BILLING_PROVIDER=stripe
ENV NEXT_PUBLIC_CI=${NEXT_PUBLIC_CI} ENV NEXT_PUBLIC_CI=${NEXT_PUBLIC_CI}
ENV NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL} ENV NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL}
ENV NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} ENV NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL}
@@ -31,6 +32,7 @@ ENV NEXT_PUBLIC_ENABLE_FISCHEREI=${NEXT_PUBLIC_ENABLE_FISCHEREI}
ENV NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=${NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS} ENV NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=${NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS}
ENV NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=${NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG} ENV NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=${NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG}
ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY} ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
ENV NEXT_PUBLIC_BILLING_PROVIDER=${NEXT_PUBLIC_BILLING_PROVIDER}
RUN pnpm --filter web build RUN pnpm --filter web build
# --- Run --- # --- Run ---

View File

@@ -126,7 +126,7 @@ export default async function BookingsPage({
icon={<CalendarCheck className="h-5 w-5" />} icon={<CalendarCheck className="h-5 w-5" />}
/> />
<StatsCard <StatsCard
title={t('common.of')} title={t('list.total')}
value={total} value={total}
icon={<Euro className="h-5 w-5" />} icon={<Euro className="h-5 w-5" />}
/> />

View File

@@ -138,7 +138,7 @@ export default async function EventsPage({ params, searchParams }: PageProps) {
{t('capacity')} {t('capacity')}
</th> </th>
<th scope="col" className="p-3 text-left font-medium"> <th scope="col" className="p-3 text-left font-medium">
{t('status')} {t('statusLabel')}
</th> </th>
<th scope="col" className="p-3 text-right font-medium"> <th scope="col" className="p-3 text-right font-medium">
{t('registrations')} {t('registrations')}

View File

@@ -116,7 +116,7 @@ export default async function EventRegistrationsPage({ params }: PageProps) {
{t('eventDate')} {t('eventDate')}
</th> </th>
<th scope="col" className="p-3 text-left font-medium"> <th scope="col" className="p-3 text-left font-medium">
{t('status')} {t('statusLabel')}
</th> </th>
<th scope="col" className="p-3 text-right font-medium"> <th scope="col" className="p-3 text-right font-medium">
{t('capacity')} {t('capacity')}

View File

@@ -144,13 +144,13 @@ export default async function FinancePage({ params, searchParams }: PageProps) {
{/* Toolbar */} {/* Toolbar */}
<ListToolbar <ListToolbar
searchPlaceholder={t('common.showAll')} searchPlaceholder={t('common.searchPlaceholder')}
filters={[ filters={[
{ {
param: 'status', param: 'status',
label: t('common.status'), label: t('common.status'),
options: [ options: [
{ value: '', label: t('common.noData') }, { value: '', label: t('common.all') },
{ value: 'draft', label: t('status.draft') }, { value: 'draft', label: t('status.draft') },
{ value: 'ready', label: t('sepa.newBatch') }, { value: 'ready', label: t('sepa.newBatch') },
{ value: 'sent', label: t('status.sent') }, { value: 'sent', label: t('status.sent') },

View File

@@ -9,6 +9,8 @@ interface CmsPageShellProps {
account: string; account: string;
title: string; title: string;
description?: string; description?: string;
/** Override breadcrumb labels for URL path segments (e.g. UUID → name) */
breadcrumbValues?: Record<string, string>;
children: ReactNode; children: ReactNode;
} }
@@ -20,6 +22,7 @@ export function CmsPageShell({
account, account,
title, title,
description, description,
breadcrumbValues,
children, children,
}: CmsPageShellProps) { }: CmsPageShellProps) {
return ( return (
@@ -28,7 +31,11 @@ export function CmsPageShell({
account={account} account={account}
title={title} title={title}
description={ description={
description !== undefined ? description : <AppBreadcrumbs /> description !== undefined ? (
description
) : (
<AppBreadcrumbs values={breadcrumbValues} />
)
} }
/> />

View File

@@ -33,7 +33,7 @@ export default createBillingSchema({
interval: 'month', interval: 'month',
lineItems: [ lineItems: [
{ {
id: 'price_starter_monthly', id: 'price_1THsqKKttnWb7SsFttMu9VzG',
name: 'Starter', name: 'Starter',
cost: 29, cost: 29,
type: 'flat' as const, type: 'flat' as const,
@@ -47,7 +47,7 @@ export default createBillingSchema({
interval: 'year', interval: 'year',
lineItems: [ lineItems: [
{ {
id: 'price_starter_yearly', id: 'price_1THsqLKttnWb7SsFgvjsKXzs',
name: 'Starter', name: 'Starter',
cost: 290, cost: 290,
type: 'flat' as const, type: 'flat' as const,
@@ -82,7 +82,7 @@ export default createBillingSchema({
interval: 'month', interval: 'month',
lineItems: [ lineItems: [
{ {
id: 'price_pro_monthly', id: 'price_1THsqLKttnWb7SsFlWPf5IdP',
name: 'Pro', name: 'Pro',
cost: 59, cost: 59,
type: 'flat' as const, type: 'flat' as const,
@@ -96,7 +96,7 @@ export default createBillingSchema({
interval: 'year', interval: 'year',
lineItems: [ lineItems: [
{ {
id: 'price_pro_yearly', id: 'price_1THsqMKttnWb7SsFZq3A4QkU',
name: 'Pro', name: 'Pro',
cost: 590, cost: 590,
type: 'flat' as const, type: 'flat' as const,
@@ -130,7 +130,7 @@ export default createBillingSchema({
interval: 'month', interval: 'month',
lineItems: [ lineItems: [
{ {
id: 'price_verband_monthly', id: 'price_1THsqNKttnWb7SsFGv7YskgJ',
name: 'Verband', name: 'Verband',
cost: 199, cost: 199,
type: 'flat' as const, type: 'flat' as const,
@@ -144,7 +144,7 @@ export default createBillingSchema({
interval: 'year', interval: 'year',
lineItems: [ lineItems: [
{ {
id: 'price_verband_yearly', id: 'price_1THsqNKttnWb7SsFhNl2bVn8',
name: 'Verband', name: 'Verband',
cost: 1990, cost: 1990,
type: 'flat' as const, type: 'flat' as const,
@@ -178,7 +178,7 @@ export default createBillingSchema({
interval: 'month', interval: 'month',
lineItems: [ lineItems: [
{ {
id: 'price_enterprise_monthly', id: 'price_1THsqOKttnWb7SsFlLjfLw72',
name: 'Enterprise', name: 'Enterprise',
cost: 349, cost: 349,
type: 'flat' as const, type: 'flat' as const,
@@ -192,7 +192,7 @@ export default createBillingSchema({
interval: 'year', interval: 'year',
lineItems: [ lineItems: [
{ {
id: 'price_enterprise_yearly', id: 'price_1THsqOKttnWb7SsF8Sr12isW',
name: 'Enterprise', name: 'Enterprise',
cost: 3490, cost: 3490,
type: 'flat' as const, type: 'flat' as const,

View File

@@ -304,34 +304,54 @@
"paginationNext": "Weiter →" "paginationNext": "Weiter →"
}, },
"permissions": { "permissions": {
"modules.read": "Module lesen", "modules": {
"modules.write": "Module bearbeiten", "read": "Module lesen",
"modules.delete": "Module löschen", "write": "Module bearbeiten",
"modules.insert": "Datensätze erstellen", "delete": "Module löschen",
"modules.lock": "Datensätze sperren", "insert": "Datensätze erstellen",
"modules.import": "Daten importieren", "lock": "Datensätze sperren",
"modules.export": "Daten exportieren", "import": "Daten importieren",
"modules.print": "Drucken", "export": "Daten exportieren",
"modules.manage": "Module verwalten", "print": "Drucken",
"members.read": "Mitglieder lesen", "manage": "Module verwalten"
"members.write": "Mitglieder bearbeiten", },
"courses.read": "Kurse lesen", "members": {
"courses.write": "Kurse bearbeiten", "read": "Mitglieder lesen",
"bookings.read": "Buchungen lesen", "write": "Mitglieder bearbeiten"
"bookings.write": "Buchungen bearbeiten", },
"finance.read": "Finanzen lesen", "courses": {
"finance.write": "Finanzen bearbeiten", "read": "Kurse lesen",
"finance.sepa": "SEPA-Einzüge ausführen", "write": "Kurse bearbeiten"
"documents.generate": "Dokumente generieren", },
"newsletter.send": "Newsletter versenden", "bookings": {
"fischerei.read": "Fischerei lesen", "read": "Buchungen lesen",
"fischerei.write": "Fischerei bearbeiten", "write": "Buchungen bearbeiten"
"meetings.read": "Sitzungsprotokolle lesen", },
"meetings.write": "Sitzungsprotokolle bearbeiten", "finance": {
"meetings.delete": "Sitzungsprotokolle löschen", "read": "Finanzen lesen",
"verband.read": "Verbandsverwaltung lesen", "write": "Finanzen bearbeiten",
"verband.write": "Verbandsverwaltung bearbeiten", "sepa": "SEPA-Einzüge ausführen"
"verband.delete": "Verbandsverwaltung löschen" },
"documents": {
"generate": "Dokumente generieren"
},
"newsletter": {
"send": "Newsletter versenden"
},
"fischerei": {
"read": "Fischerei lesen",
"write": "Fischerei bearbeiten"
},
"meetings": {
"read": "Sitzungsprotokolle lesen",
"write": "Sitzungsprotokolle bearbeiten",
"delete": "Sitzungsprotokolle löschen"
},
"verband": {
"read": "Verbandsverwaltung lesen",
"write": "Verbandsverwaltung bearbeiten",
"delete": "Verbandsverwaltung löschen"
}
}, },
"status": { "status": {
"active": "Aktiv", "active": "Aktiv",

View File

@@ -146,7 +146,9 @@
"next": "Weiter", "next": "Weiter",
"type": "Typ", "type": "Typ",
"date": "Datum", "date": "Datum",
"description": "Beschreibung" "description": "Beschreibung",
"searchPlaceholder": "Rechnung suchen...",
"all": "Alle"
}, },
"status": { "status": {
"draft": "Entwurf", "draft": "Entwurf",

View File

@@ -295,26 +295,40 @@
"paginationNext": "Next →" "paginationNext": "Next →"
}, },
"permissions": { "permissions": {
"modules.read": "Read Modules", "modules": {
"modules.write": "Edit Modules", "read": "Read Modules",
"modules.delete": "Delete Modules", "write": "Edit Modules",
"modules.insert": "Create Records", "delete": "Delete Modules",
"modules.lock": "Lock Records", "insert": "Create Records",
"modules.import": "Import Data", "lock": "Lock Records",
"modules.export": "Export Data", "import": "Import Data",
"modules.print": "Print", "export": "Export Data",
"modules.manage": "Manage Modules", "print": "Print",
"members.read": "Read Members", "manage": "Manage Modules"
"members.write": "Edit Members", },
"courses.read": "Read Courses", "members": {
"courses.write": "Edit Courses", "read": "Read Members",
"bookings.read": "Read Bookings", "write": "Edit Members"
"bookings.write": "Edit Bookings", },
"finance.read": "Read Finance", "courses": {
"finance.write": "Edit Finance", "read": "Read Courses",
"finance.sepa": "Execute SEPA Collections", "write": "Edit Courses"
"documents.generate": "Generate Documents", },
"newsletter.send": "Send Newsletter", "bookings": {
"read": "Read Bookings",
"write": "Edit Bookings"
},
"finance": {
"read": "Read Finance",
"write": "Edit Finance",
"sepa": "Execute SEPA Collections"
},
"documents": {
"generate": "Generate Documents"
},
"newsletter": {
"send": "Send Newsletter"
},
"verband": { "verband": {
"delete": "Delete Association Data" "delete": "Delete Association Data"
} }

View File

@@ -146,7 +146,9 @@
"next": "Next", "next": "Next",
"type": "Type", "type": "Type",
"date": "Date", "date": "Date",
"description": "Description" "description": "Description",
"searchPlaceholder": "Search invoices...",
"all": "All"
}, },
"status": { "status": {
"draft": "Draft", "draft": "Draft",

View File

@@ -330,6 +330,9 @@ services:
# Browser-side Supabase URL — goes through external domain (Traefik → Kong) # Browser-side Supabase URL — goes through external domain (Traefik → Kong)
NEXT_PUBLIC_SUPABASE_URL: ${API_EXTERNAL_URL:-http://localhost:8000} NEXT_PUBLIC_SUPABASE_URL: ${API_EXTERNAL_URL:-http://localhost:8000}
NEXT_PUBLIC_SUPABASE_PUBLIC_KEY: ${SUPABASE_ANON_KEY} NEXT_PUBLIC_SUPABASE_PUBLIC_KEY: ${SUPABASE_ANON_KEY}
# Stripe (build-time)
NEXT_PUBLIC_BILLING_PROVIDER: stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
supabase-kong: supabase-kong:
@@ -352,12 +355,17 @@ services:
NEXT_PUBLIC_ENABLE_THEME_TOGGLE: 'true' NEXT_PUBLIC_ENABLE_THEME_TOGGLE: 'true'
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS: 'true' NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS: 'true'
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION: 'true' NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION: 'true'
NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING: 'false' NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING: 'true'
NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING: 'false' NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING: 'true'
NEXT_PUBLIC_ENABLE_NOTIFICATIONS: 'true' NEXT_PUBLIC_ENABLE_NOTIFICATIONS: 'true'
NEXT_PUBLIC_ENABLE_FISCHEREI: 'true' NEXT_PUBLIC_ENABLE_FISCHEREI: 'true'
NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS: 'true' NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS: 'true'
NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG: 'true' NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG: 'true'
# Stripe (runtime)
NEXT_PUBLIC_BILLING_PROVIDER: stripe
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
volumes: volumes:
supabase-db-data: supabase-db-data:

View File

@@ -95,7 +95,8 @@ export function ApplicationWorkflow({
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h2 className="text-lg font-semibold">Aufnahmeanträge</h2> <h2 className="text-lg font-semibold">Aufnahmeanträge</h2>
<p className="text-muted-foreground text-sm"> <p className="text-muted-foreground text-sm">
{applications.length} Antrag{applications.length !== 1 ? 'e' : ''} {applications.length}{' '}
{applications.length === 1 ? 'Antrag' : 'Anträge'}
</p> </p>
</div> </div>