mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-04 10:12:05 +00:00
fix(work-orders): allow read-only open for canceled board rows
This commit is contained in:
parent
32609659b7
commit
fef7918f6b
2 changed files with 83 additions and 43 deletions
|
|
@ -3,7 +3,7 @@ import { Eye, Pencil } from "lucide-react";
|
||||||
type WoTableRowActionsProps = {
|
type WoTableRowActionsProps = {
|
||||||
onView: () => void;
|
onView: () => void;
|
||||||
|
|
||||||
onEdit: () => void;
|
onEdit?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function WoTableRowActions({ onView, onEdit }: WoTableRowActionsProps) {
|
export function WoTableRowActions({ onView, onEdit }: WoTableRowActionsProps) {
|
||||||
|
|
@ -61,7 +61,7 @@ export function WoTableRowActions({ onView, onEdit }: WoTableRowActionsProps) {
|
||||||
<div className="flex items-center justify-end gap-1 opacity-0 transition-opacity group-hover/row:opacity-100">
|
<div className="flex items-center justify-end gap-1 opacity-0 transition-opacity group-hover/row:opacity-100">
|
||||||
{mk(Eye, "View details", onView, "#e6f4fb", "var(--primary)")}
|
{mk(Eye, "View details", onView, "#e6f4fb", "var(--primary)")}
|
||||||
|
|
||||||
{mk(Pencil, "Edit", onEdit, "#e6f4fb", "var(--primary)")}
|
{onEdit ? mk(Pencil, "Edit", onEdit, "#e6f4fb", "var(--primary)") : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,23 +85,37 @@ export function WoTableRow({
|
||||||
}
|
}
|
||||||
|
|
||||||
const patchAndMaybeAuto = (patch: Partial<WorkOrderTableRow>) => {
|
const patchAndMaybeAuto = (patch: Partial<WorkOrderTableRow>) => {
|
||||||
|
if (isCanceled) return;
|
||||||
const merged = { ...row, ...patch };
|
const merged = { ...row, ...patch };
|
||||||
const auto = maybeAutoSchedulePatch(merged);
|
const auto = maybeAutoSchedulePatch(merged);
|
||||||
handlers.onPatch(row.id, { ...patch, ...auto });
|
handlers.onPatch(row.id, { ...patch, ...auto });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const patchRow = (patch: Partial<WorkOrderTableRow>) => {
|
||||||
|
if (isCanceled) return;
|
||||||
|
handlers.onPatch(row.id, patch);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Block mutation controls on canceled rows while keeping row/View clickable. */
|
||||||
|
const mutationCellStyle = isCanceled ? ({ pointerEvents: "none" } as const) : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
id={`wo-row-${row.id}`}
|
id={`wo-row-${row.id}`}
|
||||||
draggable={!isCanceled}
|
draggable={!isCanceled}
|
||||||
title={isCanceled ? "This work order has been cancelled" : undefined}
|
title={isCanceled ? "This work order has been cancelled" : undefined}
|
||||||
onClick={() => handlers.onRowClick(row)}
|
onClick={() => handlers.onRowClick(row)}
|
||||||
onDragStart={() => handlers.onDragStart(row.id)}
|
onDragStart={() => {
|
||||||
|
if (isCanceled) return;
|
||||||
|
handlers.onDragStart(row.id);
|
||||||
|
}}
|
||||||
onDragOver={(e) => {
|
onDragOver={(e) => {
|
||||||
|
if (isCanceled) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handlers.onDragOver(row.id);
|
handlers.onDragOver(row.id);
|
||||||
}}
|
}}
|
||||||
onDrop={(e) => {
|
onDrop={(e) => {
|
||||||
|
if (isCanceled) return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handlers.onDrop();
|
handlers.onDrop();
|
||||||
}}
|
}}
|
||||||
|
|
@ -112,7 +126,6 @@ export function WoTableRow({
|
||||||
borderBottom: "1px solid var(--border)",
|
borderBottom: "1px solid var(--border)",
|
||||||
borderTop: isDropTarget ? "2px solid var(--color-primary)" : undefined,
|
borderTop: isDropTarget ? "2px solid var(--color-primary)" : undefined,
|
||||||
opacity: isCanceled ? 0.45 : isDragging ? 0.4 : 1,
|
opacity: isCanceled ? 0.45 : isDragging ? 0.4 : 1,
|
||||||
pointerEvents: isCanceled ? "none" : undefined,
|
|
||||||
background: isFlashing || isSelected ? "var(--color-primary-tint)" : "var(--card)",
|
background: isFlashing || isSelected ? "var(--color-primary-tint)" : "var(--card)",
|
||||||
outline: isFlashing ? "2px solid var(--color-primary)" : "none",
|
outline: isFlashing ? "2px solid var(--color-primary)" : "none",
|
||||||
outlineOffset: isFlashing ? "-2px" : undefined,
|
outlineOffset: isFlashing ? "-2px" : undefined,
|
||||||
|
|
@ -131,23 +144,34 @@ export function WoTableRow({
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<td
|
<td
|
||||||
style={{ padding: "0 0 0 6px", boxShadow: firstCellShadow }}
|
style={{ padding: "0 0 0 6px", boxShadow: firstCellShadow, ...mutationCellStyle }}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="flex items-center justify-center"
|
className="flex items-center justify-center"
|
||||||
style={{
|
style={{
|
||||||
cursor: isDragging ? "grabbing" : "grab",
|
cursor: isCanceled ? "default" : isDragging ? "grabbing" : "grab",
|
||||||
color: "var(--color-text-muted)",
|
color: "var(--color-text-muted)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<GripVertical size={14} />
|
<GripVertical size={14} />
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td style={{ padding: "0 2px 0 8px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
<FlagCell color={flagColor} onChange={(c) => handlers.setFlag(row.id, c)} />
|
style={{ padding: "0 2px 0 8px", ...mutationCellStyle }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<FlagCell
|
||||||
|
color={flagColor}
|
||||||
|
disabled={isCanceled}
|
||||||
|
onChange={(c) => handlers.setFlag(row.id, c)}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
|
className="group/cell"
|
||||||
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<SiteCell
|
<SiteCell
|
||||||
value={row.site}
|
value={row.site}
|
||||||
location={row.location}
|
location={row.location}
|
||||||
|
|
@ -158,7 +182,7 @@ export function WoTableRow({
|
||||||
sites={sites}
|
sites={sites}
|
||||||
q={search}
|
q={search}
|
||||||
onSave={(p) =>
|
onSave={(p) =>
|
||||||
handlers.onPatch(row.id, {
|
patchRow({
|
||||||
site: p.site,
|
site: p.site,
|
||||||
location: p.location,
|
location: p.location,
|
||||||
locationId: p.locationId,
|
locationId: p.locationId,
|
||||||
|
|
@ -169,7 +193,7 @@ export function WoTableRow({
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td style={{ padding: "0 14px", whiteSpace: "nowrap" }}>
|
<td style={{ padding: "0 14px", whiteSpace: "nowrap", ...mutationCellStyle }}>
|
||||||
<EditableWONumberCell
|
<EditableWONumberCell
|
||||||
value={row.woNumber}
|
value={row.woNumber}
|
||||||
rescheduleCount={row.rescheduleCount}
|
rescheduleCount={row.rescheduleCount}
|
||||||
|
|
@ -177,18 +201,22 @@ export function WoTableRow({
|
||||||
q={search}
|
q={search}
|
||||||
currentId={row.id}
|
currentId={row.id}
|
||||||
allOrders={allRows}
|
allOrders={allRows}
|
||||||
onSave={(v) => handlers.onPatch(row.id, { woNumber: v })}
|
onSave={(v) => patchRow({ woNumber: v })}
|
||||||
onDuplicateFound={handlers.onDuplicateFound}
|
onDuplicateFound={handlers.onDuplicateFound}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
<TypeCell
|
className="group/cell"
|
||||||
value={row.type}
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
q={search}
|
onClick={(e) => e.stopPropagation()}
|
||||||
onSave={(t) => handlers.onPatch(row.id, { type: t })}
|
>
|
||||||
/>
|
<TypeCell value={row.type} q={search} onSave={(t) => patchRow({ type: t })} />
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
|
className="group/cell"
|
||||||
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<AssignedToCell
|
<AssignedToCell
|
||||||
dispatcherId={row.dispatcherId}
|
dispatcherId={row.dispatcherId}
|
||||||
users={users}
|
users={users}
|
||||||
|
|
@ -196,7 +224,11 @@ export function WoTableRow({
|
||||||
onSave={(id, name) => patchAndMaybeAuto({ dispatcherId: id, dispatcherName: name })}
|
onSave={(id, name) => patchAndMaybeAuto({ dispatcherId: id, dispatcherName: name })}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
|
className="group/cell"
|
||||||
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<DateCell
|
<DateCell
|
||||||
value={row.scheduledOn}
|
value={row.scheduledOn}
|
||||||
q={search}
|
q={search}
|
||||||
|
|
@ -215,22 +247,25 @@ export function WoTableRow({
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
<DateCell
|
className="group/cell"
|
||||||
value={row.dueDate}
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
q={search}
|
onClick={(e) => e.stopPropagation()}
|
||||||
onSave={(date) => handlers.onPatch(row.id, { dueDate: date })}
|
>
|
||||||
/>
|
<DateCell value={row.dueDate} q={search} onSave={(date) => patchRow({ dueDate: date })} />
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
<PMTypeCell
|
className="group/cell"
|
||||||
value={row.pm}
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
pmTypes={pmTypes}
|
onClick={(e) => e.stopPropagation()}
|
||||||
q={search}
|
>
|
||||||
onSave={(pm) => handlers.onPatch(row.id, { pm })}
|
<PMTypeCell value={row.pm} pmTypes={pmTypes} q={search} onSave={(pm) => patchRow({ pm })} />
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
|
className="group/cell"
|
||||||
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<VendorCell
|
<VendorCell
|
||||||
company={row.company}
|
company={row.company}
|
||||||
tech={row.tech}
|
tech={row.tech}
|
||||||
|
|
@ -238,7 +273,7 @@ export function WoTableRow({
|
||||||
vendors={vendors}
|
vendors={vendors}
|
||||||
q={search}
|
q={search}
|
||||||
onSave={(p) =>
|
onSave={(p) =>
|
||||||
handlers.onPatch(row.id, {
|
patchRow({
|
||||||
company: p.company,
|
company: p.company,
|
||||||
tech: p.tech,
|
tech: p.tech,
|
||||||
techPhone: p.techPhone,
|
techPhone: p.techPhone,
|
||||||
|
|
@ -246,16 +281,21 @@ export function WoTableRow({
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
<ApptTimeCell
|
className="group/cell"
|
||||||
apptTime={row.apptTime}
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
onSave={(v) => handlers.onPatch(row.id, { apptTime: v })}
|
onClick={(e) => e.stopPropagation()}
|
||||||
/>
|
>
|
||||||
|
<ApptTimeCell apptTime={row.apptTime} onSave={(v) => patchRow({ apptTime: v })} />
|
||||||
</td>
|
</td>
|
||||||
<td className="group/cell" style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td
|
||||||
|
className="group/cell"
|
||||||
|
style={{ padding: "0 14px", ...mutationCellStyle }}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
<StatusCell
|
<StatusCell
|
||||||
wo={row}
|
wo={row}
|
||||||
onChangeStatus={(status) => handlers.onPatch(row.id, { status })}
|
onChangeStatus={(status) => patchRow({ status })}
|
||||||
onOpenSlideOver={() => handlers.onOpenSlideOver(row)}
|
onOpenSlideOver={() => handlers.onOpenSlideOver(row)}
|
||||||
onPastDueAttempt={() => handlers.onPastDueAttempt?.(row.id)}
|
onPastDueAttempt={() => handlers.onPastDueAttempt?.(row.id)}
|
||||||
/>
|
/>
|
||||||
|
|
@ -272,7 +312,7 @@ export function WoTableRow({
|
||||||
<td style={{ padding: "0 8px" }} onClick={(e) => e.stopPropagation()}>
|
<td style={{ padding: "0 8px" }} onClick={(e) => e.stopPropagation()}>
|
||||||
<WoTableRowActions
|
<WoTableRowActions
|
||||||
onView={() => handlers.onView(row)}
|
onView={() => handlers.onView(row)}
|
||||||
onEdit={() => handlers.onEdit(row)}
|
onEdit={isCanceled ? undefined : () => handlers.onEdit(row)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue