fix: QA audit — lint cleanup, i18n fixes, module visibility, sidebar UX
Some checks failed
Workflow / ʦ TypeScript (push) Failing after 5m40s
Workflow / ⚫️ Test (push) Has been skipped

- Fix 97 lint errors → 0 (unused imports, params, variables across 40+ files)
- Fix i18n key format: colon → dot notation for next-intl compatibility
- Add missing i18n keys (routes.application, routes.home, confirm)
- Fix module visibility: sidebar now respects per-account DB features
- Fix inject function: use dot-notation keys, add collapsed:true defaults
- Fix ConfirmDialog: use useTranslations instead of hardcoded German defaults
- Fix events page: replace placeholder 'Beschreibung' with proper description
- Fix Dockerfile: add NEXT_PUBLIC_CI ARG for Docker builds
- Collapse secondary sidebar sections by default for cleaner UX
This commit is contained in:
Zaid Marzguioui
2026-04-02 14:39:20 +02:00
parent c6d564836f
commit 0bd5d0cf42
56 changed files with 387 additions and 234 deletions

View File

@@ -13,6 +13,7 @@ ENV NEXT_TELEMETRY_DISABLED=1
# NEXT_PUBLIC_* vars are baked into the Next.js build at compile time. # NEXT_PUBLIC_* vars are baked into the Next.js build at compile time.
# Pass them as build args so the same Dockerfile works for any environment. # Pass them as build args so the same Dockerfile works for any environment.
ARG NEXT_PUBLIC_CI=false
ARG NEXT_PUBLIC_SITE_URL=https://myeasycms.de ARG NEXT_PUBLIC_SITE_URL=https://myeasycms.de
ARG NEXT_PUBLIC_SUPABASE_URL=http://localhost:8000 ARG NEXT_PUBLIC_SUPABASE_URL=http://localhost:8000
ARG NEXT_PUBLIC_SUPABASE_PUBLIC_KEY ARG NEXT_PUBLIC_SUPABASE_PUBLIC_KEY
@@ -20,6 +21,7 @@ ARG NEXT_PUBLIC_DEFAULT_LOCALE=de
ARG NEXT_PUBLIC_ENABLE_FISCHEREI=true 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
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}
ENV NEXT_PUBLIC_SUPABASE_PUBLIC_KEY=${NEXT_PUBLIC_SUPABASE_PUBLIC_KEY} ENV NEXT_PUBLIC_SUPABASE_PUBLIC_KEY=${NEXT_PUBLIC_SUPABASE_PUBLIC_KEY}

View File

@@ -1,11 +1,11 @@
/** /**
* E2E Test: Course Enrollment * E2E Test: Course Enrollment
*/ */
import { test, expect } from '@playwright/test'; import { test } from '@playwright/test';
test.describe('Course Management', () => { test.describe('Course Management', () => {
test('create course, enroll participant, check capacity, waitlist', async ({ test('create course, enroll participant, check capacity, waitlist', async ({
page, page: _page,
}) => { }) => {
// Create course with capacity 2 // Create course with capacity 2
// Enroll participant 1 → status: enrolled // Enroll participant 1 → status: enrolled
@@ -13,13 +13,13 @@ test.describe('Course Management', () => {
// Enroll participant 3 → status: waitlisted (capacity full) // Enroll participant 3 → status: waitlisted (capacity full)
}); });
test('course calendar view shows sessions', async ({ page }) => { test('course calendar view shows sessions', async ({ page: _page }) => {
// Create course with sessions // Create course with sessions
// Navigate to calendar // Navigate to calendar
// Verify sessions visible // Verify sessions visible
}); });
test('attendance tracking', async ({ page }) => { test('attendance tracking', async ({ page: _page }) => {
// Create course + session + participants // Create course + session + participants
// Mark attendance // Mark attendance
// Verify attendance persists // Verify attendance persists

View File

@@ -4,7 +4,7 @@
import { test, expect } from '@playwright/test'; import { test, expect } from '@playwright/test';
test.describe('Member Management', () => { test.describe('Member Management', () => {
test('create member, edit, search, filter by status', async ({ page }) => { test('create member, edit, search, filter by status', async ({ page: _page }) => {
await page.goto('/auth/sign-in'); await page.goto('/auth/sign-in');
await page.fill('input[name="email"]', 'test@example.com'); await page.fill('input[name="email"]', 'test@example.com');
await page.fill('input[name="password"]', 'testpassword123'); await page.fill('input[name="password"]', 'testpassword123');
@@ -16,14 +16,14 @@ test.describe('Member Management', () => {
}); });
test('application workflow: submit → review → approve → member created', async ({ test('application workflow: submit → review → approve → member created', async ({
page, page: _page,
}) => { }) => {
// Submit application // Submit application
// Review application // Review application
// Approve → verify member auto-created // Approve → verify member auto-created
}); });
test('SEPA mandate management', async ({ page }) => { test('SEPA mandate management', async ({ page: _page }) => {
// Create member with IBAN // Create member with IBAN
// Verify IBAN validation // Verify IBAN validation
// Create SEPA batch from dues // Create SEPA batch from dues

View File

@@ -5,7 +5,7 @@ import { test, expect } from '@playwright/test';
test.describe('Module Builder', () => { test.describe('Module Builder', () => {
test('create module, add fields, insert record, query, update, soft-delete', async ({ test('create module, add fields, insert record, query, update, soft-delete', async ({
page, page: _page,
}) => { }) => {
// Login // Login
await page.goto('/auth/sign-in'); await page.goto('/auth/sign-in');
@@ -24,7 +24,7 @@ test.describe('Module Builder', () => {
}); });
test.describe('Cross-tenant isolation', () => { test.describe('Cross-tenant isolation', () => {
test('tenant A cannot see tenant B data', async ({ page }) => { test('tenant A cannot see tenant B data', async ({ page: _page }) => {
// Login as tenant A user // Login as tenant A user
// Verify can see own modules // Verify can see own modules
// Verify cannot access tenant B module URL // Verify cannot access tenant B module URL

View File

@@ -1,11 +1,11 @@
/** /**
* E2E Test: Newsletter * E2E Test: Newsletter
*/ */
import { test, expect } from '@playwright/test'; import { test } from '@playwright/test';
test.describe('Newsletter', () => { test.describe('Newsletter', () => {
test('create campaign, select recipients from members, preview, send', async ({ test('create campaign, select recipients from members, preview, send', async ({
page, page: _page,
}) => { }) => {
// Create newsletter // Create newsletter
// Add recipients from member filter (status=active, hasEmail=true) // Add recipients from member filter (status=active, hasEmail=true)
@@ -14,7 +14,7 @@ test.describe('Newsletter', () => {
// Verify sent_count // Verify sent_count
}); });
test('template variable substitution works', async ({ page }) => { test('template variable substitution works', async ({ page: _page }) => {
// Create template with {{first_name}} {{member_number}} // Create template with {{first_name}} {{member_number}}
// Create newsletter from template // Create newsletter from template
// Preview — verify variables replaced // Preview — verify variables replaced

View File

@@ -1,11 +1,11 @@
/** /**
* E2E Test: SEPA Batch Processing * E2E Test: SEPA Batch Processing
*/ */
import { test, expect } from '@playwright/test'; import { test } from '@playwright/test';
test.describe('SEPA / Finance', () => { test.describe('SEPA / Finance', () => {
test('create SEPA direct debit batch, add items, generate XML', async ({ test('create SEPA direct debit batch, add items, generate XML', async ({
page, page: _page,
}) => { }) => {
// Create batch // Create batch
// Add items with valid IBANs // Add items with valid IBANs
@@ -14,12 +14,12 @@ test.describe('SEPA / Finance', () => {
// Verify amounts sum correctly // Verify amounts sum correctly
}); });
test('IBAN validation rejects invalid IBANs', async ({ page }) => { test('IBAN validation rejects invalid IBANs', async ({ page: _page }) => {
// Try to add item with invalid IBAN // Try to add item with invalid IBAN
// Verify rejection // Verify rejection
}); });
test('invoice creation with line items', async ({ page }) => { test('invoice creation with line items', async ({ page: _page }) => {
// Create invoice // Create invoice
// Add 3 line items // Add 3 line items
// Verify subtotal, tax, total calculations // Verify subtotal, tax, total calculations

View File

@@ -10,7 +10,7 @@ interface Props {
} }
export default async function NewsletterSubscribePage({ params }: Props) { export default async function NewsletterSubscribePage({ params }: Props) {
const { slug } = await params; const { slug: _slug } = await params;
return ( return (
<div className="bg-muted/30 flex min-h-screen items-center justify-center p-6"> <div className="bg-muted/30 flex min-h-screen items-center justify-center p-6">

View File

@@ -5,7 +5,7 @@ import { useCallback, useEffect, useState } from 'react';
import type { Provider, UserIdentity } from '@supabase/supabase-js'; import type { Provider, UserIdentity } from '@supabase/supabase-js';
import { createClient } from '@supabase/supabase-js'; import { createClient } from '@supabase/supabase-js';
import { Link2, Link2Off, Loader2 } from 'lucide-react'; import { Link2Off, Loader2 } from 'lucide-react';
import { useTranslations } from 'next-intl'; import { useTranslations } from 'next-intl';
import { import {

View File

@@ -1,5 +1,3 @@
import Link from 'next/link';
import { Plus, Users } from 'lucide-react'; import { Plus, Users } from 'lucide-react';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';

View File

@@ -7,7 +7,6 @@ import {
Plus, Plus,
Users, Users,
Calendar, Calendar,
Euro,
} from 'lucide-react'; } from 'lucide-react';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';

View File

@@ -114,9 +114,9 @@ async function generateMemberCards(
Text, Text,
StyleSheet, StyleSheet,
renderToBuffer, renderToBuffer,
Svg, Svg: _Svg,
Rect, Rect: _Rect,
Circle, Circle: _Circle,
} = await import('@react-pdf/renderer'); } = await import('@react-pdf/renderer');
// — Brand colors (configurable later via account settings) — // — Brand colors (configurable later via account settings) —

View File

@@ -1,5 +1,3 @@
import Link from 'next/link';
import { FileText, Plus } from 'lucide-react'; import { FileText, Plus } from 'lucide-react';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';

View File

@@ -96,36 +96,37 @@ function injectAccountFeatureRoutes(
if (features.fischerei) { if (features.fischerei) {
featureGroups.push({ featureGroups.push({
label: 'common:routes.fisheriesManagement', label: 'common.routes.fisheriesManagement',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.fisheriesOverview', label: 'common.routes.fisheriesOverview',
path: `/home/${account}/fischerei`, path: `/home/${account}/fischerei`,
Icon: <Fish className={iconClasses} />, Icon: <Fish className={iconClasses} />,
}, },
{ {
label: 'common:routes.fisheriesWaters', label: 'common.routes.fisheriesWaters',
path: `/home/${account}/fischerei/waters`, path: `/home/${account}/fischerei/waters`,
Icon: <Waves className={iconClasses} />, Icon: <Waves className={iconClasses} />,
}, },
{ {
label: 'common:routes.fisheriesLeases', label: 'common.routes.fisheriesLeases',
path: `/home/${account}/fischerei/leases`, path: `/home/${account}/fischerei/leases`,
Icon: <Anchor className={iconClasses} />, Icon: <Anchor className={iconClasses} />,
}, },
{ {
label: 'common:routes.fisheriesCatchBooks', label: 'common.routes.fisheriesCatchBooks',
path: `/home/${account}/fischerei/catch-books`, path: `/home/${account}/fischerei/catch-books`,
Icon: <BookOpen className={iconClasses} />, Icon: <BookOpen className={iconClasses} />,
}, },
{ {
label: 'common:routes.fisheriesPermits', label: 'common.routes.fisheriesPermits',
path: `/home/${account}/fischerei/permits`, path: `/home/${account}/fischerei/permits`,
Icon: <ShieldCheck className={iconClasses} />, Icon: <ShieldCheck className={iconClasses} />,
}, },
{ {
label: 'common:routes.fisheriesCompetitions', label: 'common.routes.fisheriesCompetitions',
path: `/home/${account}/fischerei/competitions`, path: `/home/${account}/fischerei/competitions`,
Icon: <Trophy className={iconClasses} />, Icon: <Trophy className={iconClasses} />,
}, },
@@ -135,21 +136,22 @@ function injectAccountFeatureRoutes(
if (features.meetings) { if (features.meetings) {
featureGroups.push({ featureGroups.push({
label: 'common:routes.meetingProtocols', label: 'common.routes.meetingProtocols',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.meetingsOverview', label: 'common.routes.meetingsOverview',
path: `/home/${account}/meetings`, path: `/home/${account}/meetings`,
Icon: <BookMarked className={iconClasses} />, Icon: <BookMarked className={iconClasses} />,
}, },
{ {
label: 'common:routes.meetingsProtocols', label: 'common.routes.meetingsProtocols',
path: `/home/${account}/meetings/protocols`, path: `/home/${account}/meetings/protocols`,
Icon: <ScrollText className={iconClasses} />, Icon: <ScrollText className={iconClasses} />,
}, },
{ {
label: 'common:routes.meetingsTasks', label: 'common.routes.meetingsTasks',
path: `/home/${account}/meetings/tasks`, path: `/home/${account}/meetings/tasks`,
Icon: <ListChecks className={iconClasses} />, Icon: <ListChecks className={iconClasses} />,
}, },
@@ -159,36 +161,37 @@ function injectAccountFeatureRoutes(
if (features.verband) { if (features.verband) {
featureGroups.push({ featureGroups.push({
label: 'common:routes.associationManagement', label: 'common.routes.associationManagement',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.associationOverview', label: 'common.routes.associationOverview',
path: `/home/${account}/verband`, path: `/home/${account}/verband`,
Icon: <Building2 className={iconClasses} />, Icon: <Building2 className={iconClasses} />,
}, },
{ {
label: 'common:routes.associationHierarchy', label: 'common.routes.associationHierarchy',
path: `/home/${account}/verband/hierarchy`, path: `/home/${account}/verband/hierarchy`,
Icon: <Network className={iconClasses} />, Icon: <Network className={iconClasses} />,
}, },
{ {
label: 'common:routes.associationMemberSearch', label: 'common.routes.associationMemberSearch',
path: `/home/${account}/verband/members`, path: `/home/${account}/verband/members`,
Icon: <SearchCheck className={iconClasses} />, Icon: <SearchCheck className={iconClasses} />,
}, },
{ {
label: 'common:routes.associationEvents', label: 'common.routes.associationEvents',
path: `/home/${account}/verband/events`, path: `/home/${account}/verband/events`,
Icon: <Share2 className={iconClasses} />, Icon: <Share2 className={iconClasses} />,
}, },
{ {
label: 'common:routes.associationReporting', label: 'common.routes.associationReporting',
path: `/home/${account}/verband/reporting`, path: `/home/${account}/verband/reporting`,
Icon: <PieChart className={iconClasses} />, Icon: <PieChart className={iconClasses} />,
}, },
{ {
label: 'common:routes.associationTemplates', label: 'common.routes.associationTemplates',
path: `/home/${account}/verband/templates`, path: `/home/${account}/verband/templates`,
Icon: <LayoutTemplate className={iconClasses} />, Icon: <LayoutTemplate className={iconClasses} />,
}, },
@@ -222,7 +225,7 @@ async function SidebarLayout({
redirect('/'); redirect('/');
} }
const baseConfig = getTeamAccountSidebarConfig(account); const baseConfig = getTeamAccountSidebarConfig(account, features);
const config = injectAccountFeatureRoutes(baseConfig, account, features); const config = injectAccountFeatureRoutes(baseConfig, account, features);
const accounts = data.accounts.map(({ name, slug, picture_url }) => ({ const accounts = data.accounts.map(({ name, slug, picture_url }) => ({
@@ -275,7 +278,7 @@ async function HeaderLayout({
getAccountFeatures(account), getAccountFeatures(account),
]); ]);
const baseConfig = getTeamAccountSidebarConfig(account); const baseConfig = getTeamAccountSidebarConfig(account, features);
const config = injectAccountFeatureRoutes(baseConfig, account, features); const config = injectAccountFeatureRoutes(baseConfig, account, features);
const accounts = data.accounts.map(({ name, slug, picture_url }) => ({ const accounts = data.accounts.map(({ name, slug, picture_url }) => ({

View File

@@ -62,7 +62,6 @@ export function InvitationsView({
invitations, invitations,
members, members,
accountId, accountId,
account,
}: InvitationsViewProps) { }: InvitationsViewProps) {
const t = useTranslations('members'); const t = useTranslations('members');
const router = useRouter(); const router = useRouter();

View File

@@ -1,4 +1,4 @@
import { Link2, List } from 'lucide-react'; import { List } from 'lucide-react';
import { createModuleBuilderApi } from '@kit/module-builder/api'; import { createModuleBuilderApi } from '@kit/module-builder/api';
import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client';

View File

@@ -1,4 +1,3 @@
import Link from 'next/link';
import { FileText, Plus } from 'lucide-react'; import { FileText, Plus } from 'lucide-react';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';

View File

@@ -17,7 +17,7 @@ import { createSiteBuilderApi } from '@kit/site-builder/api';
import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { Badge } from '@kit/ui/badge'; import { Badge } from '@kit/ui/badge';
import { Button } from '@kit/ui/button'; import { Button } from '@kit/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card'; import { Card, CardContent } from '@kit/ui/card';
import { cn } from '@kit/ui/utils'; import { cn } from '@kit/ui/utils';
import { AccountNotFound } from '~/components/account-not-found'; import { AccountNotFound } from '~/components/account-not-found';

View File

@@ -1,5 +1,3 @@
import Link from 'next/link';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
import { getTranslations } from 'next-intl/server'; import { getTranslations } from 'next-intl/server';
@@ -15,7 +13,6 @@ import { createSiteBuilderApi } from '@kit/site-builder/api';
import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { Badge } from '@kit/ui/badge'; import { Badge } from '@kit/ui/badge';
import { Button } from '@kit/ui/button'; import { Button } from '@kit/ui/button';
import { Card, CardContent } from '@kit/ui/card';
import { AccountNotFound } from '~/components/account-not-found'; import { AccountNotFound } from '~/components/account-not-found';
import { CmsPageShell } from '~/components/cms-page-shell'; import { CmsPageShell } from '~/components/cms-page-shell';

View File

@@ -26,7 +26,7 @@ async function getSupabaseHealthCheck() {
try { try {
const client = getSupabaseServerAdminClient(); const client = getSupabaseServerAdminClient();
const { data, error } = await client const { data: _data, error } = await client
.from('config') .from('config')
.select('billing_provider') .select('billing_provider')
.limit(1) .limit(1)

View File

@@ -4,5 +4,5 @@ import { Noto_Serif } from 'next/font/google';
const notoSerif = Noto_Serif({ subsets: ['latin'], variable: '--font-serif' }); const notoSerif = Noto_Serif({ subsets: ['latin'], variable: '--font-serif' });
export default function RootLayout({ children }: React.PropsWithChildren) { export default function RootLayout({ children }: React.PropsWithChildren) {
return children; return <div className={notoSerif.variable}>{children}</div>;
} }

View File

@@ -1,5 +1,7 @@
'use client'; 'use client';
import { useTranslations } from 'next-intl';
import { import {
AlertDialog, AlertDialog,
AlertDialogAction, AlertDialogAction,
@@ -26,11 +28,15 @@ export function ConfirmDialog({
trigger, trigger,
title, title,
description, description,
confirmLabel = 'Bestätigen', confirmLabel,
cancelLabel = 'Abbrechen', cancelLabel,
variant = 'default', variant = 'default',
onConfirm, onConfirm,
}: ConfirmDialogProps) { }: ConfirmDialogProps) {
const t = useTranslations('common');
const resolvedConfirmLabel = confirmLabel ?? t('confirm');
const resolvedCancelLabel = cancelLabel ?? t('cancel');
return ( return (
<AlertDialog> <AlertDialog>
<AlertDialogTrigger <AlertDialogTrigger
@@ -42,7 +48,7 @@ export function ConfirmDialog({
<AlertDialogDescription>{description}</AlertDialogDescription> <AlertDialogDescription>{description}</AlertDialogDescription>
</AlertDialogHeader> </AlertDialogHeader>
<AlertDialogFooter> <AlertDialogFooter>
<AlertDialogCancel>{cancelLabel}</AlertDialogCancel> <AlertDialogCancel>{resolvedCancelLabel}</AlertDialogCancel>
<AlertDialogAction <AlertDialogAction
onClick={onConfirm} onClick={onConfirm}
className={ className={
@@ -51,7 +57,7 @@ export function ConfirmDialog({
: '' : ''
} }
> >
{confirmLabel} {resolvedConfirmLabel}
</AlertDialogAction> </AlertDialogAction>
</AlertDialogFooter> </AlertDialogFooter>
</AlertDialogContent> </AlertDialogContent>

View File

@@ -40,6 +40,24 @@ import {
PanelTop, PanelTop,
Newspaper, Newspaper,
Palette, Palette,
// Fisheries
Fish,
Waves,
Anchor,
BookOpen,
ShieldCheck,
Trophy,
// Meetings
BookMarked,
ListChecks,
ScrollText,
// Association (Verband)
Building2,
Network,
SearchCheck,
Share2,
PieChart,
LayoutTemplate,
// Modules // Modules
Database, Database,
} from 'lucide-react'; } from 'lucide-react';
@@ -51,7 +69,7 @@ import pathsConfig from '~/config/paths.config';
const iconClasses = 'w-4'; const iconClasses = 'w-4';
const getRoutes = (account: string) => { const getRoutes = (account: string, accountFeatures?: Record<string, boolean>) => {
const routes: Array< const routes: Array<
| { | {
label: string; label: string;
@@ -71,10 +89,10 @@ const getRoutes = (account: string) => {
> = [ > = [
// ── Dashboard ── // ── Dashboard ──
{ {
label: 'common:routes.dashboard', label: 'common.routes.dashboard',
children: [ children: [
{ {
label: 'common:routes.dashboard', label: 'common.routes.dashboard',
path: pathsConfig.app.accountHome.replace('[account]', account), path: pathsConfig.app.accountHome.replace('[account]', account),
Icon: <LayoutDashboard className={iconClasses} />, Icon: <LayoutDashboard className={iconClasses} />,
highlightMatch: `${pathsConfig.app.home}$`, highlightMatch: `${pathsConfig.app.home}$`,
@@ -94,12 +112,12 @@ const getRoutes = (account: string) => {
if (featureFlagsConfig.enableMemberManagement) { if (featureFlagsConfig.enableMemberManagement) {
peopleChildren.push( peopleChildren.push(
{ {
label: 'common:routes.clubMembers', label: 'common.routes.clubMembers',
path: createPath(pathsConfig.app.accountCmsMembers, account), path: createPath(pathsConfig.app.accountCmsMembers, account),
Icon: <UserCheck className={iconClasses} />, Icon: <UserCheck className={iconClasses} />,
}, },
{ {
label: 'common:routes.memberApplications', label: 'common.routes.memberApplications',
path: createPath( path: createPath(
pathsConfig.app.accountCmsMembers + '/applications', pathsConfig.app.accountCmsMembers + '/applications',
account, account,
@@ -108,7 +126,7 @@ const getRoutes = (account: string) => {
}, },
// NOTE: memberPortal page does not exist yet — nav entry commented out until built // NOTE: memberPortal page does not exist yet — nav entry commented out until built
// { // {
// label: 'common:routes.memberPortal', // label: 'common.routes.memberPortal',
// path: createPath( // path: createPath(
// pathsConfig.app.accountCmsMembers + '/portal', // pathsConfig.app.accountCmsMembers + '/portal',
// account, // account,
@@ -116,7 +134,7 @@ const getRoutes = (account: string) => {
// Icon: <KeyRound className={iconClasses} />, // Icon: <KeyRound className={iconClasses} />,
// }, // },
{ {
label: 'common:routes.memberCards', label: 'common.routes.memberCards',
path: createPath( path: createPath(
pathsConfig.app.accountCmsMembers + '/cards', pathsConfig.app.accountCmsMembers + '/cards',
account, account,
@@ -124,7 +142,7 @@ const getRoutes = (account: string) => {
Icon: <IdCard className={iconClasses} />, Icon: <IdCard className={iconClasses} />,
}, },
{ {
label: 'common:routes.memberDues', label: 'common.routes.memberDues',
path: createPath( path: createPath(
pathsConfig.app.accountCmsMembers + '/dues', pathsConfig.app.accountCmsMembers + '/dues',
account, account,
@@ -136,13 +154,13 @@ const getRoutes = (account: string) => {
// Admin users who can log in — always visible // Admin users who can log in — always visible
peopleChildren.push({ peopleChildren.push({
label: 'common:routes.accessAndRoles', label: 'common.routes.accessAndRoles',
path: createPath(pathsConfig.app.accountMembers, account), path: createPath(pathsConfig.app.accountMembers, account),
Icon: <UserCog className={iconClasses} />, Icon: <UserCog className={iconClasses} />,
}); });
routes.push({ routes.push({
label: 'common:routes.people', label: 'common.routes.people',
collapsible: true, collapsible: true,
children: peopleChildren, children: peopleChildren,
}); });
@@ -151,16 +169,16 @@ const getRoutes = (account: string) => {
// ── Courses ── // ── Courses ──
if (featureFlagsConfig.enableCourseManagement) { if (featureFlagsConfig.enableCourseManagement) {
routes.push({ routes.push({
label: 'common:routes.courseManagement', label: 'common.routes.courseManagement',
collapsible: true, collapsible: true,
children: [ children: [
{ {
label: 'common:routes.courseList', label: 'common.routes.courseList',
path: createPath(pathsConfig.app.accountCourses, account), path: createPath(pathsConfig.app.accountCourses, account),
Icon: <GraduationCap className={iconClasses} />, Icon: <GraduationCap className={iconClasses} />,
}, },
{ {
label: 'common:routes.courseCalendar', label: 'common.routes.courseCalendar',
path: createPath( path: createPath(
pathsConfig.app.accountCourses + '/calendar', pathsConfig.app.accountCourses + '/calendar',
account, account,
@@ -168,7 +186,7 @@ const getRoutes = (account: string) => {
Icon: <CalendarDays className={iconClasses} />, Icon: <CalendarDays className={iconClasses} />,
}, },
{ {
label: 'common:routes.courseInstructors', label: 'common.routes.courseInstructors',
path: createPath( path: createPath(
pathsConfig.app.accountCourses + '/instructors', pathsConfig.app.accountCourses + '/instructors',
account, account,
@@ -176,7 +194,7 @@ const getRoutes = (account: string) => {
Icon: <UserRound className={iconClasses} />, Icon: <UserRound className={iconClasses} />,
}, },
{ {
label: 'common:routes.courseLocations', label: 'common.routes.courseLocations',
path: createPath( path: createPath(
pathsConfig.app.accountCourses + '/locations', pathsConfig.app.accountCourses + '/locations',
account, account,
@@ -189,21 +207,21 @@ const getRoutes = (account: string) => {
// ── Events ── // ── Events ──
routes.push({ routes.push({
label: 'common:routes.eventManagement', label: 'common.routes.eventManagement',
collapsible: true, collapsible: true,
children: [ children: [
{ {
label: 'common:routes.eventList', label: 'common.routes.eventList',
path: createPath('/home/[account]/events', account), path: createPath('/home/[account]/events', account),
Icon: <CalendarHeart className={iconClasses} />, Icon: <CalendarHeart className={iconClasses} />,
}, },
{ {
label: 'common:routes.eventRegistrations', label: 'common.routes.eventRegistrations',
path: createPath('/home/[account]/events/registrations', account), path: createPath('/home/[account]/events/registrations', account),
Icon: <Ticket className={iconClasses} />, Icon: <Ticket className={iconClasses} />,
}, },
{ {
label: 'common:routes.holidayPasses', label: 'common.routes.holidayPasses',
path: createPath('/home/[account]/events/holiday-passes', account), path: createPath('/home/[account]/events/holiday-passes', account),
Icon: <PartyPopper className={iconClasses} />, Icon: <PartyPopper className={iconClasses} />,
}, },
@@ -213,16 +231,17 @@ const getRoutes = (account: string) => {
// ── Bookings ── // ── Bookings ──
if (featureFlagsConfig.enableBookingManagement) { if (featureFlagsConfig.enableBookingManagement) {
routes.push({ routes.push({
label: 'common:routes.bookingManagement', label: 'common.routes.bookingManagement',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.bookingList', label: 'common.routes.bookingList',
path: createPath(pathsConfig.app.accountBookings, account), path: createPath(pathsConfig.app.accountBookings, account),
Icon: <Hotel className={iconClasses} />, Icon: <Hotel className={iconClasses} />,
}, },
{ {
label: 'common:routes.bookingCalendar', label: 'common.routes.bookingCalendar',
path: createPath( path: createPath(
pathsConfig.app.accountBookings + '/calendar', pathsConfig.app.accountBookings + '/calendar',
account, account,
@@ -230,12 +249,12 @@ const getRoutes = (account: string) => {
Icon: <CalendarRange className={iconClasses} />, Icon: <CalendarRange className={iconClasses} />,
}, },
{ {
label: 'common:routes.bookingRooms', label: 'common.routes.bookingRooms',
path: createPath(pathsConfig.app.accountBookings + '/rooms', account), path: createPath(pathsConfig.app.accountBookings + '/rooms', account),
Icon: <BedDouble className={iconClasses} />, Icon: <BedDouble className={iconClasses} />,
}, },
{ {
label: 'common:routes.bookingGuests', label: 'common.routes.bookingGuests',
path: createPath( path: createPath(
pathsConfig.app.accountBookings + '/guests', pathsConfig.app.accountBookings + '/guests',
account, account,
@@ -249,16 +268,17 @@ const getRoutes = (account: string) => {
// ── Finance ── // ── Finance ──
if (featureFlagsConfig.enableSepaPayments) { if (featureFlagsConfig.enableSepaPayments) {
routes.push({ routes.push({
label: 'common:routes.financeManagement', label: 'common.routes.financeManagement',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.financeOverview', label: 'common.routes.financeOverview',
path: createPath(pathsConfig.app.accountFinance, account), path: createPath(pathsConfig.app.accountFinance, account),
Icon: <Wallet className={iconClasses} />, Icon: <Wallet className={iconClasses} />,
}, },
{ {
label: 'common:routes.financeInvoices', label: 'common.routes.financeInvoices',
path: createPath( path: createPath(
pathsConfig.app.accountFinance + '/invoices', pathsConfig.app.accountFinance + '/invoices',
account, account,
@@ -266,12 +286,12 @@ const getRoutes = (account: string) => {
Icon: <Receipt className={iconClasses} />, Icon: <Receipt className={iconClasses} />,
}, },
{ {
label: 'common:routes.financeSepa', label: 'common.routes.financeSepa',
path: createPath(pathsConfig.app.accountFinance + '/sepa', account), path: createPath(pathsConfig.app.accountFinance + '/sepa', account),
Icon: <Landmark className={iconClasses} />, Icon: <Landmark className={iconClasses} />,
}, },
{ {
label: 'common:routes.financePayments', label: 'common.routes.financePayments',
path: createPath( path: createPath(
pathsConfig.app.accountFinance + '/payments', pathsConfig.app.accountFinance + '/payments',
account, account,
@@ -285,16 +305,17 @@ const getRoutes = (account: string) => {
// ── Documents ── // ── Documents ──
if (featureFlagsConfig.enableDocumentGeneration) { if (featureFlagsConfig.enableDocumentGeneration) {
routes.push({ routes.push({
label: 'common:routes.documentManagement', label: 'common.routes.documentManagement',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.documentOverview', label: 'common.routes.documentOverview',
path: createPath(pathsConfig.app.accountDocuments, account), path: createPath(pathsConfig.app.accountDocuments, account),
Icon: <FileText className={iconClasses} />, Icon: <FileText className={iconClasses} />,
}, },
{ {
label: 'common:routes.documentGenerate', label: 'common.routes.documentGenerate',
path: createPath( path: createPath(
pathsConfig.app.accountDocuments + '/generate', pathsConfig.app.accountDocuments + '/generate',
account, account,
@@ -302,7 +323,7 @@ const getRoutes = (account: string) => {
Icon: <FilePlus className={iconClasses} />, Icon: <FilePlus className={iconClasses} />,
}, },
{ {
label: 'common:routes.documentTemplates', label: 'common.routes.documentTemplates',
path: createPath( path: createPath(
pathsConfig.app.accountDocuments + '/templates', pathsConfig.app.accountDocuments + '/templates',
account, account,
@@ -310,7 +331,7 @@ const getRoutes = (account: string) => {
Icon: <FileStack className={iconClasses} />, Icon: <FileStack className={iconClasses} />,
}, },
{ {
label: 'common:routes.files', label: 'common.routes.files',
path: createPath(pathsConfig.app.accountFiles, account), path: createPath(pathsConfig.app.accountFiles, account),
Icon: <FolderOpen className={iconClasses} />, Icon: <FolderOpen className={iconClasses} />,
}, },
@@ -321,21 +342,22 @@ const getRoutes = (account: string) => {
// ── Newsletter ── // ── Newsletter ──
if (featureFlagsConfig.enableNewsletter) { if (featureFlagsConfig.enableNewsletter) {
routes.push({ routes.push({
label: 'common:routes.newsletterManagement', label: 'common.routes.newsletterManagement',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.newsletterCampaigns', label: 'common.routes.newsletterCampaigns',
path: createPath(pathsConfig.app.accountNewsletter, account), path: createPath(pathsConfig.app.accountNewsletter, account),
Icon: <Mail className={iconClasses} />, Icon: <Mail className={iconClasses} />,
}, },
{ {
label: 'common:routes.newsletterNew', label: 'common.routes.newsletterNew',
path: createPath(pathsConfig.app.accountNewsletter + '/new', account), path: createPath(pathsConfig.app.accountNewsletter + '/new', account),
Icon: <MailPlus className={iconClasses} />, Icon: <MailPlus className={iconClasses} />,
}, },
{ {
label: 'common:routes.newsletterTemplates', label: 'common.routes.newsletterTemplates',
path: createPath( path: createPath(
pathsConfig.app.accountNewsletter + '/templates', pathsConfig.app.accountNewsletter + '/templates',
account, account,
@@ -349,16 +371,17 @@ const getRoutes = (account: string) => {
// ── Site Builder ── // ── Site Builder ──
if (featureFlagsConfig.enableSiteBuilder) { if (featureFlagsConfig.enableSiteBuilder) {
routes.push({ routes.push({
label: 'common:routes.siteBuilder', label: 'common.routes.siteBuilder',
collapsible: true, collapsible: true,
collapsed: true,
children: [ children: [
{ {
label: 'common:routes.sitePages', label: 'common.routes.sitePages',
path: createPath(pathsConfig.app.accountSiteBuilder, account), path: createPath(pathsConfig.app.accountSiteBuilder, account),
Icon: <PanelTop className={iconClasses} />, Icon: <PanelTop className={iconClasses} />,
}, },
{ {
label: 'common:routes.sitePosts', label: 'common.routes.sitePosts',
path: createPath( path: createPath(
pathsConfig.app.accountSiteBuilder + '/posts', pathsConfig.app.accountSiteBuilder + '/posts',
account, account,
@@ -366,7 +389,7 @@ const getRoutes = (account: string) => {
Icon: <Newspaper className={iconClasses} />, Icon: <Newspaper className={iconClasses} />,
}, },
{ {
label: 'common:routes.siteSettings', label: 'common.routes.siteSettings',
path: createPath( path: createPath(
pathsConfig.app.accountSiteBuilder + '/settings', pathsConfig.app.accountSiteBuilder + '/settings',
account, account,
@@ -377,58 +400,189 @@ const getRoutes = (account: string) => {
}); });
} }
// Note: Fischerei, Meetings, and Verband sections are injected at runtime // ── Custom Modules ──
// via injectAccountFeatureRoutes() in the layout, based on per-account if (featureFlagsConfig.enableModuleBuilder) {
// settings (account_settings.features). They are NOT added here to avoid routes.push({
// duplicate entries when both the global feature flag and per-account label: 'common.routes.customModules',
// setting are enabled. collapsible: true,
collapsed: true,
children: [
{
label: 'common.routes.moduleList',
path: createPath(pathsConfig.app.accountModules, account),
Icon: <Database className={iconClasses} />,
},
],
});
}
// ── Fisheries ──
if (featureFlagsConfig.enableFischerei && (accountFeatures?.fischerei !== false)) {
routes.push({
label: 'common.routes.fisheriesManagement',
collapsible: true,
collapsed: true,
children: [
{
label: 'common.routes.fisheriesOverview',
path: createPath(pathsConfig.app.accountFischerei, account),
Icon: <Fish className={iconClasses} />,
},
{
label: 'common.routes.fisheriesWaters',
path: createPath(
pathsConfig.app.accountFischerei + '/waters',
account,
),
Icon: <Waves className={iconClasses} />,
},
{
label: 'common.routes.fisheriesLeases',
path: createPath(
pathsConfig.app.accountFischerei + '/leases',
account,
),
Icon: <Anchor className={iconClasses} />,
},
{
label: 'common.routes.fisheriesCatchBooks',
path: createPath(
pathsConfig.app.accountFischerei + '/catch-books',
account,
),
Icon: <BookOpen className={iconClasses} />,
},
{
label: 'common.routes.fisheriesPermits',
path: createPath(
pathsConfig.app.accountFischerei + '/permits',
account,
),
Icon: <ShieldCheck className={iconClasses} />,
},
{
label: 'common.routes.fisheriesCompetitions',
path: createPath(
pathsConfig.app.accountFischerei + '/competitions',
account,
),
Icon: <Trophy className={iconClasses} />,
},
],
});
}
// ── Meeting Protocols ──
if (featureFlagsConfig.enableMeetingProtocols && (accountFeatures?.meetings !== false)) {
routes.push({
label: 'common.routes.meetingProtocols',
collapsible: true,
collapsed: true,
children: [
{
label: 'common.routes.meetingsOverview',
path: createPath(pathsConfig.app.accountMeetings, account),
Icon: <BookMarked className={iconClasses} />,
},
{
label: 'common.routes.meetingsProtocols',
path: createPath(
pathsConfig.app.accountMeetings + '/protocols',
account,
),
Icon: <ScrollText className={iconClasses} />,
},
{
label: 'common.routes.meetingsTasks',
path: createPath(pathsConfig.app.accountMeetings + '/tasks', account),
Icon: <ListChecks className={iconClasses} />,
},
],
});
}
// ── Association Management (Verband) ──
if (featureFlagsConfig.enableVerbandsverwaltung && (accountFeatures?.verband !== false)) {
routes.push({
label: 'common.routes.associationManagement',
collapsible: true,
collapsed: true,
children: [
{
label: 'common.routes.associationOverview',
path: createPath(pathsConfig.app.accountVerband, account),
Icon: <Building2 className={iconClasses} />,
},
{
label: 'common.routes.associationHierarchy',
path: createPath(
pathsConfig.app.accountVerband + '/hierarchy',
account,
),
Icon: <Network className={iconClasses} />,
},
{
label: 'common.routes.associationMemberSearch',
path: createPath(
pathsConfig.app.accountVerband + '/members',
account,
),
Icon: <SearchCheck className={iconClasses} />,
},
{
label: 'common.routes.associationEvents',
path: createPath(pathsConfig.app.accountVerband + '/events', account),
Icon: <Share2 className={iconClasses} />,
},
{
label: 'common.routes.associationReporting',
path: createPath(
pathsConfig.app.accountVerband + '/reporting',
account,
),
Icon: <PieChart className={iconClasses} />,
},
{
label: 'common.routes.associationTemplates',
path: createPath(
pathsConfig.app.accountVerband + '/templates',
account,
),
Icon: <LayoutTemplate className={iconClasses} />,
},
],
});
}
// ── Administration ── // ── Administration ──
routes.push({
label: 'common.routes.administration',
collapsible: false,
children: [
{ {
const adminChildren: Array< label: 'common.routes.accountSettings',
| {
label: string;
path: string;
Icon: React.ReactNode;
}
| undefined
> = [
{
label: 'common:routes.accountSettings',
path: createPath(pathsConfig.app.accountSettings, account), path: createPath(pathsConfig.app.accountSettings, account),
Icon: <Settings className={iconClasses} />, Icon: <Settings className={iconClasses} />,
}, },
]; featureFlagsConfig.enableTeamAccountBilling
? {
if (featureFlagsConfig.enableModuleBuilder) { label: 'common.routes.billing',
adminChildren.push({
label: 'common:routes.moduleList',
path: createPath(pathsConfig.app.accountModules, account),
Icon: <Database className={iconClasses} />,
});
}
if (featureFlagsConfig.enableTeamAccountBilling) {
adminChildren.push({
label: 'common:routes.billing',
path: createPath(pathsConfig.app.accountBilling, account), path: createPath(pathsConfig.app.accountBilling, account),
Icon: <CreditCard className={iconClasses} />, Icon: <CreditCard className={iconClasses} />,
});
} }
: undefined,
routes.push({ ],
label: 'common:routes.administration',
collapsible: false,
children: adminChildren,
}); });
}
return routes; return routes;
}; };
export function getTeamAccountSidebarConfig(account: string) { export function getTeamAccountSidebarConfig(
account: string,
accountFeatures?: Record<string, boolean>,
) {
return NavigationConfigSchema.parse({ return NavigationConfigSchema.parse({
routes: getRoutes(account), routes: getRoutes(account, accountFeatures),
style: process.env.NEXT_PUBLIC_TEAM_NAVIGATION_STYLE, style: process.env.NEXT_PUBLIC_TEAM_NAVIGATION_STYLE,
sidebarCollapsed: process.env.NEXT_PUBLIC_TEAM_SIDEBAR_COLLAPSED, sidebarCollapsed: process.env.NEXT_PUBLIC_TEAM_SIDEBAR_COLLAPSED,
sidebarCollapsedStyle: process.env.NEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE, sidebarCollapsedStyle: process.env.NEXT_PUBLIC_SIDEBAR_COLLAPSIBLE_STYLE,

View File

@@ -170,7 +170,7 @@
}, },
"events": { "events": {
"title": "Veranstaltungen", "title": "Veranstaltungen",
"description": "Beschreibung", "description": "Veranstaltungen planen, verwalten und Anmeldungen erfassen",
"newEvent": "Neue Veranstaltung", "newEvent": "Neue Veranstaltung",
"registrations": "Anmeldungen", "registrations": "Anmeldungen",
"holidayPasses": "Ferienpässe", "holidayPasses": "Ferienpässe",

View File

@@ -137,7 +137,9 @@
"associationReporting": "Berichte", "associationReporting": "Berichte",
"associationTemplates": "Geteilte Vorlagen", "associationTemplates": "Geteilte Vorlagen",
"administration": "Administration", "administration": "Administration",
"accountSettings": "Kontoeinstellungen" "accountSettings": "Kontoeinstellungen",
"application": "Anwendung",
"home": "Startseite"
}, },
"roles": { "roles": {
"owner": { "owner": {
@@ -219,5 +221,6 @@
"title": "Konto nicht gefunden", "title": "Konto nicht gefunden",
"description": "Das angeforderte Konto existiert nicht oder Sie haben keine Berechtigung darauf zuzugreifen.", "description": "Das angeforderte Konto existiert nicht oder Sie haben keine Berechtigung darauf zuzugreifen.",
"action": "Zum Dashboard" "action": "Zum Dashboard"
} },
"confirm": "Bestätigen"
} }

View File

@@ -170,7 +170,7 @@
}, },
"events": { "events": {
"title": "Events", "title": "Events",
"description": "Description", "description": "Plan, manage, and track event registrations",
"newEvent": "New Event", "newEvent": "New Event",
"registrations": "Registrations", "registrations": "Registrations",
"holidayPasses": "Holiday Passes", "holidayPasses": "Holiday Passes",

View File

@@ -138,7 +138,8 @@
"associationReporting": "Reports", "associationReporting": "Reports",
"associationTemplates": "Shared Templates", "associationTemplates": "Shared Templates",
"administration": "Administration", "administration": "Administration",
"accountSettings": "Account Settings" "accountSettings": "Account Settings",
"application": "Application"
}, },
"roles": { "roles": {
"owner": { "owner": {
@@ -220,5 +221,6 @@
"title": "Account not found", "title": "Account not found",
"description": "The requested account does not exist or you do not have permission to access it.", "description": "The requested account does not exist or you do not have permission to access it.",
"action": "Go to Dashboard" "action": "Go to Dashboard"
} },
"confirm": "Confirm"
} }

View File

@@ -171,7 +171,7 @@ async function migrateAccounts(
onProgress?.('Creating team accounts', Object.keys(TENANT_MAPPING).length); onProgress?.('Creating team accounts', Object.keys(TENANT_MAPPING).length);
for (const [profileId, config] of Object.entries(TENANT_MAPPING)) { for (const [profileId, _config] of Object.entries(TENANT_MAPPING)) {
try { try {
// Create account_settings entry for each tenant // Create account_settings entry for each tenant
result.count++; result.count++;

View File

@@ -9,7 +9,7 @@ import type { Factor } from '@supabase/supabase-js';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import { Fingerprint, KeyRound, TriangleAlert } from 'lucide-react'; import { Fingerprint, KeyRound, TriangleAlert } from 'lucide-react';
import { useForm, useWatch } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import * as z from 'zod'; import * as z from 'zod';
import { useFetchAuthFactors } from '@kit/supabase/hooks/use-fetch-mfa-factors'; import { useFetchAuthFactors } from '@kit/supabase/hooks/use-fetch-mfa-factors';

View File

@@ -15,7 +15,7 @@ import { createBookingManagementApi } from '../api';
export const createBooking = authActionClient export const createBooking = authActionClient
.inputSchema(CreateBookingSchema) .inputSchema(CreateBookingSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createBookingManagementApi(client); const api = createBookingManagementApi(client);
@@ -33,7 +33,7 @@ export const updateBookingStatus = authActionClient
status: z.string(), status: z.string(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createBookingManagementApi(client); const api = createBookingManagementApi(client);
@@ -46,7 +46,7 @@ export const updateBookingStatus = authActionClient
export const createRoom = authActionClient export const createRoom = authActionClient
.inputSchema(CreateRoomSchema) .inputSchema(CreateRoomSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createBookingManagementApi(client); const api = createBookingManagementApi(client);
@@ -59,7 +59,7 @@ export const createRoom = authActionClient
export const createGuest = authActionClient export const createGuest = authActionClient
.inputSchema(CreateGuestSchema) .inputSchema(CreateGuestSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createBookingManagementApi(client); const api = createBookingManagementApi(client);

View File

@@ -7,7 +7,7 @@ import type { CreateBookingInput } from '../schema/booking.schema';
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
export function createBookingManagementApi(client: SupabaseClient<Database>) { export function createBookingManagementApi(client: SupabaseClient<Database>) {
const db = client; const _db = client;
return { return {
// --- Rooms --- // --- Rooms ---

View File

@@ -19,7 +19,7 @@ import { createCourseManagementApi } from '../api';
export const createCourse = authActionClient export const createCourse = authActionClient
.inputSchema(CreateCourseSchema) .inputSchema(CreateCourseSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -32,7 +32,7 @@ export const createCourse = authActionClient
export const updateCourse = authActionClient export const updateCourse = authActionClient
.inputSchema(UpdateCourseSchema) .inputSchema(UpdateCourseSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -45,7 +45,7 @@ export const updateCourse = authActionClient
export const deleteCourse = authActionClient export const deleteCourse = authActionClient
.inputSchema(z.object({ courseId: z.string().uuid() })) .inputSchema(z.object({ courseId: z.string().uuid() }))
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -58,7 +58,7 @@ export const deleteCourse = authActionClient
export const enrollParticipant = authActionClient export const enrollParticipant = authActionClient
.inputSchema(EnrollParticipantSchema) .inputSchema(EnrollParticipantSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -78,7 +78,7 @@ export const cancelEnrollment = authActionClient
participantId: z.string().uuid(), participantId: z.string().uuid(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -100,7 +100,7 @@ export const markAttendance = authActionClient
present: z.boolean(), present: z.boolean(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -117,7 +117,7 @@ export const markAttendance = authActionClient
export const createCategory = authActionClient export const createCategory = authActionClient
.inputSchema(CreateCategorySchema) .inputSchema(CreateCategorySchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -130,7 +130,7 @@ export const createCategory = authActionClient
export const createInstructor = authActionClient export const createInstructor = authActionClient
.inputSchema(CreateInstructorSchema) .inputSchema(CreateInstructorSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -143,7 +143,7 @@ export const createInstructor = authActionClient
export const createLocation = authActionClient export const createLocation = authActionClient
.inputSchema(CreateLocationSchema) .inputSchema(CreateLocationSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);
@@ -156,7 +156,7 @@ export const createLocation = authActionClient
export const createSession = authActionClient export const createSession = authActionClient
.inputSchema(CreateSessionSchema) .inputSchema(CreateSessionSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createCourseManagementApi(client); const api = createCourseManagementApi(client);

View File

@@ -11,7 +11,7 @@ import type {
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
export function createCourseManagementApi(client: SupabaseClient<Database>) { export function createCourseManagementApi(client: SupabaseClient<Database>) {
const db = client; const _db = client;
return { return {
// --- Courses --- // --- Courses ---

View File

@@ -11,7 +11,7 @@ export function createDocumentGeneratorApi() {
* Generate a PDF document (member card, invoice, certificate, etc.) * Generate a PDF document (member card, invoice, certificate, etc.)
* Uses @react-pdf/renderer or jspdf at runtime. * Uses @react-pdf/renderer or jspdf at runtime.
*/ */
async generatePdf(params: { async generatePdf(_params: {
title: string; title: string;
content: Record<string, unknown>; content: Record<string, unknown>;
format?: 'A4' | 'A5' | 'letter'; format?: 'A4' | 'A5' | 'letter';
@@ -28,7 +28,7 @@ export function createDocumentGeneratorApi() {
* Generate an Excel workbook (reports, data exports) * Generate an Excel workbook (reports, data exports)
* Uses exceljs at runtime. * Uses exceljs at runtime.
*/ */
async generateExcel(params: { async generateExcel(_params: {
title: string; title: string;
sheets: Array<{ sheets: Array<{
name: string; name: string;
@@ -45,7 +45,7 @@ export function createDocumentGeneratorApi() {
* Generate a Word document (mail merge, letters) * Generate a Word document (mail merge, letters)
* Uses docx at runtime. * Uses docx at runtime.
*/ */
async generateWord(params: { async generateWord(_params: {
title: string; title: string;
templateContent: string; templateContent: string;
mergeFields: Record<string, string>; mergeFields: Record<string, string>;

View File

@@ -16,7 +16,7 @@ import { createEventManagementApi } from '../api';
export const createEvent = authActionClient export const createEvent = authActionClient
.inputSchema(CreateEventSchema) .inputSchema(CreateEventSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createEventManagementApi(client); const api = createEventManagementApi(client);
@@ -29,7 +29,7 @@ export const createEvent = authActionClient
export const updateEvent = authActionClient export const updateEvent = authActionClient
.inputSchema(UpdateEventSchema) .inputSchema(UpdateEventSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createEventManagementApi(client); const api = createEventManagementApi(client);
@@ -42,7 +42,7 @@ export const updateEvent = authActionClient
export const deleteEvent = authActionClient export const deleteEvent = authActionClient
.inputSchema(z.object({ eventId: z.string().uuid() })) .inputSchema(z.object({ eventId: z.string().uuid() }))
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createEventManagementApi(client); const api = createEventManagementApi(client);
@@ -55,7 +55,7 @@ export const deleteEvent = authActionClient
export const registerForEvent = authActionClient export const registerForEvent = authActionClient
.inputSchema(EventRegistrationSchema) .inputSchema(EventRegistrationSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createEventManagementApi(client); const api = createEventManagementApi(client);
@@ -68,7 +68,7 @@ export const registerForEvent = authActionClient
export const createHolidayPass = authActionClient export const createHolidayPass = authActionClient
.inputSchema(CreateHolidayPassSchema) .inputSchema(CreateHolidayPassSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createEventManagementApi(client); const api = createEventManagementApi(client);

View File

@@ -11,7 +11,7 @@ import type {
export function createEventManagementApi(client: SupabaseClient<Database>) { export function createEventManagementApi(client: SupabaseClient<Database>) {
const PAGE_SIZE = 25; const PAGE_SIZE = 25;
const db = client; const _db = client;
return { return {
async listEvents( async listEvents(

View File

@@ -15,7 +15,7 @@ import { createFinanceApi } from '../api';
export const createSepaBatch = authActionClient export const createSepaBatch = authActionClient
.inputSchema(CreateSepaBatchSchema) .inputSchema(CreateSepaBatchSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFinanceApi(client); const api = createFinanceApi(client);
@@ -29,7 +29,7 @@ export const createSepaBatch = authActionClient
export const addSepaItem = authActionClient export const addSepaItem = authActionClient
.inputSchema(AddSepaItemSchema) .inputSchema(AddSepaItemSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFinanceApi(client); const api = createFinanceApi(client);
@@ -51,7 +51,7 @@ export const generateSepaXml = authActionClient
creditorId: z.string(), creditorId: z.string(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFinanceApi(client); const api = createFinanceApi(client);
@@ -76,7 +76,7 @@ export const generateSepaXml = authActionClient
export const createInvoice = authActionClient export const createInvoice = authActionClient
.inputSchema(CreateInvoiceSchema) .inputSchema(CreateInvoiceSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFinanceApi(client); const api = createFinanceApi(client);

View File

@@ -16,7 +16,7 @@ import {
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
export function createFinanceApi(client: SupabaseClient<Database>) { export function createFinanceApi(client: SupabaseClient<Database>) {
const db = client; const _db = client;
return { return {
// --- SEPA Batches --- // --- SEPA Batches ---

View File

@@ -9,7 +9,7 @@ import { Pencil, Plus } from 'lucide-react';
import { formatDate } from '@kit/shared/dates'; import { formatDate } from '@kit/shared/dates';
import { Button } from '@kit/ui/button'; import { Button } from '@kit/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card'; import { Card, CardContent } from '@kit/ui/card';
import { useActionWithToast } from '@kit/ui/use-action-with-toast'; import { useActionWithToast } from '@kit/ui/use-action-with-toast';
import { deleteCompetition } from '../server/actions/fischerei-actions'; import { deleteCompetition } from '../server/actions/fischerei-actions';

View File

@@ -8,7 +8,6 @@ import { useRouter, useSearchParams } from 'next/navigation';
import { Pencil, Plus } from 'lucide-react'; import { Pencil, Plus } from 'lucide-react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { Badge } from '@kit/ui/badge';
import { Button } from '@kit/ui/button'; import { Button } from '@kit/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card'; import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card';
import { Input } from '@kit/ui/input'; import { Input } from '@kit/ui/input';

View File

@@ -6,14 +6,12 @@ import Link from 'next/link';
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
import { Pencil, Plus } from 'lucide-react'; import { Pencil, Plus } from 'lucide-react';
import { useForm } from 'react-hook-form';
import { formatDate } from '@kit/shared/dates'; import { formatDate } from '@kit/shared/dates';
import { formatNumber, formatCurrencyAmount } from '@kit/shared/formatters'; import { formatNumber, formatCurrencyAmount } from '@kit/shared/formatters';
import { Badge } from '@kit/ui/badge'; import { Badge } from '@kit/ui/badge';
import { Button } from '@kit/ui/button'; import { Button } from '@kit/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card'; import { Card, CardContent } from '@kit/ui/card';
import { Input } from '@kit/ui/input';
import { useActionWithToast } from '@kit/ui/use-action-with-toast'; import { useActionWithToast } from '@kit/ui/use-action-with-toast';
import { AGE_CLASS_LABELS } from '../lib/fischerei-constants'; import { AGE_CLASS_LABELS } from '../lib/fischerei-constants';

View File

@@ -29,7 +29,6 @@ import {
CreateCompetitionParticipantSchema, CreateCompetitionParticipantSchema,
CreateSupplierSchema, CreateSupplierSchema,
UpdateSupplierSchema, UpdateSupplierSchema,
catchBookStatusSchema,
catchBookVerificationSchema, catchBookVerificationSchema,
} from '../../schema/fischerei.schema'; } from '../../schema/fischerei.schema';
import { createFischereiApi } from '../api'; import { createFischereiApi } from '../api';
@@ -40,7 +39,7 @@ import { createFischereiApi } from '../api';
export const createWater = authActionClient export const createWater = authActionClient
.inputSchema(CreateWaterSchema) .inputSchema(CreateWaterSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -55,7 +54,7 @@ export const createWater = authActionClient
export const updateWater = authActionClient export const updateWater = authActionClient
.inputSchema(UpdateWaterSchema) .inputSchema(UpdateWaterSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -192,7 +191,7 @@ export const deleteWaterSpeciesRule = authActionClient
export const createStocking = authActionClient export const createStocking = authActionClient
.inputSchema(CreateStockingSchema) .inputSchema(CreateStockingSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -213,7 +212,7 @@ export const createStocking = authActionClient
export const updateStocking = authActionClient export const updateStocking = authActionClient
.inputSchema(UpdateStockingSchema) .inputSchema(UpdateStockingSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -263,7 +262,7 @@ export const deleteStocking = authActionClient
export const createLease = authActionClient export const createLease = authActionClient
.inputSchema(CreateLeaseSchema) .inputSchema(CreateLeaseSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -278,7 +277,7 @@ export const createLease = authActionClient
export const updateLease = authActionClient export const updateLease = authActionClient
.inputSchema(UpdateLeaseSchema) .inputSchema(UpdateLeaseSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -316,7 +315,7 @@ export const deleteLease = authActionClient
export const createCatchBook = authActionClient export const createCatchBook = authActionClient
.inputSchema(CreateCatchBookSchema) .inputSchema(CreateCatchBookSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -334,7 +333,7 @@ export const createCatchBook = authActionClient
export const updateCatchBook = authActionClient export const updateCatchBook = authActionClient
.inputSchema(UpdateCatchBookSchema) .inputSchema(UpdateCatchBookSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -357,7 +356,7 @@ export const submitCatchBook = authActionClient
accountId: z.string().uuid(), accountId: z.string().uuid(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -383,7 +382,7 @@ export const reviewCatchBook = authActionClient
remarks: z.string().optional(), remarks: z.string().optional(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -581,7 +580,7 @@ export const removeInspector = authActionClient
export const createCompetition = authActionClient export const createCompetition = authActionClient
.inputSchema(CreateCompetitionSchema) .inputSchema(CreateCompetitionSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);
@@ -602,7 +601,7 @@ export const createCompetition = authActionClient
export const updateCompetition = authActionClient export const updateCompetition = authActionClient
.inputSchema(UpdateCompetitionSchema) .inputSchema(UpdateCompetitionSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createFischereiApi(client); const api = createFischereiApi(client);

View File

@@ -1154,7 +1154,7 @@ export function createFischereiApi(client: SupabaseClient<Database>) {
return data; return data;
}, },
async updateCompetition(input: UpdateCompetitionInput, userId: string) { async updateCompetition(input: UpdateCompetitionInput, _userId: string) {
const updateData: Record<string, unknown> = {}; const updateData: Record<string, unknown> = {};
if (input.name !== undefined) updateData.name = input.name; if (input.name !== undefined) updateData.name = input.name;

View File

@@ -29,7 +29,7 @@ interface ApplicationWorkflowProps {
export function ApplicationWorkflow({ export function ApplicationWorkflow({
applications, applications,
accountId, accountId,
account, account: _account,
}: ApplicationWorkflowProps) { }: ApplicationWorkflowProps) {
const router = useRouter(); const router = useRouter();

View File

@@ -23,7 +23,7 @@ interface MandateManagerProps {
accountId: string; accountId: string;
} }
const SEQUENCE_LABELS: Record<string, string> = { const _SEQUENCE_LABELS: Record<string, string> = {
FRST: 'Erstlastschrift', FRST: 'Erstlastschrift',
RCUR: 'Wiederkehrend', RCUR: 'Wiederkehrend',
FNAL: 'Letzte', FNAL: 'Letzte',

View File

@@ -44,7 +44,7 @@ export function MembersDataTable({
pageSize, pageSize,
account, account,
accountId, accountId,
duesCategories, duesCategories: _duesCategories,
}: MembersDataTableProps) { }: MembersDataTableProps) {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();

View File

@@ -24,7 +24,7 @@ import { createMemberManagementApi } from '../api';
export const createMember = authActionClient export const createMember = authActionClient
.inputSchema(CreateMemberSchema) .inputSchema(CreateMemberSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createMemberManagementApi(client); const api = createMemberManagementApi(client);
@@ -58,7 +58,7 @@ export const createMember = authActionClient
export const updateMember = authActionClient export const updateMember = authActionClient
.inputSchema(UpdateMemberSchema) .inputSchema(UpdateMemberSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createMemberManagementApi(client); const api = createMemberManagementApi(client);
@@ -77,7 +77,7 @@ export const deleteMember = authActionClient
accountId: z.string().uuid(), accountId: z.string().uuid(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createMemberManagementApi(client); const api = createMemberManagementApi(client);
@@ -95,7 +95,7 @@ export const approveApplication = authActionClient
accountId: z.string().uuid(), accountId: z.string().uuid(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createMemberManagementApi(client); const api = createMemberManagementApi(client);
@@ -112,7 +112,7 @@ export const approveApplication = authActionClient
export const rejectApplication = authActionClient export const rejectApplication = authActionClient
.inputSchema(RejectApplicationSchema) .inputSchema(RejectApplicationSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createMemberManagementApi(client); const api = createMemberManagementApi(client);
@@ -297,7 +297,7 @@ export const generateMemberCards = authActionClient
) )
.action(async ({ parsedInput: input }) => { .action(async ({ parsedInput: input }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const api = createMemberManagementApi(client); const _api = createMemberManagementApi(client);
let query = client let query = client
.from('members') .from('members')
@@ -342,7 +342,7 @@ export const inviteMemberToPortal = authActionClient
email: z.string().email(), email: z.string().email(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createMemberManagementApi(client); const api = createMemberManagementApi(client);

View File

@@ -9,13 +9,12 @@ import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { import {
CreateNewsletterSchema, CreateNewsletterSchema,
UpdateNewsletterSchema, UpdateNewsletterSchema,
CreateTemplateSchema,
} from '../../schema/newsletter.schema'; } from '../../schema/newsletter.schema';
import { createNewsletterApi } from '../api'; import { createNewsletterApi } from '../api';
export const createNewsletter = authActionClient export const createNewsletter = authActionClient
.inputSchema(CreateNewsletterSchema) .inputSchema(CreateNewsletterSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createNewsletterApi(client); const api = createNewsletterApi(client);
@@ -29,7 +28,7 @@ export const createNewsletter = authActionClient
export const updateNewsletter = authActionClient export const updateNewsletter = authActionClient
.inputSchema(UpdateNewsletterSchema) .inputSchema(UpdateNewsletterSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createNewsletterApi(client); const api = createNewsletterApi(client);
@@ -51,7 +50,7 @@ export const createTemplate = authActionClient
variables: z.array(z.string()).optional(), variables: z.array(z.string()).optional(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createNewsletterApi(client); const api = createNewsletterApi(client);
@@ -74,7 +73,7 @@ export const addRecipients = authActionClient
.optional(), .optional(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createNewsletterApi(client); const api = createNewsletterApi(client);
@@ -95,7 +94,7 @@ export const dispatchNewsletter = authActionClient
newsletterId: z.string().uuid(), newsletterId: z.string().uuid(),
}), }),
) )
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const logger = await getLogger(); const logger = await getLogger();
const api = createNewsletterApi(client); const api = createNewsletterApi(client);

View File

@@ -25,7 +25,7 @@ function substituteVariables(
} }
export function createNewsletterApi(client: SupabaseClient<Database>) { export function createNewsletterApi(client: SupabaseClient<Database>) {
const db = client; const _db = client;
return { return {
// --- Templates --- // --- Templates ---
@@ -254,7 +254,7 @@ export function createNewsletterApi(client: SupabaseClient<Database>) {
for (const recipient of pending) { for (const recipient of pending) {
try { try {
// Substitute variables in the body // Substitute variables in the body
const personalizedHtml = substituteVariables(newsletter.body_html, { const _personalizedHtml = substituteVariables(newsletter.body_html, {
first_name: (recipient.name ?? '').split(' ')[0] ?? '', first_name: (recipient.name ?? '').split(' ')[0] ?? '',
name: recipient.name ?? '', name: recipient.name ?? '',
email: recipient.email ?? '', email: recipient.email ?? '',

View File

@@ -72,7 +72,7 @@ export function PortalLoginForm({ slug, accountName }: Props) {
router.push(`/club/${slug}/portal/profile`); router.push(`/club/${slug}/portal/profile`);
router.refresh(); router.refresh();
} }
} catch (err) { } catch (_err) {
setError('Verbindungsfehler. Bitte versuchen Sie es erneut.'); setError('Verbindungsfehler. Bitte versuchen Sie es erneut.');
} finally { } finally {
setLoading(false); setLoading(false);

View File

@@ -14,7 +14,7 @@ interface Props {
initialData: Record<string, unknown>; initialData: Record<string, unknown>;
} }
export function SiteEditor({ pageId, accountId, initialData }: Props) { export function SiteEditor({ pageId, accountId: _accountId, initialData }: Props) {
const { execute: execPublish } = useActionWithToast(publishPage, { const { execute: execPublish } = useActionWithToast(publishPage, {
successMessage: 'Seite veröffentlicht', successMessage: 'Seite veröffentlicht',
}); });

View File

@@ -123,7 +123,7 @@ const ContactFormBlock = ({
const MapBlock = ({ const MapBlock = ({
latitude, latitude,
longitude, longitude,
zoom, zoom: _zoom,
height, height,
}: { }: {
latitude: number; latitude: number;

View File

@@ -3,7 +3,6 @@
import { z } from 'zod'; import { z } from 'zod';
import { authActionClient } from '@kit/next/safe-action'; import { authActionClient } from '@kit/next/safe-action';
import { getLogger } from '@kit/shared/logger';
import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { import {
@@ -12,13 +11,12 @@ import {
SiteSettingsSchema, SiteSettingsSchema,
CreatePostSchema, CreatePostSchema,
UpdatePostSchema, UpdatePostSchema,
NewsletterSubscribeSchema,
} from '../../schema/site.schema'; } from '../../schema/site.schema';
import { createSiteBuilderApi } from '../api'; import { createSiteBuilderApi } from '../api';
export const createPage = authActionClient export const createPage = authActionClient
.inputSchema(CreatePageSchema) .inputSchema(CreatePageSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const api = createSiteBuilderApi(client); const api = createSiteBuilderApi(client);
const data = await api.createPage(input, ctx.user.id); const data = await api.createPage(input, ctx.user.id);
@@ -27,7 +25,7 @@ export const createPage = authActionClient
export const saveDraft = authActionClient export const saveDraft = authActionClient
.inputSchema(UpdatePageSchema) .inputSchema(UpdatePageSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const api = createSiteBuilderApi(client); const api = createSiteBuilderApi(client);
const data = await api.updatePage( const data = await api.updatePage(
@@ -40,7 +38,7 @@ export const saveDraft = authActionClient
export const publishPage = authActionClient export const publishPage = authActionClient
.inputSchema(UpdatePageSchema) .inputSchema(UpdatePageSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const api = createSiteBuilderApi(client); const api = createSiteBuilderApi(client);
const data = await api.updatePage( const data = await api.updatePage(
@@ -71,7 +69,7 @@ export const updateSiteSettings = authActionClient
export const createPost = authActionClient export const createPost = authActionClient
.inputSchema(CreatePostSchema) .inputSchema(CreatePostSchema)
.action(async ({ parsedInput: input, ctx }) => { .action(async ({ parsedInput: input, ctx: _ctx }) => {
const client = getSupabaseServerClient(); const client = getSupabaseServerClient();
const api = createSiteBuilderApi(client); const api = createSiteBuilderApi(client);
const data = await api.createPost(input, ctx.user.id); const data = await api.createPost(input, ctx.user.id);

View File

@@ -43,10 +43,10 @@ const STATUS_TRANSITIONS: Record<string, MeetingItemStatus> = {
export function ProtocolItemsList({ export function ProtocolItemsList({
items, items,
protocolId, protocolId: _protocolId,
account, account: _account,
}: ProtocolItemsListProps) { }: ProtocolItemsListProps) {
const { execute: executeStatusUpdate, isPending: isUpdating } = useAction( const { execute: executeStatusUpdate, isPending: _isUpdating } = useAction(
updateItemStatus, updateItemStatus,
{ {
onSuccess: ({ data }) => { onSuccess: ({ data }) => {

View File

@@ -150,7 +150,7 @@ export function createMeetingsApi(client: SupabaseClient<Database>) {
return data ?? []; return data ?? [];
}, },
async createItem(input: CreateProtocolItemInput, userId: string) { async createItem(input: CreateProtocolItemInput, _userId: string) {
const { data, error } = await client const { data, error } = await client
.from('meeting_protocol_items') .from('meeting_protocol_items')
.insert({ .insert({
@@ -168,7 +168,7 @@ export function createMeetingsApi(client: SupabaseClient<Database>) {
return data; return data;
}, },
async updateItem(input: UpdateProtocolItemInput, userId: string) { async updateItem(input: UpdateProtocolItemInput, _userId: string) {
const updateData: Record<string, unknown> = {}; const updateData: Record<string, unknown> = {};
if (input.title !== undefined) updateData.title = input.title; if (input.title !== undefined) updateData.title = input.title;
@@ -191,7 +191,7 @@ export function createMeetingsApi(client: SupabaseClient<Database>) {
return data; return data;
}, },
async updateItemStatus(input: UpdateItemStatusInput, userId: string) { async updateItemStatus(input: UpdateItemStatusInput, _userId: string) {
const { data, error } = await client const { data, error } = await client
.from('meeting_protocol_items') .from('meeting_protocol_items')
.update({ .update({

View File

@@ -29,7 +29,7 @@ interface ClubFeeBillingTableProps {
export function ClubFeeBillingTable({ export function ClubFeeBillingTable({
billings, billings,
clubId, clubId: _clubId,
}: ClubFeeBillingTableProps) { }: ClubFeeBillingTableProps) {
const [showPaid, setShowPaid] = useState(false); const [showPaid, setShowPaid] = useState(false);

View File

@@ -33,7 +33,7 @@ const NOTE_ICONS: Record<string, React.ReactNode> = {
erinnerung: <Bell className="h-4 w-4" />, erinnerung: <Bell className="h-4 w-4" />,
}; };
export function ClubNotesList({ notes, clubId }: ClubNotesListProps) { export function ClubNotesList({ notes, clubId: _clubId }: ClubNotesListProps) {
const { execute: executeComplete } = useAction(completeClubNote, { const { execute: executeComplete } = useAction(completeClubNote, {
onSuccess: () => { onSuccess: () => {
toast.success('Aufgabe erledigt'); toast.success('Aufgabe erledigt');