diff --git a/Dockerfile b/Dockerfile index 3d280e6aa..d14450b2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,6 +22,7 @@ ARG NEXT_PUBLIC_ENABLE_FISCHEREI=true ARG NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS=true ARG NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG=true ARG NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= +ARG NEXT_PUBLIC_BILLING_PROVIDER=stripe ENV NEXT_PUBLIC_CI=${NEXT_PUBLIC_CI} ENV NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_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_VERBANDSVERWALTUNG=${NEXT_PUBLIC_ENABLE_VERBANDSVERWALTUNG} 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 --- diff --git a/apps/web/app/[locale]/home/[account]/bookings/page.tsx b/apps/web/app/[locale]/home/[account]/bookings/page.tsx index 5acea6ee0..026d99a8c 100644 --- a/apps/web/app/[locale]/home/[account]/bookings/page.tsx +++ b/apps/web/app/[locale]/home/[account]/bookings/page.tsx @@ -126,7 +126,7 @@ export default async function BookingsPage({ icon={} /> } /> diff --git a/apps/web/app/[locale]/home/[account]/events/page.tsx b/apps/web/app/[locale]/home/[account]/events/page.tsx index d9b22abe2..bc680e686 100644 --- a/apps/web/app/[locale]/home/[account]/events/page.tsx +++ b/apps/web/app/[locale]/home/[account]/events/page.tsx @@ -138,7 +138,7 @@ export default async function EventsPage({ params, searchParams }: PageProps) { {t('capacity')} - {t('status')} + {t('statusLabel')} {t('registrations')} diff --git a/apps/web/app/[locale]/home/[account]/events/registrations/page.tsx b/apps/web/app/[locale]/home/[account]/events/registrations/page.tsx index e9c7d3968..55a419d83 100644 --- a/apps/web/app/[locale]/home/[account]/events/registrations/page.tsx +++ b/apps/web/app/[locale]/home/[account]/events/registrations/page.tsx @@ -116,7 +116,7 @@ export default async function EventRegistrationsPage({ params }: PageProps) { {t('eventDate')} - {t('status')} + {t('statusLabel')} {t('capacity')} diff --git a/apps/web/app/[locale]/home/[account]/finance/page.tsx b/apps/web/app/[locale]/home/[account]/finance/page.tsx index 3f2a186e8..65bc92d14 100644 --- a/apps/web/app/[locale]/home/[account]/finance/page.tsx +++ b/apps/web/app/[locale]/home/[account]/finance/page.tsx @@ -144,13 +144,13 @@ export default async function FinancePage({ params, searchParams }: PageProps) { {/* Toolbar */} ; children: ReactNode; } @@ -20,6 +22,7 @@ export function CmsPageShell({ account, title, description, + breadcrumbValues, children, }: CmsPageShellProps) { return ( @@ -28,7 +31,11 @@ export function CmsPageShell({ account={account} title={title} description={ - description !== undefined ? description : + description !== undefined ? ( + description + ) : ( + + ) } /> diff --git a/apps/web/config/billing.config.ts b/apps/web/config/billing.config.ts index 71b08b732..38ceb7254 100644 --- a/apps/web/config/billing.config.ts +++ b/apps/web/config/billing.config.ts @@ -33,7 +33,7 @@ export default createBillingSchema({ interval: 'month', lineItems: [ { - id: 'price_starter_monthly', + id: 'price_1THsqKKttnWb7SsFttMu9VzG', name: 'Starter', cost: 29, type: 'flat' as const, @@ -47,7 +47,7 @@ export default createBillingSchema({ interval: 'year', lineItems: [ { - id: 'price_starter_yearly', + id: 'price_1THsqLKttnWb7SsFgvjsKXzs', name: 'Starter', cost: 290, type: 'flat' as const, @@ -82,7 +82,7 @@ export default createBillingSchema({ interval: 'month', lineItems: [ { - id: 'price_pro_monthly', + id: 'price_1THsqLKttnWb7SsFlWPf5IdP', name: 'Pro', cost: 59, type: 'flat' as const, @@ -96,7 +96,7 @@ export default createBillingSchema({ interval: 'year', lineItems: [ { - id: 'price_pro_yearly', + id: 'price_1THsqMKttnWb7SsFZq3A4QkU', name: 'Pro', cost: 590, type: 'flat' as const, @@ -130,7 +130,7 @@ export default createBillingSchema({ interval: 'month', lineItems: [ { - id: 'price_verband_monthly', + id: 'price_1THsqNKttnWb7SsFGv7YskgJ', name: 'Verband', cost: 199, type: 'flat' as const, @@ -144,7 +144,7 @@ export default createBillingSchema({ interval: 'year', lineItems: [ { - id: 'price_verband_yearly', + id: 'price_1THsqNKttnWb7SsFhNl2bVn8', name: 'Verband', cost: 1990, type: 'flat' as const, @@ -178,7 +178,7 @@ export default createBillingSchema({ interval: 'month', lineItems: [ { - id: 'price_enterprise_monthly', + id: 'price_1THsqOKttnWb7SsFlLjfLw72', name: 'Enterprise', cost: 349, type: 'flat' as const, @@ -192,7 +192,7 @@ export default createBillingSchema({ interval: 'year', lineItems: [ { - id: 'price_enterprise_yearly', + id: 'price_1THsqOKttnWb7SsF8Sr12isW', name: 'Enterprise', cost: 3490, type: 'flat' as const, diff --git a/apps/web/i18n/messages/de/cms.json b/apps/web/i18n/messages/de/cms.json index 732b48f91..41acb62b7 100644 --- a/apps/web/i18n/messages/de/cms.json +++ b/apps/web/i18n/messages/de/cms.json @@ -304,34 +304,54 @@ "paginationNext": "Weiter →" }, "permissions": { - "modules.read": "Module lesen", - "modules.write": "Module bearbeiten", - "modules.delete": "Module löschen", - "modules.insert": "Datensätze erstellen", - "modules.lock": "Datensätze sperren", - "modules.import": "Daten importieren", - "modules.export": "Daten exportieren", - "modules.print": "Drucken", - "modules.manage": "Module verwalten", - "members.read": "Mitglieder lesen", - "members.write": "Mitglieder bearbeiten", - "courses.read": "Kurse lesen", - "courses.write": "Kurse bearbeiten", - "bookings.read": "Buchungen lesen", - "bookings.write": "Buchungen bearbeiten", - "finance.read": "Finanzen lesen", - "finance.write": "Finanzen bearbeiten", - "finance.sepa": "SEPA-Einzüge ausführen", - "documents.generate": "Dokumente generieren", - "newsletter.send": "Newsletter versenden", - "fischerei.read": "Fischerei lesen", - "fischerei.write": "Fischerei bearbeiten", - "meetings.read": "Sitzungsprotokolle lesen", - "meetings.write": "Sitzungsprotokolle bearbeiten", - "meetings.delete": "Sitzungsprotokolle löschen", - "verband.read": "Verbandsverwaltung lesen", - "verband.write": "Verbandsverwaltung bearbeiten", - "verband.delete": "Verbandsverwaltung löschen" + "modules": { + "read": "Module lesen", + "write": "Module bearbeiten", + "delete": "Module löschen", + "insert": "Datensätze erstellen", + "lock": "Datensätze sperren", + "import": "Daten importieren", + "export": "Daten exportieren", + "print": "Drucken", + "manage": "Module verwalten" + }, + "members": { + "read": "Mitglieder lesen", + "write": "Mitglieder bearbeiten" + }, + "courses": { + "read": "Kurse lesen", + "write": "Kurse bearbeiten" + }, + "bookings": { + "read": "Buchungen lesen", + "write": "Buchungen bearbeiten" + }, + "finance": { + "read": "Finanzen lesen", + "write": "Finanzen bearbeiten", + "sepa": "SEPA-Einzüge ausführen" + }, + "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": { "active": "Aktiv", @@ -812,4 +832,4 @@ "formatExcel": "Excel" } } -} +} \ No newline at end of file diff --git a/apps/web/i18n/messages/de/finance.json b/apps/web/i18n/messages/de/finance.json index 02e8003b0..914bbf19a 100644 --- a/apps/web/i18n/messages/de/finance.json +++ b/apps/web/i18n/messages/de/finance.json @@ -146,7 +146,9 @@ "next": "Weiter", "type": "Typ", "date": "Datum", - "description": "Beschreibung" + "description": "Beschreibung", + "searchPlaceholder": "Rechnung suchen...", + "all": "Alle" }, "status": { "draft": "Entwurf", @@ -160,4 +162,4 @@ "completed": "Abgeschlossen", "failed": "Fehlgeschlagen" } -} +} \ No newline at end of file diff --git a/apps/web/i18n/messages/en/cms.json b/apps/web/i18n/messages/en/cms.json index 027c53567..b45a2c202 100644 --- a/apps/web/i18n/messages/en/cms.json +++ b/apps/web/i18n/messages/en/cms.json @@ -295,26 +295,40 @@ "paginationNext": "Next →" }, "permissions": { - "modules.read": "Read Modules", - "modules.write": "Edit Modules", - "modules.delete": "Delete Modules", - "modules.insert": "Create Records", - "modules.lock": "Lock Records", - "modules.import": "Import Data", - "modules.export": "Export Data", - "modules.print": "Print", - "modules.manage": "Manage Modules", - "members.read": "Read Members", - "members.write": "Edit Members", - "courses.read": "Read Courses", - "courses.write": "Edit Courses", - "bookings.read": "Read Bookings", - "bookings.write": "Edit Bookings", - "finance.read": "Read Finance", - "finance.write": "Edit Finance", - "finance.sepa": "Execute SEPA Collections", - "documents.generate": "Generate Documents", - "newsletter.send": "Send Newsletter", + "modules": { + "read": "Read Modules", + "write": "Edit Modules", + "delete": "Delete Modules", + "insert": "Create Records", + "lock": "Lock Records", + "import": "Import Data", + "export": "Export Data", + "print": "Print", + "manage": "Manage Modules" + }, + "members": { + "read": "Read Members", + "write": "Edit Members" + }, + "courses": { + "read": "Read Courses", + "write": "Edit Courses" + }, + "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": { "delete": "Delete Association Data" } @@ -338,4 +352,4 @@ } } } -} +} \ No newline at end of file diff --git a/apps/web/i18n/messages/en/finance.json b/apps/web/i18n/messages/en/finance.json index 88593b0d6..669a5dded 100644 --- a/apps/web/i18n/messages/en/finance.json +++ b/apps/web/i18n/messages/en/finance.json @@ -146,7 +146,9 @@ "next": "Next", "type": "Type", "date": "Date", - "description": "Description" + "description": "Description", + "searchPlaceholder": "Search invoices...", + "all": "All" }, "status": { "draft": "Draft", @@ -160,4 +162,4 @@ "completed": "Completed", "failed": "Failed" } -} +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 19ef51ee3..8eb41c0bc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -330,6 +330,9 @@ services: # Browser-side Supabase URL — goes through external domain (Traefik → Kong) NEXT_PUBLIC_SUPABASE_URL: ${API_EXTERNAL_URL:-http://localhost:8000} 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 depends_on: supabase-kong: @@ -352,12 +355,17 @@ services: NEXT_PUBLIC_ENABLE_THEME_TOGGLE: 'true' NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS: 'true' NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_CREATION: 'true' - NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING: 'false' - NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING: 'false' + NEXT_PUBLIC_ENABLE_TEAM_ACCOUNTS_BILLING: 'true' + NEXT_PUBLIC_ENABLE_PERSONAL_ACCOUNT_BILLING: 'true' NEXT_PUBLIC_ENABLE_NOTIFICATIONS: 'true' NEXT_PUBLIC_ENABLE_FISCHEREI: 'true' NEXT_PUBLIC_ENABLE_MEETING_PROTOCOLS: '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: supabase-db-data: diff --git a/packages/features/member-management/src/components/application-workflow.tsx b/packages/features/member-management/src/components/application-workflow.tsx index 3a599be5a..40e47cf7d 100644 --- a/packages/features/member-management/src/components/application-workflow.tsx +++ b/packages/features/member-management/src/components/application-workflow.tsx @@ -95,7 +95,8 @@ export function ApplicationWorkflow({

Aufnahmeanträge

- {applications.length} Antrag{applications.length !== 1 ? 'e' : ''} + {applications.length}{' '} + {applications.length === 1 ? 'Antrag' : 'Anträge'}