Files
dyolink/frontend/src/components/shared/permissions.ts

106 lines
3.4 KiB
TypeScript

import type { Organization } from '@/types/organization';
const ROUTE_TAB_READ: { prefix: string; permission: string }[] = [
{ prefix: '/today', permission: 'TAB_TODAY_READ' },
{ prefix: '/staff', permission: 'TAB_STAFF_READ' },
{ prefix: '/organizations', permission: 'TAB_ORGANIZATIONS_READ' },
{ prefix: '/patients', permission: 'TAB_PATIENTS_READ' },
{ prefix: '/appointments', permission: 'TAB_APPOINTMENTS_READ' },
{ prefix: '/treatment', permission: 'TAB_TREATMENT_READ' },
{ prefix: '/billing', permission: 'TAB_BILLING_READ' },
{ prefix: '/reports', permission: 'TAB_REPORTS_READ' },
];
export function hasPermission(org: Organization | null, permission: string): boolean {
if (!org) return false;
return Boolean(org.permissions?.includes(permission));
}
/** True when the user is owner of the currently selected organization. */
export function canCreateOrganizationFromCurrentOrg(org: Organization | null): boolean {
return Boolean(org?.isOwner);
}
/** Sidebar / route guard: READ access to a tab */
export function canViewTab(org: Organization | null, readPermission: string): boolean {
return hasPermission(org, readPermission);
}
export function getRequiredReadPermissionForPath(pathname: string): string | null {
for (const { prefix, permission } of ROUTE_TAB_READ) {
if (pathname === prefix || pathname.startsWith(`${prefix}/`)) {
return permission;
}
}
return null;
}
/** First dashboard route the user may open (ordered). Fallback: account settings. */
export function firstAccessibleDashboardPath(org: Organization | null): string {
if (!org) return '/today';
for (const { prefix, permission } of ROUTE_TAB_READ) {
if (hasPermission(org, permission)) return prefix;
}
return '/settings/account';
}
export function canEditStaff(org: Organization | null): boolean {
return hasPermission(org, 'TAB_STAFF_EDIT');
}
export function canViewStaff(org: Organization | null): boolean {
return (
hasPermission(org, 'TAB_STAFF_READ') || hasPermission(org, 'TAB_STAFF_EDIT')
);
}
/**
* Create/delete/book slots: owners, appointment editors, or treatment editors (schedule columns).
* Aligns with backend appointment mutations.
*/
export function canEditAppointments(org: Organization | null): boolean {
if (!org) {
return false;
}
if (org.isOwner) {
return true;
}
return (
hasPermission(org, 'TAB_APPOINTMENTS_EDIT') ||
hasPermission(org, 'TAB_TREATMENT_EDIT')
);
}
/** Route + sidebar: view appointments page if user can read appointments or manage treatment (column staff). */
export function canAccessAppointmentsSection(org: Organization | null): boolean {
if (!org) {
return false;
}
if (org.isOwner) {
return true;
}
return (
hasPermission(org, 'TAB_APPOINTMENTS_READ') ||
hasPermission(org, 'TAB_APPOINTMENTS_EDIT') ||
hasPermission(org, 'TAB_TREATMENT_EDIT') ||
hasPermission(org, 'TAB_TREATMENT_READ')
);
}
/** Treatment composer, scheduling columns, and saving clinical workflows */
export function canEditTreatment(org: Organization | null): boolean {
if (!org) return false;
if (org.isOwner) return true;
return hasPermission(org, 'TAB_TREATMENT_EDIT');
}
/** View treatment workspace (read-only or edit) */
export function canViewTreatment(org: Organization | null): boolean {
if (!org) return false;
if (org.isOwner) return true;
return (
hasPermission(org, 'TAB_TREATMENT_READ') ||
hasPermission(org, 'TAB_TREATMENT_EDIT')
);
}