improvement: tasks UI responsivness improved for mobile devices.
This commit is contained in:
@@ -28,7 +28,7 @@ export function TaskCaseGroupHeader({ caseGroup, locale }: TaskCaseGroupHeaderPr
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 px-3 py-2.5 bg-background-secondary/60 border-b border-border/80">
|
||||
<div className="sticky top-0 z-10 flex flex-wrap items-center justify-between gap-2 border-b border-border/80 bg-background-secondary/95 px-3 py-2.5 backdrop-blur-sm supports-[backdrop-filter]:bg-background-secondary/80">
|
||||
<div className="min-w-0 space-y-0.5">
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
<p className="text-sm font-semibold text-text-primary truncate">
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Check, FolderOpen, MessageSquare } from 'lucide-react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Badge } from '@/components/ui/shared/Badge';
|
||||
import { Button } from '@/components/ui/shared/Button';
|
||||
import { FORM_SELECT_CLASS } from '@/components/shared/formSelectStyles';
|
||||
import { LAB_TASK_STATUS_SELECT_CLASS } from '@/components/shared/formSelectStyles';
|
||||
import { LabCaseCommentsPanel } from '@/components/ui/lab/LabCaseCommentsPanel';
|
||||
import {
|
||||
canEditLabTaskStatus,
|
||||
@@ -79,12 +79,63 @@ export function TaskRow({
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
|
||||
const commentsButton =
|
||||
canEdit && !exiting ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onToggleComments(task.id)}
|
||||
className={`inline-flex h-[44px] w-[44px] shrink-0 items-center justify-center rounded-md border sm:h-9 sm:w-9 ${
|
||||
commentsOpen
|
||||
? 'border-primary bg-primary/10 text-primary'
|
||||
: 'border-border text-text-muted hover:border-primary/40'
|
||||
}`}
|
||||
title={t('commentsButton')}
|
||||
aria-label={t('commentsButton')}
|
||||
>
|
||||
<MessageSquare className="h-4 w-4" />
|
||||
</button>
|
||||
) : null;
|
||||
|
||||
const statusControl = canEditStatus && !exiting ? (
|
||||
<select
|
||||
value={task.status}
|
||||
disabled={updatingTaskId === task.id || exiting}
|
||||
onChange={(e) => onStatusUpdate(task.id, e.target.value as LabTaskStatus)}
|
||||
className={LAB_TASK_STATUS_SELECT_CLASS}
|
||||
style={labTaskStatusSelectStyle(task.status)}
|
||||
>
|
||||
{statusOptions.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
) : assignedToOther && !exiting ? (
|
||||
<Badge
|
||||
variant="default"
|
||||
fixedWidth={false}
|
||||
className="h-[44px] w-full text-sm text-center whitespace-normal leading-snug sm:h-9 sm:w-auto sm:max-w-[10.5rem] sm:text-xs"
|
||||
>
|
||||
{t('assignedToStaff', { name: task.assignee!.name })}
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge
|
||||
variant={labTaskStatusVariant(task.status)}
|
||||
fixedWidth={false}
|
||||
className="h-[44px] w-full text-sm sm:h-9 sm:w-auto sm:text-xs"
|
||||
>
|
||||
{statusOptions.find((opt) => opt.value === task.status)?.label ?? task.status}
|
||||
</Badge>
|
||||
);
|
||||
|
||||
return (
|
||||
<li id={`task-row-${task.id}`} className={rowClassName}>
|
||||
<div
|
||||
className={`flex flex-col gap-3 px-3 py-3 sm:grid sm:grid-cols-[minmax(0,1fr)_minmax(8.5rem,11rem)_auto] sm:items-center sm:gap-x-3 sm:gap-y-0.5 sm:py-2 ${
|
||||
flatMode ? '' : 'ps-5'
|
||||
}`}
|
||||
className={`flex flex-col gap-3 px-3 py-3 sm:grid sm:items-center sm:gap-x-3 sm:gap-y-0.5 sm:py-2 ${
|
||||
flatMode
|
||||
? 'sm:grid-cols-[minmax(0,1fr)_minmax(10rem,14rem)_auto]'
|
||||
: 'sm:grid-cols-[minmax(0,1fr)_minmax(10rem,14rem)]'
|
||||
} ${flatMode ? '' : 'ps-3 sm:ps-5'}`}
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
@@ -127,68 +178,25 @@ export function TaskRow({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`flex sm:justify-center pe-2 sm:pe-3 shrink-0 ${
|
||||
assignedToOther ? 'mb-1 sm:mb-0' : ''
|
||||
}`}
|
||||
>
|
||||
{canEditStatus && !exiting ? (
|
||||
<select
|
||||
value={task.status}
|
||||
disabled={updatingTaskId === task.id || exiting}
|
||||
onChange={(e) => onStatusUpdate(task.id, e.target.value as LabTaskStatus)}
|
||||
className={`${FORM_SELECT_CLASS} w-full sm:max-w-[132px] font-medium`}
|
||||
style={labTaskStatusSelectStyle(task.status)}
|
||||
>
|
||||
{statusOptions.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>
|
||||
{opt.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
) : assignedToOther && !exiting ? (
|
||||
<Badge
|
||||
variant="default"
|
||||
fixedWidth={false}
|
||||
className="text-center whitespace-normal leading-snug max-w-[10.5rem]"
|
||||
>
|
||||
{t('assignedToStaff', { name: task.assignee!.name })}
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge variant={labTaskStatusVariant(task.status)} fixedWidth={false}>
|
||||
{statusOptions.find((opt) => opt.value === task.status)?.label ?? task.status}
|
||||
</Badge>
|
||||
)}
|
||||
<div className="flex w-full min-w-0 items-stretch gap-2">
|
||||
<div className="min-w-0 flex-1">{statusControl}</div>
|
||||
{commentsButton}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1.5 shrink-0 justify-between sm:justify-end flex-wrap ps-1 sm:ps-0">
|
||||
{flatMode && onShowInCase && !exiting ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-xs px-2 py-1 h-auto"
|
||||
onClick={() => onShowInCase(task)}
|
||||
>
|
||||
<FolderOpen className="h-3.5 w-3.5 me-1" />
|
||||
{t('showInCase')}
|
||||
</Button>
|
||||
) : null}
|
||||
{canEdit && !exiting ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onToggleComments(task.id)}
|
||||
className={`p-1.5 rounded border ${
|
||||
commentsOpen
|
||||
? 'border-primary bg-primary/10 text-primary'
|
||||
: 'border-border text-text-muted hover:border-primary/40'
|
||||
}`}
|
||||
title={t('commentsButton')}
|
||||
>
|
||||
<MessageSquare className="h-4 w-4" />
|
||||
</button>
|
||||
) : null}
|
||||
{flatMode ? (
|
||||
{flatMode ? (
|
||||
<div className="flex items-center gap-1.5 shrink-0 justify-between sm:justify-end flex-wrap">
|
||||
{onShowInCase && !exiting ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-xs px-2 py-1 h-auto"
|
||||
onClick={() => onShowInCase(task)}
|
||||
>
|
||||
<FolderOpen className="h-3.5 w-3.5 me-1" />
|
||||
{t('showInCase')}
|
||||
</Button>
|
||||
) : null}
|
||||
<Badge
|
||||
fixedWidth={false}
|
||||
truncate
|
||||
@@ -201,8 +209,8 @@ export function TaskRow({
|
||||
>
|
||||
{task.prosthesisTypeLabel}
|
||||
</Badge>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{commentsOpen && canEdit && !exiting ? (
|
||||
|
||||
@@ -282,7 +282,7 @@ export function TasksPage() {
|
||||
[canEdit, loadTasks, setError, showError, showSuccess, statusFilter, t, tErrors],
|
||||
);
|
||||
|
||||
const filterSelectClass = `${FORM_SELECT_CLASS} w-full rounded-md px-2 py-1.5 text-sm`;
|
||||
const filterSelectClass = `${FORM_SELECT_CLASS} w-full min-h-[44px] rounded-md px-2 py-2 text-base sm:min-h-0 sm:py-1.5 sm:text-sm`;
|
||||
|
||||
const sortHintKey = useMemo(() => {
|
||||
switch (sortBy) {
|
||||
@@ -467,7 +467,7 @@ export function TasksPage() {
|
||||
) : null}
|
||||
</section>
|
||||
|
||||
<section className="surface-card min-h-[280px]">
|
||||
<section className="surface-card min-h-[280px] overflow-x-hidden">
|
||||
{(loading || locatingCase) && tasks.length === 0 ? (
|
||||
<p className="p-3 text-sm text-text-muted">
|
||||
{locatingCase ? t('locatingCase') : t('loading')}
|
||||
|
||||
Reference in New Issue
Block a user