feat(tasks): stato "In revisione", con gli stati finalmente in un posto solo
Mancava il modo di dire "finito, ma da controllare prima di consegnarlo". Il nuovo stato sta fra "In corso" e "Fatto" ed e' visibile anche al cliente: il lavoro c'e' ed e' in controllo qualita', non e' fermo. Il costo non era la logica ma la dispersione: tre letterali ricopiati a mano in otto file, in tre forme diverse (allow-list a runtime, union TS, colonne kanban, opzioni della select) e nessun CHECK in DB a tenerli insieme. Invece di modificarne quattordici occorrenze, tutto deriva da TASK_STATUSES in src/lib/task-status.ts: la prossima aggiunta costa una riga. Due punti perdevano dati in silenzio, ed erano il vero motivo per centralizzare: - recomputePhaseStatus considerava "iniziato" solo in_progress|done, come lista. Una fase con tutti i task in revisione non rientrava ne' in allDone ne' in anyActive e retrocedeva a "upcoming": si leggeva "non iniziata" quando era quasi finita. Ora e' la negazione di "todo", e regge anche il prossimo stato. - ClientKanban ripartiva i task con un oggetto a tre chiavi fisse, non derivato dalle colonne: un task fuori da quelle spariva da ogni colonna e da ogni contatore, e il cliente ne vedeva meno di quanti ce n'erano, senza errore. Chiuso anche il cast non verificato al confine del portale (page.tsx), che era la causa a monte di entrambi: ora ci passa normalizeTaskStatus. Nessuna migration: tasks.status e' text senza CHECK, le righe esistenti valgono. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useState } from "react";
|
||||
import { ApproveButton } from "@/components/client/ApproveButton";
|
||||
import { useChatContext } from "@/components/client/ChatProvider";
|
||||
import type { ClientView } from "@/lib/client-view";
|
||||
import { TASK_STATUS_LABELS, type TaskStatus } from "@/lib/task-status";
|
||||
|
||||
type Phase = ClientView["phases"][number];
|
||||
|
||||
@@ -28,7 +29,7 @@ const phaseBarColor: Record<"upcoming" | "active" | "done", string> = {
|
||||
done: "bg-emerald-600",
|
||||
};
|
||||
|
||||
function TaskStatusIcon({ status }: { status: "todo" | "in_progress" | "done" }) {
|
||||
function TaskStatusIcon({ status }: { status: TaskStatus }) {
|
||||
if (status === "done") {
|
||||
return (
|
||||
<span className="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-emerald-50 text-[10px] font-bold text-emerald-600 dark:bg-emerald-500/10 dark:text-emerald-400">
|
||||
@@ -36,6 +37,16 @@ function TaskStatusIcon({ status }: { status: "todo" | "in_progress" | "done" })
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (status === "in_review") {
|
||||
return (
|
||||
<span
|
||||
className="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 border-violet-400 bg-card dark:border-violet-500"
|
||||
title={TASK_STATUS_LABELS.in_review}
|
||||
>
|
||||
<span className="h-2 w-2 rounded-full bg-violet-500 dark:bg-violet-400" />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
if (status === "in_progress") {
|
||||
return (
|
||||
<span className="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 border-amber-400 bg-card">
|
||||
|
||||
Reference in New Issue
Block a user