fix: add missing newlines at the end of JSON files; clean up formatting in page components
This commit is contained in:
@@ -4,7 +4,24 @@ import { use } from 'react';
|
||||
import { cookies } from 'next/headers';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
import { Fish, FileSignature, Building2 } from 'lucide-react';
|
||||
import {
|
||||
Fish,
|
||||
Waves,
|
||||
Anchor,
|
||||
BookOpen,
|
||||
ShieldCheck,
|
||||
Trophy,
|
||||
FileSignature,
|
||||
ScrollText,
|
||||
ListChecks,
|
||||
BookMarked,
|
||||
Building2,
|
||||
Network,
|
||||
SearchCheck,
|
||||
Share2,
|
||||
PieChart,
|
||||
LayoutTemplate,
|
||||
} from 'lucide-react';
|
||||
import * as z from 'zod';
|
||||
|
||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
@@ -61,65 +78,132 @@ const getAccountFeatures = cache(async (accountSlug: string) => {
|
||||
return (settings?.features as Record<string, boolean>) ?? {};
|
||||
});
|
||||
|
||||
const iconClasses = 'w-4';
|
||||
|
||||
/**
|
||||
* Inject per-account feature routes (e.g. Fischerei) into the parsed
|
||||
* navigation config. The entry is inserted right after "Veranstaltungen".
|
||||
* Inject per-account feature module route groups (Fischerei, Meetings, Verband)
|
||||
* into the navigation config. These are added as separate collapsible sections
|
||||
* before the Administration section (last group).
|
||||
*
|
||||
* Only modules enabled in the account's settings are shown.
|
||||
*/
|
||||
function injectAccountFeatureRoutes(
|
||||
config: z.output<typeof NavigationConfigSchema>,
|
||||
account: string,
|
||||
features: Record<string, boolean>,
|
||||
): z.output<typeof NavigationConfigSchema> {
|
||||
if (!features.fischerei && !features.meetings && !features.verband)
|
||||
return config;
|
||||
|
||||
const featureEntries: Array<{
|
||||
label: string;
|
||||
path: string;
|
||||
Icon: React.ReactNode;
|
||||
}> = [];
|
||||
const featureGroups: z.output<typeof NavigationConfigSchema>['routes'] = [];
|
||||
|
||||
if (features.fischerei) {
|
||||
featureEntries.push({
|
||||
label: 'common.routes.fischerei',
|
||||
path: `/home/${account}/fischerei`,
|
||||
Icon: <Fish className="w-4" />,
|
||||
featureGroups.push({
|
||||
label: 'common:routes.fisheriesManagement',
|
||||
collapsible: true,
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.fisheriesOverview',
|
||||
path: `/home/${account}/fischerei`,
|
||||
Icon: <Fish className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.fisheriesWaters',
|
||||
path: `/home/${account}/fischerei/waters`,
|
||||
Icon: <Waves className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.fisheriesLeases',
|
||||
path: `/home/${account}/fischerei/leases`,
|
||||
Icon: <Anchor className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.fisheriesCatchBooks',
|
||||
path: `/home/${account}/fischerei/catch-books`,
|
||||
Icon: <BookOpen className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.fisheriesPermits',
|
||||
path: `/home/${account}/fischerei/permits`,
|
||||
Icon: <ShieldCheck className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.fisheriesCompetitions',
|
||||
path: `/home/${account}/fischerei/competitions`,
|
||||
Icon: <Trophy className={iconClasses} />,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (features.meetings) {
|
||||
featureEntries.push({
|
||||
label: 'common.routes.meetings',
|
||||
path: `/home/${account}/meetings`,
|
||||
Icon: <FileSignature className="w-4" />,
|
||||
featureGroups.push({
|
||||
label: 'common:routes.meetingProtocols',
|
||||
collapsible: true,
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.meetingsOverview',
|
||||
path: `/home/${account}/meetings`,
|
||||
Icon: <BookMarked className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.meetingsProtocols',
|
||||
path: `/home/${account}/meetings/protocols`,
|
||||
Icon: <ScrollText className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.meetingsTasks',
|
||||
path: `/home/${account}/meetings/tasks`,
|
||||
Icon: <ListChecks className={iconClasses} />,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (features.verband) {
|
||||
featureEntries.push({
|
||||
label: 'common.routes.verband',
|
||||
path: `/home/${account}/verband`,
|
||||
Icon: <Building2 className="w-4" />,
|
||||
featureGroups.push({
|
||||
label: 'common:routes.associationManagement',
|
||||
collapsible: true,
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.associationOverview',
|
||||
path: `/home/${account}/verband`,
|
||||
Icon: <Building2 className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.associationHierarchy',
|
||||
path: `/home/${account}/verband/hierarchy`,
|
||||
Icon: <Network className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.associationMemberSearch',
|
||||
path: `/home/${account}/verband/members`,
|
||||
Icon: <SearchCheck className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.associationEvents',
|
||||
path: `/home/${account}/verband/events`,
|
||||
Icon: <Share2 className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.associationReporting',
|
||||
path: `/home/${account}/verband/reporting`,
|
||||
Icon: <PieChart className={iconClasses} />,
|
||||
},
|
||||
{
|
||||
label: 'common:routes.associationTemplates',
|
||||
path: `/home/${account}/verband/templates`,
|
||||
Icon: <LayoutTemplate className={iconClasses} />,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...config,
|
||||
routes: config.routes.map((group) => {
|
||||
if (!('children' in group)) return group;
|
||||
if (featureGroups.length === 0) return config;
|
||||
|
||||
const eventsIndex = group.children.findIndex(
|
||||
(child) => child.label === 'common.routes.events',
|
||||
);
|
||||
// Insert before the last group (Administration)
|
||||
const routes = [...config.routes];
|
||||
const adminIndex = routes.length - 1;
|
||||
routes.splice(adminIndex, 0, ...featureGroups);
|
||||
|
||||
if (eventsIndex === -1) return group;
|
||||
|
||||
const newChildren = [...group.children];
|
||||
newChildren.splice(eventsIndex + 1, 0, ...featureEntries);
|
||||
|
||||
return { ...group, children: newChildren };
|
||||
}),
|
||||
};
|
||||
return { ...config, routes };
|
||||
}
|
||||
|
||||
async function SidebarLayout({
|
||||
|
||||
Reference in New Issue
Block a user