improvement: task assignment flow added. cases and tasks feature updated accordingly.

This commit is contained in:
2026-07-13 15:47:32 +03:30
parent 0d073f1ec0
commit a391eee15f
21 changed files with 357 additions and 35 deletions

View File

@@ -7,6 +7,7 @@ import { Badge } from '@/components/ui/shared/Badge';
import { Button } from '@/components/ui/shared/Button';
import { Checkbox } from '@/components/ui/shared/Checkbox';
import { CaseToothChartPanel } from '@/components/ui/lab/CaseToothChartPanel';
import { FORM_SELECT_CLASS } from '@/components/shared/formSelectStyles';
import { LabCaseAttachmentPreview } from '@/components/ui/lab/LabCaseAttachmentPreview';
import { LabCaseAttachmentsDialog } from '@/components/ui/lab/LabCaseAttachmentsDialog';
import { labTaskStatusVariant } from '@/components/lab/labTaskStatusDisplay';
@@ -21,7 +22,7 @@ import {
formatPatientName,
latestCaseAttachment,
} from '@/components/lab/caseDetailUtils';
import type { LabCaseDetail, LabTaskStatus } from '@/types/cases';
import type { AssignableTaskStaff, LabCaseDetail, LabTaskStatus } from '@/types/cases';
import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog';
function CaseTaskProgressBar({ completed, total }: { completed: number; total: number }) {
@@ -60,6 +61,10 @@ export interface CaseDetailPanelProps {
updatingImportant?: boolean;
onImportantChange?: (checked: boolean) => void;
commentsSection?: ReactNode;
assignableStaff?: AssignableTaskStaff[];
canAssignTasks?: boolean;
assigningTaskId?: string | null;
onAssignTask?: (taskId: string, assigneeUserId: string | null) => void;
}
export function CaseDetailPanel({
@@ -76,6 +81,10 @@ export function CaseDetailPanel({
updatingImportant = false,
onImportantChange,
commentsSection,
assignableStaff = [],
canAssignTasks = false,
assigningTaskId = null,
onAssignTask,
}: CaseDetailPanelProps) {
const t = useTranslations('cases');
const [attachmentsDialogOpen, setAttachmentsDialogOpen] = useState(false);
@@ -213,24 +222,42 @@ export function CaseDetailPanel({
</div>
<ul className="space-y-2">
{group.tasks.map((task) => (
<li key={task.id} className="rounded bg-background p-2 text-sm space-y-1">
<div className="flex flex-wrap items-center gap-2">
<span className="min-w-0 flex-1">
<li key={task.id} className="rounded bg-background px-2 py-1.5 text-sm">
<div className="flex flex-wrap items-center gap-x-2 gap-y-1">
<span className="min-w-0 flex-1 font-medium text-text-primary">
{task.stepOrder}. {task.stepLabel}
</span>
<span className="text-[11px] text-text-muted shrink-0">
{task.lastStatusChangedBy
? t('lastUpdatedBy', { name: task.lastStatusChangedBy.name })
: t('lastUpdatedUnknown')}
{task.lastStatusChangedAt
? ` · ${formatCaseDateTime(task.lastStatusChangedAt, locale)}`
: ''}
</span>
{canAssignTasks && onAssignTask ? (
<select
value={task.assignee?.id ?? ''}
disabled={assigningTaskId === task.id}
onChange={(e) =>
onAssignTask(task.id, e.target.value ? e.target.value : null)
}
aria-label={t('assigneeLabel')}
className={`${FORM_SELECT_CLASS} max-w-[9.5rem] rounded-md px-2 py-0.5 text-xs`}
>
<option value="">{t('assigneeUnassigned')}</option>
{assignableStaff.map((staff) => (
<option key={staff.id} value={staff.id}>
{staff.name}
</option>
))}
</select>
) : null}
<Badge variant={labTaskStatusVariant(task.status)} fixedWidth={false}>
{statusOptions.find((opt) => opt.value === task.status)?.label ??
task.status}
</Badge>
</div>
<p className="text-[11px] text-text-muted">
{task.lastStatusChangedBy
? t('lastUpdatedBy', { name: task.lastStatusChangedBy.name })
: t('lastUpdatedUnknown')}
{task.lastStatusChangedAt
? ` · ${formatCaseDateTime(task.lastStatusChangedAt, locale)}`
: ''}
</p>
</li>
))}
</ul>