mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +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 = {
|
type UpliftCellProps = {
|
||||||
summary: UpliftSummary;
|
summary: UpliftSummary;
|
||||||
onOpen?: () => void;
|
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);
|
const label = getUpliftCellLabel(summary);
|
||||||
|
|
||||||
if (!onOpen) {
|
if (!onOpen) {
|
||||||
|
|
@ -30,7 +32,7 @@ export function UpliftCell({ summary, onOpen }: UpliftCellProps) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onOpen();
|
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"
|
className="flex w-full items-center justify-start transition-opacity hover:opacity-80"
|
||||||
>
|
>
|
||||||
{label && pillStyle ? (
|
{label && pillStyle ? (
|
||||||
|
|
@ -40,6 +42,8 @@ export function UpliftCell({ summary, onOpen }: UpliftCellProps) {
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
|
) : readOnly ? (
|
||||||
|
<span className="text-[11px] text-[var(--color-text-muted)]">—</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-[11px] font-semibold text-[var(--color-primary)]">Manage</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 { UpliftCell } from "./cells/uplift-cell";
|
||||||
import { VendorCell } from "./cells/vendor-cell";
|
import { VendorCell } from "./cells/vendor-cell";
|
||||||
import { EMPTY_UPLIFT_SUMMARY } from "@/domain/work-orders/types/work-order-uplift";
|
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 { applyVendorTableSave } from "@/domain/work-orders/utils/work-order-feedback-toasts";
|
||||||
import { effectiveCompany } from "@/domain/work-orders/utils/effective-completion-snapshot";
|
import { effectiveCompany } from "@/domain/work-orders/utils/effective-completion-snapshot";
|
||||||
import type { WoTableRowHandlers } from "./wo-table-row";
|
import type { WoTableRowHandlers } from "./wo-table-row";
|
||||||
|
|
@ -132,12 +132,8 @@ export function WoTableRowServiceCells({
|
||||||
<td style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
<td style={{ padding: "0 14px" }} onClick={(e) => e.stopPropagation()}>
|
||||||
<UpliftCell
|
<UpliftCell
|
||||||
summary={row.upliftSummary ?? EMPTY_UPLIFT_SUMMARY}
|
summary={row.upliftSummary ?? EMPTY_UPLIFT_SUMMARY}
|
||||||
onOpen={
|
onOpen={handlers.onOpenUplifts ? () => handlers.onOpenUplifts!(row) : undefined}
|
||||||
canOpenUpliftsDialog(row.upliftSummary ?? EMPTY_UPLIFT_SUMMARY, row.status) &&
|
readOnly={isWorkOrderUpliftsReadOnly(row.status)}
|
||||||
handlers.onOpenUplifts
|
|
||||||
? () => handlers.onOpenUplifts!(row)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -74,16 +74,6 @@ export function isWorkOrderUpliftsReadOnly(status: WorkOrderTableRow["status"]):
|
||||||
return status === "Completed" || status === "Canceled";
|
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(
|
export function canRevokeWorkOrderUplift(
|
||||||
uplift: Pick<WorkOrderUplift, "status" | "requestedById">,
|
uplift: Pick<WorkOrderUplift, "status" | "requestedById">,
|
||||||
currentUserId: string | number | null | undefined,
|
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