Task card: due date urgency bg, clickable status dropdown, plain text level, consistent text-xs
This commit is contained in:
parent
a215d7ce44
commit
4852acafda
1 changed files with 51 additions and 9 deletions
|
|
@ -97,6 +97,7 @@ function TaskCard({ task: initial }: { task: Task }) {
|
|||
const [naReason, setNaReason] = useState('')
|
||||
const [naSubmitting, setNaSubmitting] = useState(false)
|
||||
const [editOpen, setEditOpen] = useState(false)
|
||||
const [statusUpdating, setStatusUpdating] = useState(false)
|
||||
const [completeDialogOpen, setCompleteDialogOpen] = useState(false)
|
||||
const [imageRightFiled, setImageRightFiled] = useState<boolean | null>(null)
|
||||
const [reminderDate, setReminderDate] = useState('')
|
||||
|
|
@ -199,11 +200,41 @@ function TaskCard({ task: initial }: { task: Task }) {
|
|||
}
|
||||
|
||||
const levelLabel = task.policyGroup ? 'Group' : task.policy ? 'Policy' : 'Client'
|
||||
const levelColor = task.policyGroup
|
||||
? 'bg-purple-500/10 text-purple-700 dark:text-purple-400'
|
||||
: task.policy
|
||||
? 'bg-blue-500/10 text-blue-700 dark:text-blue-400'
|
||||
: 'bg-muted text-muted-foreground'
|
||||
|
||||
const handleQuickStatus = async (newStatus: string) => {
|
||||
if (newStatus === task.status) return
|
||||
if (newStatus === 'NA') { setNaDialogOpen(true); return }
|
||||
if (newStatus === 'COMPLETED') { handleToggleStatus(); return }
|
||||
setStatusUpdating(true)
|
||||
try {
|
||||
const res = await fetch(`/api/tasks/${task.id}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ status: newStatus }),
|
||||
})
|
||||
if (!res.ok) throw new Error((await res.json()).error)
|
||||
setTask((t) => ({ ...t, status: newStatus }))
|
||||
toast.success(`Status → ${newStatus.replace('_', ' ')}`)
|
||||
} catch (err: any) {
|
||||
toast.error(err.message)
|
||||
} finally {
|
||||
setStatusUpdating(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Due date urgency background
|
||||
const dueMs = new Date(task.dueDate).getTime()
|
||||
const nowMs = now.getTime()
|
||||
const daysUntilDue = Math.ceil((dueMs - nowMs) / 86400000)
|
||||
const dueBg = isCompleted
|
||||
? 'bg-muted/50'
|
||||
: daysUntilDue < 0
|
||||
? 'bg-red-500/15'
|
||||
: daysUntilDue <= 7
|
||||
? 'bg-red-500/10'
|
||||
: daysUntilDue <= 14
|
||||
? 'bg-orange-500/10'
|
||||
: 'bg-muted/40'
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -243,12 +274,23 @@ function TaskCard({ task: initial }: { task: Task }) {
|
|||
<div className="shrink-0 border-l border-border flex flex-col text-[12px]">
|
||||
<div className="flex-1 flex">
|
||||
{/* Left col: Due / Status / Level (data only, fit to content) */}
|
||||
<div className="flex flex-col justify-center gap-1.5 px-3 py-2.5 whitespace-nowrap">
|
||||
<span className={`font-medium ${isOverdue ? 'text-red-500' : 'text-foreground'}`} suppressHydrationWarning>
|
||||
<div className="flex flex-col justify-center gap-1 px-3 py-2.5 whitespace-nowrap text-xs">
|
||||
<span className={`font-bold rounded px-1.5 py-0.5 w-fit ${dueBg}`} suppressHydrationWarning>
|
||||
{formatDate(task.dueDate)}
|
||||
</span>
|
||||
<StatusBadge status={task.status} />
|
||||
<span className={`inline-flex items-center rounded-full px-1.5 py-0.5 text-[10px] font-medium w-fit ${levelColor}`}>
|
||||
<Select value={task.status} onValueChange={handleQuickStatus} disabled={statusUpdating}>
|
||||
<SelectTrigger className="h-auto border-0 p-0 shadow-none text-xs font-medium hover:underline focus:ring-0 w-auto gap-1">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="NOT_STARTED">Not Started</SelectItem>
|
||||
<SelectItem value="IN_PROGRESS">In Progress</SelectItem>
|
||||
<SelectItem value="BLOCKED">Blocked</SelectItem>
|
||||
<SelectItem value="COMPLETED">Completed</SelectItem>
|
||||
<SelectItem value="NA">N/A</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{levelLabel}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue