diff --git a/e2e/work-orders/advanced-filters.spec.ts b/e2e/work-orders/advanced-filters.spec.ts index b882415d..ef4b55f1 100644 --- a/e2e/work-orders/advanced-filters.spec.ts +++ b/e2e/work-orders/advanced-filters.spec.ts @@ -99,6 +99,25 @@ test.describe("Work Orders advanced filters", () => { await expect(page.getByText("No work orders match these filters")).toBeVisible(); }); + test("sends avetaOnly on board/search and shows empty copy", async ({ page }) => { + const searchUrls: string[] = []; + await signInAndOpenWorkOrders(page); + await mockWorkOrderApis(page, searchUrls); + + await page.goto("/workorders"); + await expect(page.getByRole("heading", { name: "Work Orders" })).toBeVisible({ + timeout: 15_000, + }); + + const sheet = await applyAdvancedFilters(page); + await sheet.getByRole("button", { name: /Aveta Compliance/i }).click(); + await sheet.getByRole("checkbox", { name: /Aveta required only/i }).click(); + await sheet.getByRole("button", { name: /apply filters/i }).click(); + + await expect.poll(() => searchUrls.some((url) => url.includes("avetaOnly=true"))).toBe(true); + await expect(page.getByText("No work orders match these filters")).toBeVisible(); + }); + test("sends combined advanced-filter facets on the same board/search request", async ({ page, }) => { diff --git a/src/app/(protected)/workorders/_components/detail/slide-over-header.tsx b/src/app/(protected)/workorders/_components/detail/slide-over-header.tsx index 0302625e..6407e109 100644 --- a/src/app/(protected)/workorders/_components/detail/slide-over-header.tsx +++ b/src/app/(protected)/workorders/_components/detail/slide-over-header.tsx @@ -1,5 +1,7 @@ import { CircularProgress } from "@mui/material"; import { X } from "lucide-react"; +import { AvetaBadge } from "@/app/(protected)/workorders/_components/list/table/cells/aveta-badge"; +import { RescheduleCounterPill } from "@/app/(protected)/workorders/_components/list/table/cells/wo-counter-pills"; import { WoTableStatusLabel } from "@/app/(protected)/workorders/_components/list/table/cells/wo-table-status-label"; import { WoTableTypeLabel } from "@/app/(protected)/workorders/_components/list/table/cells/wo-table-type-label"; import { Text } from "@/components/ui/text"; @@ -34,6 +36,8 @@ export function SlideOverHeader({ > #{row.woNumber || "—"} + + {Boolean(row.avetaRequired) && } {isCancelled && ( void; onRemove: (id: string) => void; }; +function ExtraDocRow({ + file, + index, + uploads, + avetaRequired, + isReadOnly, + pending, + onRemove, +}: { + file: MediaFile; + index: number; + uploads: MediaFile[]; + avetaRequired: boolean; + isReadOnly: boolean; + pending: boolean; + onRemove: (id: string) => void; +}) { + const category = resolveExtraDocCategory(file, index, avetaRequired, uploads); + const isAveta = category === "Aveta"; + const ItemIcon = isAveta ? ShieldCheck : FILETYPE_ICON[file.fileType]; + const showDelete = !isReadOnly && canDeleteWorkOrderMedia(file); + + return ( +
+ + + {file.name} + + {isAveta && ( + Aveta + )} + {showDelete && ( + + )} +
+ ); +} + export function SlideOverExtrasTab({ uploads, isReadOnly, pending = false, + avetaRequired = false, onUpload, onRemove, }: SlideOverExtrasTabProps) { @@ -70,6 +131,15 @@ export function SlideOverExtrasTab({ Extra Documents + {Boolean(avetaRequired) && ( + + + Aveta + + )} {!isReadOnly && ( @@ -122,40 +192,18 @@ export function SlideOverExtrasTab({ ) : (
- {uploads.map((file) => { - const ItemIcon = FILETYPE_ICON[file.fileType]; - const showDelete = !isReadOnly && canDeleteWorkOrderMedia(file); - return ( -
- - - {file.name} - - {showDelete && ( - - )} -
- ); - })} + {uploads.map((file, index) => ( + + ))}
)} diff --git a/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx b/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx index 46443207..ea2aafc1 100644 --- a/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx +++ b/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-display-view.tsx @@ -2,6 +2,7 @@ import { SiteCell } from "@/app/(protected)/workorders/_components/list/table/ce import { PMTypeCell } from "@/app/(protected)/workorders/_components/list/table/cells/pm-type-cell"; import { VendorCell } from "@/app/(protected)/workorders/_components/list/table/cells/vendor-cell"; import { SlideOverInfoRow } from "@/app/(protected)/workorders/_components/detail/slide-over-info-row"; +import { AvetaBadge } from "@/app/(protected)/workorders/_components/list/table/cells/aveta-badge"; import { PmTypeIcon } from "@/app/(protected)/workorders/_components/list/table/pm-type-icons"; import { WoTableTypeLabel } from "@/app/(protected)/workorders/_components/list/table/cells/wo-table-type-label"; import type { @@ -100,6 +101,7 @@ export function SlideOverInfoTabDisplayView({ pmTypes={pmTypes} serviceNotes={source.serviceNotes} extraServices={source.extraServices} + avetaRequired={source.avetaRequired} woNumber={source.woNumber} viewOnly onSave={() => undefined} @@ -108,6 +110,7 @@ export function SlideOverInfoTabDisplayView({ {source.pm} + {Boolean(source.avetaRequired) && } ) : ( — diff --git a/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-edit-view.tsx b/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-edit-view.tsx index 6cbd8006..dbb11c52 100644 --- a/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-edit-view.tsx +++ b/src/app/(protected)/workorders/_components/detail/tabs/slide-over-info-tab-edit-view.tsx @@ -1,6 +1,7 @@ import { AssignedToCell } from "@/app/(protected)/workorders/_components/list/table/cells/assigned-to-cell"; import { ApptTimeCell } from "@/app/(protected)/workorders/_components/list/table/cells/appt-time-cell"; import { DateCell } from "@/app/(protected)/workorders/_components/list/table/cells/date-cell"; +import { DueDateCell } from "@/app/(protected)/workorders/_components/list/table/cells/due-date-cell"; import { EditableWONumberCell } from "@/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell"; import { PMTypeCell } from "@/app/(protected)/workorders/_components/list/table/cells/pm-type-cell"; import { SiteCell } from "@/app/(protected)/workorders/_components/list/table/cells/site-cell"; @@ -48,6 +49,7 @@ export function SlideOverInfoTabEditView({ value={draft.woNumber} rescheduleCount={draft.rescheduleCount} carriedOver={draft.carriedOver} + originalDate={draft.originalDate} currentId={draft.id} allOrders={allOrders} onSave={(woNumber) => onDraftChange({ woNumber })} @@ -113,7 +115,11 @@ export function SlideOverInfoTabEditView({ /> - onDraftChange({ dueDate })} /> + onDraftChange({ dueDate })} + /> onDraftChange({ pm })} onSaveDetails={(details) => onDraftChange({ + pm: details.pm, serviceNotes: details.serviceNotes, extraServices: details.extraServices, + avetaRequired: details.avetaRequired, }) } /> diff --git a/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts b/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts index bd0fab4b..b4990b44 100644 --- a/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts +++ b/src/app/(protected)/workorders/_components/detail/use-slide-over-media-state.ts @@ -65,6 +65,7 @@ export function useSlideOverMediaState({ setMediaBatchPending(true); try { for (const file of files) { + // Board purpose is Extra only; Aveta is a UI overlay when avetaRequired. await uploadMediaMutation.mutateAsync({ file, category: "Extra" }); } } finally { diff --git a/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx b/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx index 222ed0d6..04a68747 100644 --- a/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx +++ b/src/app/(protected)/workorders/_components/detail/work-order-slide-over-tabs.tsx @@ -146,6 +146,7 @@ export function WorkOrderSlideOverTabs({ > { diff --git a/src/app/(protected)/workorders/_components/list/advanced-search/adv-filter-sections.tsx b/src/app/(protected)/workorders/_components/list/advanced-search/adv-filter-sections.tsx index b21120b7..812b98b6 100644 --- a/src/app/(protected)/workorders/_components/list/advanced-search/adv-filter-sections.tsx +++ b/src/app/(protected)/workorders/_components/list/advanced-search/adv-filter-sections.tsx @@ -13,7 +13,11 @@ import { import { AdvDocPill, AdvStatusPill } from "./adv-filter-pill"; import { AdvDateRangeSection } from "./adv-date-range-section"; import { AdvMultiSelect } from "./adv-multi-select"; -import { AdvFlagInternalUpliftSections, AdvIndicatorsSection } from "./adv-parity-filter-sections"; +import { + AdvAvetaSection, + AdvFlagInternalUpliftSections, + AdvIndicatorsSection, +} from "./adv-parity-filter-sections"; import { AdvSection } from "./adv-section"; import { AdvSeverityList } from "./adv-severity-list"; import { AdvTypeGrid } from "./adv-type-grid"; @@ -127,6 +131,8 @@ export function AdvancedSearchFilterSections({ + + ({ value: pmType, label: pmType }))} diff --git a/src/app/(protected)/workorders/_components/list/advanced-search/adv-parity-filter-sections.tsx b/src/app/(protected)/workorders/_components/list/advanced-search/adv-parity-filter-sections.tsx index dc2f1a8e..3bb9ecbd 100644 --- a/src/app/(protected)/workorders/_components/list/advanced-search/adv-parity-filter-sections.tsx +++ b/src/app/(protected)/workorders/_components/list/advanced-search/adv-parity-filter-sections.tsx @@ -1,5 +1,14 @@ import type { Dispatch, ReactNode, SetStateAction } from "react"; -import { ArrowRight, Check, DollarSign, Flag, Hash, Plus, RefreshCw } from "lucide-react"; +import { + ArrowRight, + Check, + DollarSign, + Flag, + Hash, + Plus, + RefreshCw, + ShieldCheck, +} from "lucide-react"; import { Checkbox } from "@mui/material"; import { AdvDocPill } from "./adv-filter-pill"; import { AdvMultiSelect } from "./adv-multi-select"; @@ -115,6 +124,26 @@ export function AdvIndicatorsSection({ draft, setDraft }: DraftProps) { ); } +export function AdvAvetaSection({ draft, setDraft }: DraftProps) { + return ( + + + + ); +} + export function AdvFlagInternalUpliftSections({ draft, setDraft, diff --git a/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts b/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts index 68605ce8..5f911bd8 100644 --- a/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts +++ b/src/app/(protected)/workorders/_components/list/table/build-inline-draft-create-input.ts @@ -28,6 +28,7 @@ export function buildInlineDraftCreateInput( dueDate: draft.dueDate, pm: draft.pm, extraServices: draft.extraServices ?? [], + avetaRequired: Boolean(draft.avetaRequired), pmNote: draft.serviceNotes ?? "", vendorId: draft.vendorId || "", vendorName: draft.company, diff --git a/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx b/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx new file mode 100644 index 00000000..0f67b21c --- /dev/null +++ b/src/app/(protected)/workorders/_components/list/table/cells/aveta-badge.tsx @@ -0,0 +1,17 @@ +import { ShieldCheck } from "lucide-react"; +import { Tooltip } from "@mui/material"; + +type AvetaBadgeProps = { + size?: number; +}; + +/** Per-WO Aveta shield — never a site-level flag. Color is paired with the icon. */ +export function AvetaBadge({ size = 11 }: AvetaBadgeProps) { + return ( + + + + + + ); +} diff --git a/src/app/(protected)/workorders/_components/list/table/cells/aveta-checkbox.tsx b/src/app/(protected)/workorders/_components/list/table/cells/aveta-checkbox.tsx new file mode 100644 index 00000000..6ebd6daa --- /dev/null +++ b/src/app/(protected)/workorders/_components/list/table/cells/aveta-checkbox.tsx @@ -0,0 +1,28 @@ +type AvetaCheckboxProps = { + checked: boolean; + onChange: (value: boolean) => void; + disabled?: boolean; +}; + +export function AvetaCheckbox({ checked, onChange, disabled = false }: AvetaCheckboxProps) { + return ( + + ); +} diff --git a/src/app/(protected)/workorders/_components/list/table/cells/due-date-cell.tsx b/src/app/(protected)/workorders/_components/list/table/cells/due-date-cell.tsx index d6cae8fb..c212b795 100644 --- a/src/app/(protected)/workorders/_components/list/table/cells/due-date-cell.tsx +++ b/src/app/(protected)/workorders/_components/list/table/cells/due-date-cell.tsx @@ -43,6 +43,7 @@ export function DueDateCell({ type, value, q, highlight, onSave }: DueDateCellPr } : undefined } + aria-label="Due Date" aria-haspopup="dialog" > diff --git a/src/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell.tsx b/src/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell.tsx index 9278fff1..b71f9c4f 100644 --- a/src/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell.tsx +++ b/src/app/(protected)/workorders/_components/list/table/cells/editable-wo-number-cell.tsx @@ -5,12 +5,14 @@ import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-ta import { findDuplicateWoNumberRow } from "@/domain/work-orders/utils/find-duplicate-wo-number-row"; import { EditableWONumberInput } from "./editable-wo-number-input"; import { HighlightText } from "./highlight-text"; +import { AddOnPill, CarriedOverCounterPill, RescheduleCounterPill } from "./wo-counter-pills"; type EditableWONumberCellProps = { value: string; rescheduleCount: number; carriedOver?: number; isAddOn?: boolean; + originalDate?: string; q?: string; currentId: string | number; allOrders: WorkOrderTableRow[]; @@ -19,42 +21,6 @@ type EditableWONumberCellProps = { locked?: boolean; }; -function CounterPill({ label, count }: { label: string; count: number }) { - if (count < 2) return null; - return ( - - {count} - - ); -} - -function AddOnPill({ when }: { when: boolean }) { - if (!when) { - return null; - } - - return ( - - Add-On - - ); -} - async function resolveDuplicateWoNumber( draft: string, allOrders: WorkOrderTableRow[], @@ -70,6 +36,7 @@ export function EditableWONumberCell({ rescheduleCount, carriedOver = 0, isAddOn = false, + originalDate, q, currentId, allOrders, @@ -150,8 +117,8 @@ export function EditableWONumberCell({ {value ? : "-"} - - + + ); } @@ -187,8 +154,8 @@ export function EditableWONumberCell({
)} - - + + ); } diff --git a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx index bec126e3..5da468d2 100644 --- a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx +++ b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-cell.tsx @@ -6,6 +6,7 @@ import { import { HighlightText } from "@/app/(protected)/workorders/_components/list/table/cells/highlight-text"; import { HoverChevron } from "@/app/(protected)/workorders/_components/list/table/cells/hover-chevron"; import { PmTypeIcon } from "@/app/(protected)/workorders/_components/list/table/pm-type-icons"; +import { AvetaBadge } from "@/app/(protected)/workorders/_components/list/table/cells/aveta-badge"; import { PmTypeDetailsTrigger } from "@/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger"; import { PmTypePickerPopover } from "@/app/(protected)/workorders/_components/list/table/cells/pm-type-picker-popover"; import { @@ -20,6 +21,7 @@ type PMTypeCellProps = { onSave: (v: string) => void; serviceNotes?: string; extraServices?: string[]; + avetaRequired?: boolean; woNumber?: string; onSaveDetails?: (details: ServiceNotesDetails) => void; viewOnly?: boolean; @@ -32,6 +34,7 @@ export function PMTypeCell({ onSave, serviceNotes = "", extraServices = [], + avetaRequired = false, woNumber, onSaveDetails, viewOnly = false, @@ -45,7 +48,7 @@ export function PMTypeCell({ : pmTypes; const extras = extraServices ?? []; - const hasDetails = hasServiceNotesDetails(serviceNotes, extras); + const hasDetails = hasServiceNotesDetails(serviceNotes, extras, avetaRequired); const notePreview = serviceNotes?.trim() ? truncateServiceNotesPreview(serviceNotes) : ""; const closePopover = () => { @@ -61,6 +64,7 @@ export function PMTypeCell({ pm={value} extraServices={extras} serviceNotes={serviceNotes ?? ""} + avetaRequired={avetaRequired} woNumber={woNumber} pmTypes={pmTypes} viewOnly={viewOnly} @@ -95,6 +99,7 @@ export function PMTypeCell({ ) : ( — )} + {Boolean(avetaRequired) && } {modal} @@ -109,6 +114,7 @@ export function PMTypeCell({ q={q} notePreview={notePreview} extrasCount={extras.length} + avetaRequired={avetaRequired} onOpenDetails={() => setModalOpen(true)} /> {modal} diff --git a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx index 4595a6b9..20b7708d 100644 --- a/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx +++ b/src/app/(protected)/workorders/_components/list/table/cells/pm-type-details-trigger.tsx @@ -1,3 +1,4 @@ +import { AvetaBadge } from "@/app/(protected)/workorders/_components/list/table/cells/aveta-badge"; import { HighlightText } from "@/app/(protected)/workorders/_components/list/table/cells/highlight-text"; import { PmTypeIcon } from "@/app/(protected)/workorders/_components/list/table/pm-type-icons"; @@ -6,6 +7,7 @@ type PmTypeDetailsTriggerProps = { q?: string; notePreview: string; extrasCount: number; + avetaRequired?: boolean; onOpenDetails: () => void; }; @@ -14,6 +16,7 @@ export function PmTypeDetailsTrigger({ q, notePreview, extrasCount, + avetaRequired = false, onOpenDetails, }: PmTypeDetailsTriggerProps) { return ( @@ -41,6 +44,7 @@ export function PmTypeDetailsTrigger({ > {value ? : "Select …"} + {Boolean(avetaRequired) && } {notePreview ? ( ([]); const [note, setNote] = useState(""); + const [aveta, setAveta] = useState(false); const [search, setSearch] = useState(""); useEffect(() => { @@ -44,8 +48,9 @@ export function ServiceNotesDialog({ } setSel([pm, ...(extraServices ?? [])].filter((p, i, a) => !!p && a.indexOf(p) === i)); setNote(serviceNotes ?? ""); + setAveta(Boolean(avetaRequired)); setSearch(""); - }, [open, pm, extraServices, serviceNotes]); + }, [open, pm, extraServices, serviceNotes, avetaRequired]); const toggle = (value: string) => { setSel((cur) => (cur.includes(value) ? cur.filter((x) => x !== value) : [...cur, value])); @@ -87,6 +92,8 @@ export function ServiceNotesDialog({ setNote={setNote} search={search} setSearch={setSearch} + avetaRequired={aveta} + onAvetaRequiredChange={setAveta} />
@@ -116,6 +123,7 @@ export function ServiceNotesDialog({ pm: sel[0] ?? "", extraServices: sel.slice(1), serviceNotes: note, + avetaRequired: aveta, }); onOpenChange(false); }} diff --git a/src/app/(protected)/workorders/_components/list/table/cells/wo-counter-pills.tsx b/src/app/(protected)/workorders/_components/list/table/cells/wo-counter-pills.tsx new file mode 100644 index 00000000..3dad9c2d --- /dev/null +++ b/src/app/(protected)/workorders/_components/list/table/cells/wo-counter-pills.tsx @@ -0,0 +1,79 @@ +import { RefreshCw } from "lucide-react"; +import { Tooltip } from "@mui/material"; +import { formatRescheduleHover } from "@/domain/work-orders/utils/reschedule-indicator"; + +const RESCHEDULE_PILL_STYLE = { + background: "#f5f3ff", + color: "#7c3aed", + border: "1px solid #ddd6fe", +} as const; + +const MUTED_PILL_STYLE = { + background: "var(--color-bg-muted)", + color: "var(--color-text-secondary)", + border: "1px solid var(--color-border)", +} as const; + +const ADDON_PILL_STYLE = { + background: "var(--type-addon-bg)", + color: "var(--type-addon-text)", +} as const; + +export function RescheduleCounterPill({ + count, + originalDate, +}: { + count: number; + originalDate?: string; +}) { + if (count < 2) { + return null; + } + + const hover = formatRescheduleHover(count, originalDate); + + return ( + + + + {count} + + + ); +} + +export function CarriedOverCounterPill({ count }: { count: number }) { + if (count < 2) { + return null; + } + + return ( + + {count} + + ); +} + +export function AddOnPill({ when }: { when: boolean }) { + if (!when) { + return null; + } + + return ( + + Add-On + + ); +} diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx index 11ecf728..8f6482ea 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx +++ b/src/app/(protected)/workorders/_components/list/table/wo-table-inline-row-cells.tsx @@ -178,6 +178,7 @@ export function WoTableInlineRowCells({ pmTypes={pmTypes} serviceNotes={draft.serviceNotes} extraServices={draft.extraServices} + avetaRequired={draft.avetaRequired} woNumber={draft.woNumber} onSave={(pm) => onPatch({ pm })} onSaveDetails={(d) => @@ -185,6 +186,7 @@ export function WoTableInlineRowCells({ pm: d.pm, extraServices: d.extraServices, serviceNotes: d.serviceNotes, + avetaRequired: d.avetaRequired, }) } /> diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-row-cells.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table-row-cells.tsx index 3e64f0cc..bb904aaa 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table-row-cells.tsx +++ b/src/app/(protected)/workorders/_components/list/table/wo-table-row-cells.tsx @@ -81,6 +81,7 @@ export function WoTableRowCells({ rescheduleCount={row.rescheduleCount} carriedOver={row.carriedOver} isAddOn={row.isAddOn} + originalDate={row.originalDate} q={search} currentId={row.id} allOrders={allRows} diff --git a/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx b/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx index 3d3e3fc6..1c6ac5ae 100644 --- a/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx +++ b/src/app/(protected)/workorders/_components/list/table/wo-table-row-service-cells.tsx @@ -49,6 +49,7 @@ export function WoTableRowServiceCells({ q={search} serviceNotes={row.serviceNotes} extraServices={row.extraServices} + avetaRequired={row.avetaRequired} woNumber={row.woNumber} viewOnly={viewOnly} onSave={(pm) => onPatchRow({ pm })} @@ -57,6 +58,7 @@ export function WoTableRowServiceCells({ pm: d.pm, extraServices: d.extraServices, serviceNotes: d.serviceNotes, + avetaRequired: d.avetaRequired, }) } /> diff --git a/src/app/(protected)/workorders/_components/wizard/wizard-service-notes-fields.tsx b/src/app/(protected)/workorders/_components/wizard/wizard-service-notes-fields.tsx index 505a2f7c..1f0dafc2 100644 --- a/src/app/(protected)/workorders/_components/wizard/wizard-service-notes-fields.tsx +++ b/src/app/(protected)/workorders/_components/wizard/wizard-service-notes-fields.tsx @@ -1,6 +1,7 @@ import type { ReactNode } from "react"; import { Check } from "lucide-react"; import { getPmTypeIcon } from "@/app/(protected)/workorders/_components/list/table/pm-type-icons"; +import { AvetaCheckbox } from "@/app/(protected)/workorders/_components/list/table/cells/aveta-checkbox"; import { DLG_INPUT_CLS, DLG_INPUT_STYLE, @@ -14,6 +15,8 @@ type WizardServiceNotesFieldsProps = { setNote: (v: string) => void; search: string; setSearch: (v: string) => void; + avetaRequired?: boolean; + onAvetaRequiredChange?: (value: boolean) => void; }; function SvcSectionLabel({ children }: { children: ReactNode }) { @@ -43,6 +46,8 @@ export function WizardServiceNotesFields({ setNote, search, setSearch, + avetaRequired = false, + onAvetaRequiredChange, }: WizardServiceNotesFieldsProps) { const filtered = search ? services.filter((s) => s.value.toLowerCase().includes(search.toLowerCase())) @@ -124,6 +129,11 @@ export function WizardServiceNotesFields({ )}
+ {onAvetaRequiredChange != null && ( +
+ +
+ )}
Notes / Issue Detail