mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-09-30 05:43:12 +00:00
fix(work-orders): keep uplift history reachable on closed work orders
The Uplift column hid its trigger on a Completed or Canceled work order with no live uplift, so once cancelled/revoked uplifts stop counting as "has uplift", their read-only history had no way in. The cell now always opens the uplifts dialog; closed work orders show a dash instead of Manage.
This commit is contained in:
parent
f068beb45e
commit
a2d03f9461
4 changed files with 90 additions and 19 deletions
|
|
@ -7,9 +7,11 @@ import {
|
|||
type UpliftCellProps = {
|
||||
summary: UpliftSummary;
|
||||
onOpen?: () => void;
|
||||
/** Closed work orders show a dash (not "Manage") that still opens the read-only history. */
|
||||
readOnly?: boolean;
|
||||
};
|
||||
|
||||
export function UpliftCell({ summary, onOpen }: UpliftCellProps) {
|
||||
export function UpliftCell({ summary, onOpen, readOnly = false }: UpliftCellProps) {
|
||||
const label = getUpliftCellLabel(summary);
|
||||
|
||||
if (!onOpen) {
|
||||
|
|
@ -30,7 +32,7 @@ export function UpliftCell({ summary, onOpen }: UpliftCellProps) {
|
|||
e.stopPropagation();
|
||||
onOpen();
|
||||
}}
|
||||
title={label ? "View uplifts" : "Manage uplifts"}
|
||||
title={label || readOnly ? "View uplifts" : "Manage uplifts"}
|
||||
className="flex w-full items-center justify-start transition-opacity hover:opacity-80"
|
||||
>
|
||||
{label && pillStyle ? (
|
||||
|
|
@ -40,6 +42,8 @@ export function UpliftCell({ summary, onOpen }: UpliftCellProps) {
|
|||
>
|
||||
{label}
|
||||
</span>
|
||||
) : readOnly ? (
|
||||
<span className="text-[11px] text-[var(--color-text-muted)]">—</span>
|
||||
) : (
|
||||
<span className="text-[11px] font-semibold text-[var(--color-primary)]">Manage</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { StatusCell } from "./cells/status-cell";
|
|||
import { UpliftCell } from "./cells/uplift-cell";
|
||||
import { VendorCell } from "./cells/vendor-cell";
|
||||
import { EMPTY_UPLIFT_SUMMARY } from "@/domain/work-orders/types/work-order-uplift";
|
||||
import { canOpenUpliftsDialog } from "@/domain/work-orders/utils/uplift-display-utils";
|
||||
import { isWorkOrderUpliftsReadOnly } from "@/domain/work-orders/utils/uplift-display-utils";
|
||||
import { applyVendorTableSave } from "@/domain/work-orders/utils/work-order-feedback-toasts";
|
||||
import { effectiveCompany } from "@/domain/work-orders/utils/effective-completion-snapshot";
|
||||
import type { WoTableRowHandlers } from "./wo-table-row";
|
||||
|
|
@ -132,12 +132,8 @@ export function WoTableRowServiceCells({
|
|||
<td style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
||||
<UpliftCell
|
||||
summary={row.upliftSummary ?? EMPTY_UPLIFT_SUMMARY}
|
||||
onOpen={
|
||||
canOpenUpliftsDialog(row.upliftSummary ?? EMPTY_UPLIFT_SUMMARY, row.status) &&
|
||||
handlers.onOpenUplifts
|
||||
? () => handlers.onOpenUplifts!(row)
|
||||
: undefined
|
||||
}
|
||||
onOpen={handlers.onOpenUplifts ? () => handlers.onOpenUplifts!(row) : undefined}
|
||||
readOnly={isWorkOrderUpliftsReadOnly(row.status)}
|
||||
/>
|
||||
</td>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -74,16 +74,6 @@ export function isWorkOrderUpliftsReadOnly(status: WorkOrderTableRow["status"]):
|
|||
return status === "Completed" || status === "Canceled";
|
||||
}
|
||||
|
||||
export function canOpenUpliftsDialog(
|
||||
summary: UpliftSummary,
|
||||
status: WorkOrderTableRow["status"],
|
||||
): boolean {
|
||||
if (summary.hasUplift || summary.pendingCount > 0) {
|
||||
return true;
|
||||
}
|
||||
return !isWorkOrderUpliftsReadOnly(status);
|
||||
}
|
||||
|
||||
export function canRevokeWorkOrderUplift(
|
||||
uplift: Pick<WorkOrderUplift, "status" | "requestedById">,
|
||||
currentUserId: string | number | null | undefined,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
import { fireEvent, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { WoTableRowServiceCells } from "@/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells";
|
||||
import type { WoTableRowHandlers } from "@/app/(protected)/workorders/_components/list/table/wo-table-row";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
import { renderWithProviders } from "@/test/test-utils";
|
||||
|
||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/pm-type-cell", () => ({
|
||||
PMTypeCell: () => null,
|
||||
}));
|
||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/appt-time-cell", () => ({
|
||||
ApptTimeCell: () => null,
|
||||
}));
|
||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/status-cell", () => ({
|
||||
StatusCell: () => null,
|
||||
}));
|
||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/comp-doc-cell", () => ({
|
||||
CompDocCell: () => null,
|
||||
}));
|
||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/date-cell", () => ({
|
||||
DateCell: () => null,
|
||||
}));
|
||||
vi.mock("@/app/(protected)/workorders/_components/list/table/cells/vendor-cell", () => ({
|
||||
VendorCell: () => null,
|
||||
}));
|
||||
|
||||
function renderCells(row: WorkOrderTableRow, onOpenUplifts = vi.fn()) {
|
||||
const handlers = { onOpenUplifts } as unknown as WoTableRowHandlers;
|
||||
renderWithProviders(
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<WoTableRowServiceCells
|
||||
row={row}
|
||||
vendors={[]}
|
||||
pmTypes={[]}
|
||||
handlers={handlers}
|
||||
onPatchRow={vi.fn()}
|
||||
/>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>,
|
||||
{ withAuth: false },
|
||||
);
|
||||
return onOpenUplifts;
|
||||
}
|
||||
|
||||
describe("WoTableRowServiceCells uplift column", () => {
|
||||
// A closed work order whose uplifts were all cancelled or revoked has no live uplift,
|
||||
// but its read-only uplift history must stay one click away.
|
||||
it.each(["Completed", "Canceled"] as const)(
|
||||
"opens the read-only uplift history from a dash on a %s work order with no live uplift",
|
||||
(status) => {
|
||||
const row = {
|
||||
id: 7,
|
||||
status,
|
||||
upliftSummary: { hasUplift: false, pendingCount: 0 },
|
||||
} as WorkOrderTableRow;
|
||||
|
||||
const onOpenUplifts = renderCells(row);
|
||||
|
||||
const trigger = screen.getByRole("button", { name: "—" });
|
||||
expect(screen.queryByText("Manage")).not.toBeInTheDocument();
|
||||
fireEvent.click(trigger);
|
||||
expect(onOpenUplifts).toHaveBeenCalledWith(row);
|
||||
},
|
||||
);
|
||||
|
||||
it("offers Manage on an open work order with no live uplift", () => {
|
||||
const row = {
|
||||
id: 8,
|
||||
status: "Scheduled",
|
||||
upliftSummary: { hasUplift: false, pendingCount: 0 },
|
||||
} as WorkOrderTableRow;
|
||||
|
||||
const onOpenUplifts = renderCells(row);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Manage" }));
|
||||
expect(onOpenUplifts).toHaveBeenCalledWith(row);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue