Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions hms-ui/src/api/departments.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import api from './axiosInstance';
import type { ApiResponse, Department } from '../types';
import type { ApiResponse, Department, PaginatedResponse } from '../types';

export const getDepartments = (params?: { page?: number; size?: number }) =>
api.get<ApiResponse<Department[]>>('/departments', { params });
api.get<ApiResponse<PaginatedResponse<Department>>>('/departments', { params });
16 changes: 16 additions & 0 deletions hms-ui/src/constants/roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const ROLES = {
ADMIN: 'ROLE_ADMIN',
DOCTOR: 'ROLE_DOCTOR',
RECEPTIONIST: 'ROLE_RECEPTIONIST',
PHARMACIST: 'ROLE_PHARMACIST',
CASHIER: 'ROLE_CASHIER',
PATIENT: 'ROLE_PATIENT',
} as const;

export const ROLE_NAMES = {
ADMIN: 'ADMIN',
DOCTOR: 'DOCTOR',
RECEPTIONIST: 'RECEPTIONIST',
PHARMACIST: 'PHARMACIST',
CASHIER: 'CASHIER',
} as const;
11 changes: 6 additions & 5 deletions hms-ui/src/pages/admin/CreateEmployeePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useState } from 'react';
import { createEmployee } from '../../api/employees';
import { getDepartments } from '../../api/departments';
import type { CreateEmployeeRequest } from '../../types';
import { ROLE_NAMES } from '../../constants/roles';
import dayjs from 'dayjs';

const { Title } = Typography;
Expand Down Expand Up @@ -154,17 +155,17 @@ export default function CreateEmployeePage() {
<Col span={12}>
<Form.Item label="Role" name="role" rules={[{ required: true }]}>
<Select placeholder="Select role">
<Select.Option value="DOCTOR">Doctor</Select.Option>
<Select.Option value="RECEPTIONIST">Receptionist</Select.Option>
<Select.Option value="PHARMACIST">Pharmacist</Select.Option>
<Select.Option value="CASHIER">Cashier</Select.Option>
<Select.Option value={ROLE_NAMES.DOCTOR}>Doctor</Select.Option>
<Select.Option value={ROLE_NAMES.RECEPTIONIST}>Receptionist</Select.Option>
<Select.Option value={ROLE_NAMES.PHARMACIST}>Pharmacist</Select.Option>
<Select.Option value={ROLE_NAMES.CASHIER}>Cashier</Select.Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="Department" name="departmentId" rules={[{ required: true }]}>
<Select placeholder="Select department" loading={!deptData}>
{deptData?.data?.map((dept) => (
{deptData?.data?.content?.map((dept) => (
<Select.Option key={dept.id} value={dept.id}>
{dept.name}
</Select.Option>
Expand Down
19 changes: 10 additions & 9 deletions hms-ui/src/pages/admin/EmployeeListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { getEmployees, deactivateEmployee, activateEmployee } from '../../api/employees';
import type { Employee } from '../../types';
import { ROLE_NAMES } from '../../constants/roles';

const { Title } = Typography;

Expand Down Expand Up @@ -63,11 +64,11 @@ export default function EmployeeListPage() {
key: 'role',
render: (role: { name: string }) => {
const colorMap: Record<string, string> = {
DOCTOR: 'blue',
RECEPTIONIST: 'green',
PHARMACIST: 'purple',
CASHIER: 'orange',
ADMIN: 'red',
[ROLE_NAMES.DOCTOR]: 'blue',
[ROLE_NAMES.RECEPTIONIST]: 'green',
[ROLE_NAMES.PHARMACIST]: 'purple',
[ROLE_NAMES.CASHIER]: 'orange',
[ROLE_NAMES.ADMIN]: 'red',
};
return <Tag color={colorMap[role?.name] ?? 'default'}>{role?.name}</Tag>;
},
Expand Down Expand Up @@ -147,10 +148,10 @@ export default function EmployeeListPage() {
allowClear
onChange={(val) => { setRole(val); setPage(1); }}
>
<Select.Option value="DOCTOR">Doctor</Select.Option>
<Select.Option value="RECEPTIONIST">Receptionist</Select.Option>
<Select.Option value="PHARMACIST">Pharmacist</Select.Option>
<Select.Option value="CASHIER">Cashier</Select.Option>
<Select.Option value={ROLE_NAMES.DOCTOR}>Doctor</Select.Option>
<Select.Option value={ROLE_NAMES.RECEPTIONIST}>Receptionist</Select.Option>
<Select.Option value={ROLE_NAMES.PHARMACIST}>Pharmacist</Select.Option>
<Select.Option value={ROLE_NAMES.CASHIER}>Cashier</Select.Option>
</Select>
<Button
type="primary"
Expand Down
3 changes: 2 additions & 1 deletion hms-ui/src/pages/shared/MedicalRecordDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useParams, useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { getMedicalRecordById, updateMedicalRecord } from '../../api/medicalRecords';
import { useAuthStore } from '../../store/authStore';
import { ROLES } from '../../constants/roles';
import dayjs from 'dayjs';

const { Title, Text } = Typography;
Expand All @@ -15,7 +16,7 @@ export default function MedicalRecordDetailPage() {
const navigate = useNavigate();
const queryClient = useQueryClient();
const user = useAuthStore((s) => s.user);
const isDoctor = user?.roles.includes('ROLE_DOCTOR') ?? false;
const isDoctor = user?.roles.includes(ROLES.DOCTOR) ?? false;

const [editOpen, setEditOpen] = useState(false);
const [form] = Form.useForm();
Expand Down
13 changes: 11 additions & 2 deletions hms-ui/src/pages/shared/MedicalRecordsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Table, Card, Input, Button, Space, Typography, DatePicker, Divider } from 'antd';
import { Table, Card, Input, Button, Space, Typography, DatePicker, Divider, Alert } from 'antd';
import { SearchOutlined, EyeOutlined } from '@ant-design/icons';
import { useQuery } from '@tanstack/react-query';
import { useState } from 'react';
Expand All @@ -19,7 +19,7 @@ export default function MedicalRecordsPage() {
const [searchInput, setSearchInput] = useState('');
const [doctorInput, setDoctorInput] = useState('');

const { data, isLoading } = useQuery({
const { data, isLoading, isError } = useQuery({
queryKey: ['medical-records', page, keyword, doctorName, dateRange],
queryFn: () =>
getMedicalRecords({
Expand Down Expand Up @@ -134,6 +134,15 @@ export default function MedicalRecordsPage() {
</Space>

<Divider style={{ margin: '0 0 16px 0' }} />
{isError && (
<Alert
type="error"
message="Failed to load medical records"
description="The request failed. Check your connection or try again."
showIcon
style={{ marginBottom: 16 }}
/>
)}
<Table
dataSource={data?.data?.content ?? []}
columns={columns}
Expand Down
11 changes: 6 additions & 5 deletions hms-ui/src/utils/jwt.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { JwtPayload, UserInfo } from '../types';
import { ROLES } from '../constants/roles';

export function decodeJwt(token: string): JwtPayload | null {
try {
Expand Down Expand Up @@ -28,8 +29,8 @@ export function extractUserInfo(token: string): UserInfo | null {
}

export function getPrimaryRole(roles: string[]): string {
const priority = ['ROLE_ADMIN', 'ROLE_DOCTOR', 'ROLE_RECEPTIONIST', 'ROLE_PHARMACIST', 'ROLE_CASHIER', 'ROLE_PATIENT'];
return priority.find((r) => roles.includes(r)) ?? 'ROLE_PATIENT';
const priority = [ROLES.ADMIN, ROLES.DOCTOR, ROLES.RECEPTIONIST, ROLES.PHARMACIST, ROLES.CASHIER, ROLES.PATIENT];
return priority.find((r) => roles.includes(r)) ?? ROLES.PATIENT;
}

export function isTokenExpired(token: string): boolean {
Expand All @@ -41,9 +42,9 @@ export function isTokenExpired(token: string): boolean {
export function getRoleRedirectPath(roles: string[]): string {
const role = getPrimaryRole(roles);
switch (role) {
case 'ROLE_ADMIN': return '/admin/employees';
case 'ROLE_DOCTOR': return '/doctor/medical-records';
case 'ROLE_RECEPTIONIST': return '/receptionist/medical-records';
case ROLES.ADMIN: return '/admin/employees';
case ROLES.DOCTOR: return '/doctor/medical-records';
case ROLES.RECEPTIONIST: return '/receptionist/medical-records';
default: return '/patient/dashboard';
}
}
Loading