MED-109: add doctor role and basic view (#45)

* MED-109: add doctor role and basic view

* add role to accounts

* remove old super admin and doctor sql
This commit is contained in:
Helena
2025-08-13 12:28:50 +03:00
committed by GitHub
parent ce7b04fda8
commit 3c6c86c7c8
32 changed files with 562 additions and 35 deletions

View File

@@ -6,7 +6,14 @@ import Link from 'next/link';
import type { User } from '@supabase/supabase-js';
import { ChevronsUpDown, Home, LogOut, Shield, UserCircle } from 'lucide-react';
import {
ChevronsUpDown,
Cross,
Home,
LogOut,
Shield,
UserCircle,
} from 'lucide-react';
import { Avatar, AvatarFallback, AvatarImage } from '@kit/ui/avatar';
import {
@@ -44,16 +51,21 @@ export function PersonalAccountDropdown({
id: string | null;
name: string | null;
picture_url: string | null;
application_role: string;
};
accounts: {
label: string | null;
value: string | null;
image?: string | null;
application_role: string;
}[];
signOutRequested: () => unknown;
paths: {
home: string;
admin: string;
doctor: string;
personalAccountSettings: string;
};
features: {
@@ -64,10 +76,7 @@ export function PersonalAccountDropdown({
className?: string;
}) {
const { data: personalAccountData } = usePersonalAccountData(
user.id,
account,
);
const { data: personalAccountData } = usePersonalAccountData(user.id);
const signedInAsLabel = useMemo(() => {
const email = user?.email ?? undefined;
@@ -79,15 +88,25 @@ export function PersonalAccountDropdown({
const displayName =
personalAccountData?.name ?? account?.name ?? user?.email ?? '';
const isSuperAdmin = useMemo(() => {
const hasTotpFactor = useMemo(() => {
const factors = user?.factors ?? [];
const hasAdminRole = user?.app_metadata.role === 'super-admin';
const hasTotpFactor = factors.some(
return factors.some(
(factor) => factor.factor_type === 'totp' && factor.status === 'verified',
);
}, [user.factors]);
const isSuperAdmin = useMemo(() => {
const hasAdminRole =
personalAccountData?.application_role === 'super_admin';
return hasAdminRole && hasTotpFactor;
}, [user]);
}, [user, personalAccountData, hasTotpFactor]);
const isDoctor = useMemo(() => {
const hasDoctorRole = personalAccountData?.application_role === 'doctor';
return hasDoctorRole && hasTotpFactor;
}, [user, personalAccountData, hasTotpFactor]);
return (
<DropdownMenu>
@@ -177,7 +196,7 @@ export function PersonalAccountDropdown({
<DropdownMenuItem key={account.value} asChild>
<Link
className={'s-full flex cursor-pointer items-center space-x-2'}
href={`/home/${account.value}`}
href={`${paths.home}/${account.value}`}
>
<div className={'flex items-center'}>
<Avatar className={'h-5 w-5 rounded-xs ' + account.image}>
@@ -209,7 +228,7 @@ export function PersonalAccountDropdown({
<DropdownMenuItem asChild>
<Link
className={'s-full flex cursor-pointer items-center space-x-2'}
href={'/home/settings'}
href={paths.personalAccountSettings}
>
<UserCircle className={'h-5'} />
@@ -227,7 +246,7 @@ export function PersonalAccountDropdown({
className={
's-full flex cursor-pointer items-center space-x-2 text-yellow-700 dark:text-yellow-500'
}
href={'/admin'}
href={paths.admin}
>
<Shield className={'h-5'} />
@@ -236,6 +255,25 @@ export function PersonalAccountDropdown({
</DropdownMenuItem>
</If>
<If condition={isDoctor}>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className={
's-full flex cursor-pointer items-center space-x-2 text-yellow-700 dark:text-yellow-500'
}
href={paths.doctor}
>
<Cross className={'h-5'} />
<span>
<Trans i18nKey="common:doctor" />
</span>
</Link>
</DropdownMenuItem>
</If>
<DropdownMenuSeparator />
<If condition={features.enableThemeToggle}>