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:
@@ -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}>
|
||||
|
||||
@@ -4,9 +4,13 @@ import { Database } from '@kit/supabase/database';
|
||||
|
||||
import { UserAnalysis } from '../types/accounts';
|
||||
|
||||
export type AccountWithParams = Database['medreport']['Tables']['accounts']['Row'] & {
|
||||
account_params: Pick<Database['medreport']['Tables']['account_params']['Row'], 'weight' | 'height'> | null;
|
||||
};
|
||||
export type AccountWithParams =
|
||||
Database['medreport']['Tables']['accounts']['Row'] & {
|
||||
account_params: Pick<
|
||||
Database['medreport']['Tables']['account_params']['Row'],
|
||||
'weight' | 'height'
|
||||
> | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing an API for interacting with user accounts.
|
||||
@@ -79,7 +83,8 @@ class AccountsApi {
|
||||
accounts (
|
||||
name,
|
||||
slug,
|
||||
picture_url
|
||||
picture_url,
|
||||
application_role
|
||||
)
|
||||
`,
|
||||
)
|
||||
@@ -95,6 +100,7 @@ class AccountsApi {
|
||||
label: accounts.name,
|
||||
value: accounts.slug,
|
||||
image: accounts.picture_url,
|
||||
application_role: accounts.application_role,
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -209,11 +215,12 @@ class AccountsApi {
|
||||
return null;
|
||||
}
|
||||
|
||||
return analysisResponses
|
||||
.map((r) => ({
|
||||
...r,
|
||||
elements: analysisResponseElements.filter((e) => e.analysis_response_id === r.id),
|
||||
}));
|
||||
return analysisResponses.map((r) => ({
|
||||
...r,
|
||||
elements: analysisResponseElements.filter(
|
||||
(e) => e.analysis_response_id === r.id,
|
||||
),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user