246 lines
7.4 KiB
TypeScript
246 lines
7.4 KiB
TypeScript
'use client';
|
|
|
|
import { useTransition } from 'react';
|
|
|
|
import Link from 'next/link';
|
|
|
|
import { format } from 'date-fns';
|
|
import { capitalize } from 'lodash';
|
|
import { Eye } from 'lucide-react';
|
|
|
|
import { getResultSetName } from '@kit/doctor/lib/helpers';
|
|
import { ResponseTable } from '@kit/doctor/schema/doctor-analysis.schema';
|
|
import { pathsConfig } from '@kit/shared/config';
|
|
import { useCurrentLocaleLanguageNames } from '@kit/shared/hooks';
|
|
import { getFullName } from '@kit/shared/utils';
|
|
import { useUser } from '@kit/supabase/hooks/use-user';
|
|
import { Button } from '@kit/ui/button';
|
|
import { toast } from '@kit/ui/sonner';
|
|
import {
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableHead,
|
|
TableHeader,
|
|
TableRow,
|
|
} from '@kit/ui/table';
|
|
import { Trans } from '@kit/ui/trans';
|
|
|
|
import DoctorJobSelect from './doctor-job-select';
|
|
|
|
export default function ResultsTable({
|
|
results = [],
|
|
pagination = {
|
|
currentPage: 1,
|
|
totalPages: 1,
|
|
totalCount: 0,
|
|
pageSize: 10,
|
|
},
|
|
fetchAction,
|
|
onJobUpdate,
|
|
}: {
|
|
results: ResponseTable[] | null;
|
|
pagination?: {
|
|
currentPage: number;
|
|
totalPages: number;
|
|
totalCount: number;
|
|
pageSize: number;
|
|
};
|
|
fetchAction: ({
|
|
page,
|
|
pageSize,
|
|
}: {
|
|
page: number;
|
|
pageSize: number;
|
|
}) => Promise<{
|
|
success: boolean;
|
|
data: null;
|
|
}>;
|
|
onJobUpdate: () => void;
|
|
}) {
|
|
const [isPending, startTransition] = useTransition();
|
|
const { data: currentUser } = useUser();
|
|
|
|
const languageNames = useCurrentLocaleLanguageNames();
|
|
|
|
const fetchPage = async (page: number) => {
|
|
startTransition(async () => {
|
|
const result = await fetchAction({
|
|
page,
|
|
pageSize: pagination.pageSize,
|
|
});
|
|
if (!result.success) {
|
|
toast.error('common.genericServerError');
|
|
}
|
|
});
|
|
};
|
|
|
|
const handleNextPage = () => {
|
|
if (pagination.currentPage < pagination.totalPages) {
|
|
fetchPage(pagination.currentPage + 1);
|
|
}
|
|
};
|
|
|
|
const handlePrevPage = () => {
|
|
if (pagination.currentPage > 1) {
|
|
fetchPage(pagination.currentPage - 1);
|
|
}
|
|
};
|
|
|
|
const handleJobUpdate = () => {
|
|
onJobUpdate();
|
|
fetchPage(pagination.currentPage);
|
|
};
|
|
|
|
if (!results?.length) {
|
|
return (
|
|
<p>
|
|
<Trans i18nKey="common:noData" />.
|
|
</p>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Table className="border-separate rounded-lg border">
|
|
<TableHeader className="text-ui-fg-subtle txt-medium-plus">
|
|
<TableRow>
|
|
<TableHead className="w-6"></TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.patientName" />
|
|
</TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.serviceName" />
|
|
</TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.orderNr" />
|
|
</TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.time" />
|
|
</TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.resultsStatus" />
|
|
</TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.language" />
|
|
</TableHead>
|
|
<TableHead className="w-20">
|
|
<Trans i18nKey="doctor:resultsTable.assignedTo" />
|
|
</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{results
|
|
?.sort((a, b) =>
|
|
(a.created_at ?? '') > (b.created_at ?? '') ? -1 : 1,
|
|
)
|
|
.map((result) => {
|
|
const isCompleted = result.feedback?.status === 'COMPLETED';
|
|
const isCurrentDoctorJob =
|
|
!!result.doctor?.primary_owner_user_id &&
|
|
result.doctor?.primary_owner_user_id === currentUser?.id;
|
|
|
|
const resultsReceived = result.elements.length || 0;
|
|
const elementsInOrder = Array.from(
|
|
new Set(result.analysis_order_id.analysis_element_ids),
|
|
)?.length;
|
|
|
|
return (
|
|
<TableRow key={result.order_number}>
|
|
<TableCell className="text-center">
|
|
<Link
|
|
href={`/${pathsConfig.app.analysisDetails}/${result.id}`}
|
|
>
|
|
<Eye />
|
|
</Link>
|
|
</TableCell>
|
|
<TableCell>
|
|
{getFullName(
|
|
result.patient?.name,
|
|
result.patient?.last_name,
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
<Trans
|
|
i18nKey={getResultSetName(
|
|
result.order?.title ?? '-',
|
|
result.order?.isPackage,
|
|
result.elements?.length || 0,
|
|
)}
|
|
/>
|
|
</TableCell>
|
|
<TableCell>{result.order_number}</TableCell>
|
|
<TableCell>
|
|
{result.firstSampleGivenAt
|
|
? format(result.firstSampleGivenAt, 'dd.MM.yyyy HH:mm')
|
|
: '-'}
|
|
</TableCell>
|
|
<TableCell>
|
|
<Trans
|
|
i18nKey={
|
|
resultsReceived === elementsInOrder
|
|
? 'doctor:resultsTable.responsesReceived'
|
|
: 'doctor:resultsTable.waitingForNr'
|
|
}
|
|
values={{
|
|
nr: elementsInOrder - resultsReceived,
|
|
}}
|
|
/>
|
|
</TableCell>
|
|
<TableCell>
|
|
{capitalize(
|
|
languageNames.of(
|
|
result?.patient?.preferred_locale ?? 'et',
|
|
),
|
|
)}
|
|
</TableCell>
|
|
<TableCell>
|
|
<DoctorJobSelect
|
|
doctorUserId={result.doctor?.primary_owner_user_id}
|
|
doctorName={getFullName(
|
|
result.doctor?.name,
|
|
result.doctor?.last_name,
|
|
)}
|
|
analysisOrderId={result.analysis_order_id?.id}
|
|
userId={result.patient?.id}
|
|
isRemovable={!isCompleted && isCurrentDoctorJob}
|
|
onJobUpdate={handleJobUpdate}
|
|
linkTo={`/${pathsConfig.app.analysisDetails}/${result.id}`}
|
|
/>
|
|
</TableCell>
|
|
</TableRow>
|
|
);
|
|
})}
|
|
</TableBody>
|
|
</Table>
|
|
<div className="mt-4 flex items-center justify-between">
|
|
<Button
|
|
onClick={handlePrevPage}
|
|
disabled={pagination.currentPage === 1 || isPending}
|
|
variant="outline"
|
|
>
|
|
<Trans i18nKey="common:previous" />
|
|
</Button>
|
|
<span className="text-sm text-gray-600">
|
|
<Trans
|
|
i18nKey={'common:pageOfPages'}
|
|
values={{
|
|
page: pagination.currentPage,
|
|
total: pagination.totalPages,
|
|
}}
|
|
/>
|
|
</span>
|
|
<Button
|
|
onClick={handleNextPage}
|
|
disabled={
|
|
pagination.currentPage === pagination.totalPages || isPending
|
|
}
|
|
variant="outline"
|
|
>
|
|
<Trans i18nKey="common:next" />
|
|
</Button>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|