feature: phase1 - org-type navigation, Cases permissions, staff filtering, and route guards.
This commit is contained in:
14
frontend/src/app/[locale]/(dashboard)/cases/page.tsx
Normal file
14
frontend/src/app/[locale]/(dashboard)/cases/page.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
'use client';
|
||||
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
export default function CasesPage() {
|
||||
const t = useTranslations('cases');
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h1 className="text-2xl font-semibold text-text-primary">{t('title')}</h1>
|
||||
<p className="text-sm text-text-muted max-w-xl">{t('stubDescription')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -8,10 +8,8 @@ import Sidebar from '@/components/ui/shared/Sidebar';
|
||||
import { TopBarControls } from '@/components/ui/shared/TopBarControls';
|
||||
import { DashboardAccountMenu } from '@/components/ui/dashboard/DashboardAccountMenu';
|
||||
import {
|
||||
canAccessAppointmentsSection,
|
||||
canAccessDashboardRoute,
|
||||
firstAccessibleDashboardPath,
|
||||
getRequiredReadPermissionForPath,
|
||||
hasPermission,
|
||||
} from '@/components/shared/permissions';
|
||||
|
||||
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
|
||||
@@ -33,15 +31,8 @@ export default function DashboardLayout({ children }: { children: React.ReactNod
|
||||
return;
|
||||
}
|
||||
|
||||
const required = getRequiredReadPermissionForPath(pathname);
|
||||
if (required) {
|
||||
const allowed =
|
||||
hasPermission(currentOrganization, required) ||
|
||||
(required === 'TAB_APPOINTMENTS_READ' &&
|
||||
canAccessAppointmentsSection(currentOrganization));
|
||||
if (!allowed) {
|
||||
router.replace(firstAccessibleDashboardPath(currentOrganization));
|
||||
}
|
||||
if (!canAccessDashboardRoute(currentOrganization, pathname)) {
|
||||
router.replace(firstAccessibleDashboardPath(currentOrganization));
|
||||
}
|
||||
}, [isAuthReady, user, currentOrganization, router, pathname]);
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import {
|
||||
canViewStaff,
|
||||
} from '@/components/shared/permissions';
|
||||
import {
|
||||
STAFF_FEATURE_GROUPS,
|
||||
permissionNamesFromFeatureState,
|
||||
emptyFeaturePermissionState,
|
||||
featureStateFromPermissionNames,
|
||||
featureStateHasTreatmentEdit,
|
||||
resolveStaffFeatureLabel,
|
||||
formatAccessSummary,
|
||||
staffFeatureGroupsForOrgType,
|
||||
type FeaturePermState,
|
||||
} from '@/components/staff/staff-permission-form';
|
||||
import {
|
||||
@@ -112,7 +112,7 @@ function PermissionGrid({
|
||||
|
||||
return (
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
{STAFF_FEATURE_GROUPS.map((g) => {
|
||||
{staffFeatureGroupsForOrgType(organizationType).map((g) => {
|
||||
const cell = state[g.edit] ?? { read: false, edit: false };
|
||||
return (
|
||||
<div
|
||||
@@ -199,10 +199,14 @@ export default function StaffPage() {
|
||||
|
||||
const canEdit = useMemo(() => canEditStaff(currentOrganization), [currentOrganization]);
|
||||
const inviteHasTreatmentEdit = useMemo(
|
||||
() => featureStateHasTreatmentEdit(invitePerms),
|
||||
[invitePerms],
|
||||
() =>
|
||||
currentOrganization?.type === 'CLINIC' && featureStateHasTreatmentEdit(invitePerms),
|
||||
[currentOrganization?.type, invitePerms],
|
||||
);
|
||||
const editHasTreatmentEdit = useMemo(
|
||||
() => currentOrganization?.type === 'CLINIC' && featureStateHasTreatmentEdit(editPerms),
|
||||
[currentOrganization?.type, editPerms],
|
||||
);
|
||||
const editHasTreatmentEdit = useMemo(() => featureStateHasTreatmentEdit(editPerms), [editPerms]);
|
||||
const hasActivePlan = Boolean(currentOrganization?.plan);
|
||||
const atSeatLimit = useMemo(() => {
|
||||
if (!seats || seats.unlimited) return false;
|
||||
@@ -309,7 +313,7 @@ export default function StaffPage() {
|
||||
setInviteStep(1);
|
||||
setInviteEmail('');
|
||||
setInviteName('');
|
||||
setInvitePerms(emptyFeaturePermissionState());
|
||||
setInvitePerms(emptyFeaturePermissionState(currentOrganization?.type));
|
||||
const defaults = createDefaultWorkingHoursState();
|
||||
setInviteWorkingHoursDays(defaults.days);
|
||||
setInviteAutoRepeatWeekly(defaults.autoRepeatWeekly);
|
||||
@@ -393,7 +397,7 @@ export default function StaffPage() {
|
||||
setEditing(m);
|
||||
setEditStep(1);
|
||||
setEditName(m.name);
|
||||
setEditPerms(featureStateFromPermissionNames(m.permissions ?? []));
|
||||
setEditPerms(featureStateFromPermissionNames(m.permissions ?? [], currentOrganization?.type));
|
||||
setEditHoursValidationError(null);
|
||||
const defaults = createDefaultWorkingHoursState();
|
||||
setEditWorkingHoursDays(defaults.days);
|
||||
|
||||
Reference in New Issue
Block a user