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

@@ -1,5 +1,7 @@
'use client';
import { useTransition } from 'react';
import Link from 'next/link';
import { usePathname, useRouter } from 'next/navigation';
@@ -11,6 +13,7 @@ import { z } from 'zod';
import { Database } from '@kit/supabase/database';
import { Button } from '@kit/ui/button';
import { Checkbox } from '@kit/ui/checkbox';
import {
DropdownMenu,
DropdownMenuContent,
@@ -32,7 +35,10 @@ import {
SelectTrigger,
SelectValue,
} from '@kit/ui/select';
import { toast } from '@kit/ui/sonner';
import { Trans } from '@kit/ui/trans';
import { updateRoleAction } from '../lib/server/admin-server-actions';
import { AdminDeleteAccountDialog } from './admin-delete-account-dialog';
import { AdminDeleteUserDialog } from './admin-delete-user-dialog';
import { AdminImpersonateUserDialog } from './admin-impersonate-user-dialog';
@@ -204,6 +210,39 @@ function getColumns(): ColumnDef<Account>[] {
header: 'Updated At',
accessorKey: 'updated_at',
},
{
id: 'isDoctor',
header: 'Doctor',
cell: ({ row }) => {
const [isPending, startTransition] = useTransition();
const handleToggle = () => {
startTransition(async () => {
const isDoctor = row.original.application_role === 'doctor';
const newRole = isDoctor ? 'user' : 'doctor';
const promise = updateRoleAction({
accountId: row.original.id,
role: newRole,
});
toast.promise(() => promise, {
success: <Trans i18nKey={'account:updateRoleSuccess'} />,
error: <Trans i18nKey={'account:updateRoleError'} />,
loading: <Trans i18nKey={'account:updateRoleLoading'} />,
});
});
};
return (
<Checkbox
checked={row.original.application_role === 'doctor'}
onCheckedChange={handleToggle}
disabled={isPending}
/>
);
},
},
{
id: 'actions',
header: '',

View File

@@ -14,6 +14,7 @@ import {
DeleteUserSchema,
ImpersonateUserSchema,
ReactivateUserSchema,
UpdateAccountRoleSchema,
} from './schema/admin-actions.schema';
import { CreateCompanySchema } from './schema/create-company.schema';
import { CreateUserSchema } from './schema/create-user.schema';
@@ -273,6 +274,32 @@ export const createCompanyAccountAction = enhanceAction(
},
);
/**
* @name updateRoleAction
* @description Update application role for user
*/
export const updateRoleAction = adminAction(
enhanceAction(
async ({ accountId, role }) => {
const service = getAdminAccountsService();
const logger = await getLogger();
logger.info({ accountId }, `Super Admin is updating account role...`);
await service.updateRole(accountId, role);
logger.info({ accountId }, `Successfully changed role`);
revalidateAdmin();
return { success: true };
},
{
schema: UpdateAccountRoleSchema,
},
),
);
function revalidateAdmin() {
revalidatePath('/admin', 'layout');
}

View File

@@ -1,5 +1,7 @@
import { z } from 'zod';
import { Database } from '@kit/supabase/database';
const ConfirmationSchema = z.object({
confirmation: z.custom<string>((value) => value === 'CONFIRM'),
});
@@ -16,3 +18,10 @@ export const DeleteUserSchema = UserIdSchema;
export const DeleteAccountSchema = ConfirmationSchema.extend({
accountId: z.string().uuid(),
});
type ApplicationRoleType =
Database['medreport']['Tables']['accounts']['Row']['application_role'];
export const UpdateAccountRoleSchema = z.object({
accountId: z.string().uuid(),
role: z.string() as z.ZodType<ApplicationRoleType>,
});

View File

@@ -22,4 +22,19 @@ class AdminAccountsService {
throw error;
}
}
async updateRole(
accountId: string,
role: Database['medreport']['Tables']['accounts']['Row']['application_role'],
) {
const { error } = await this.adminClient
.schema('medreport')
.from('accounts')
.update({ application_role: role })
.eq('id', accountId);
if (error) {
throw error;
}
}
}