fix(settings): derive the sidebar preview from the real sidebar declaration
SidebarPreview kept its own hand-maintained 6-item array with only two gates wired (analytics, userManagement), so toggling e.g. Workflows changed nothing in the preview even though it does add a real sidebar entry once saved. Export AdminSidebar's `navigation` as `adminNavigation` (2 lines) and derive the preview from it, so every gate -- transfers, messaging, analytics, userManagement, clients incl. its featureFlagsAny set, accounting, workflows -- is covered and the two can't drift again. Note the report's item list was partly wrong: Quotes, Contracts, Invoices, Hours, Projects, Calendar and the CRM dev tools have no top-level sidebar entries at all -- they are sub-nav inside /admin/clients and surface in the preview through the CRM entry's featureFlagsAny. Permission filtering is deliberately not applied (unchanged): the preview answers "what do these flags do to the sidebar", not "what can this admin see". Refs testplan REPORT.md #20 (Part 3, J.14).
This commit is contained in:
@@ -1,22 +1,14 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import {
|
||||
LayoutDashboard,
|
||||
Calendar,
|
||||
Archive,
|
||||
BarChart3,
|
||||
Settings,
|
||||
Users,
|
||||
} from 'lucide-react';
|
||||
import type { LucideIcon } from 'lucide-react';
|
||||
import { Card } from '../../../components/common';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { adminNavigation } from '../../../components/admin/AdminSidebar';
|
||||
import type { FeatureFlags } from '../../../contexts/FeatureFlagsContext';
|
||||
|
||||
interface PreviewItem {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: LucideIcon;
|
||||
icon: React.ComponentType<{ className?: string }>;
|
||||
featureDriven: boolean;
|
||||
}
|
||||
|
||||
@@ -28,21 +20,25 @@ interface SidebarPreviewProps {
|
||||
* Renders the live shape of the main admin sidebar based on the user's
|
||||
* staged (unsaved) feature flags. Items in green (primary tint) are
|
||||
* controlled by toggles above; greyscale items are unconditional.
|
||||
*
|
||||
* Derived from AdminSidebar's own `adminNavigation` declaration so every
|
||||
* feature-gated entry is covered automatically — the previous hand-kept
|
||||
* copy had drifted to 2 of the gates (QA J.14). Permissions are
|
||||
* deliberately NOT applied here: the preview answers "what do these flags
|
||||
* do to the sidebar", not "what can this particular admin see".
|
||||
*/
|
||||
export const SidebarPreview: React.FC<SidebarPreviewProps> = ({ staged }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const items = useMemo<PreviewItem[]>(() => {
|
||||
const all: Array<PreviewItem & { gate?: keyof FeatureFlags }> = [
|
||||
{ key: 'dashboard', label: t('navigation.dashboard'), icon: LayoutDashboard, featureDriven: false },
|
||||
{ key: 'events', label: t('navigation.events'), icon: Calendar, featureDriven: false },
|
||||
{ key: 'archives', label: t('navigation.archives'), icon: Archive, featureDriven: false },
|
||||
{ key: 'analytics', label: t('admin.analytics', 'Analytics'), icon: BarChart3, featureDriven: true, gate: 'analytics' },
|
||||
{ key: 'settings', label: t('navigation.settings'), icon: Settings, featureDriven: false },
|
||||
{ key: 'users', label: t('navigation.users'), icon: Users, featureDriven: true, gate: 'userManagement' },
|
||||
];
|
||||
return all.filter((it) => !it.gate || staged[it.gate]);
|
||||
}, [staged, t]);
|
||||
const items = useMemo<PreviewItem[]>(() => adminNavigation
|
||||
.filter((it) => (!it.featureFlag || staged[it.featureFlag])
|
||||
&& (!it.featureFlagsAny?.length || it.featureFlagsAny.some((k) => staged[k])))
|
||||
.map((it) => ({
|
||||
key: it.nameKey,
|
||||
label: t(it.nameKey),
|
||||
icon: it.icon,
|
||||
featureDriven: Boolean(it.featureFlag || it.featureFlagsAny?.length),
|
||||
})), [staged, t]);
|
||||
|
||||
return (
|
||||
<Card padding="md">
|
||||
|
||||
Reference in New Issue
Block a user