mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
refactor(workorders): extract wizard state hook and list overlays
This commit is contained in:
parent
1ba7ce0003
commit
41dd7d0957
5 changed files with 264 additions and 167 deletions
|
|
@ -0,0 +1,33 @@
|
|||
import { MediaUploadModal } from "@/app/(protected)/workorders/_components/media/media-upload-modal";
|
||||
import { EMPTY_MEDIA, type MediaFile } from "@/domain/work-orders/types/work-order-media";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
|
||||
type WorkOrdersListMediaOverlayProps = {
|
||||
activeMediaRow: WorkOrderTableRow | null;
|
||||
onCloseMedia: () => void;
|
||||
mediaFiles: Record<string, MediaFile[]>;
|
||||
onMediaChange: (rowId: string | number, files: MediaFile[]) => void;
|
||||
};
|
||||
|
||||
export function WorkOrdersListMediaOverlay({
|
||||
activeMediaRow,
|
||||
onCloseMedia,
|
||||
mediaFiles,
|
||||
onMediaChange,
|
||||
}: WorkOrdersListMediaOverlayProps) {
|
||||
if (activeMediaRow == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MediaUploadModal
|
||||
row={activeMediaRow}
|
||||
open={Boolean(activeMediaRow)}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) onCloseMedia();
|
||||
}}
|
||||
uploads={mediaFiles[String(activeMediaRow.id)] ?? EMPTY_MEDIA}
|
||||
onChange={(files) => onMediaChange(activeMediaRow.id, files)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { useNavigate } from "react-router";
|
||||
import { NewWoWizard } from "@/app/(protected)/workorders/_components/wizard/new-wo-wizard";
|
||||
import type { WorkOrderUser } from "@/domain/work-orders/types/work-order";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
|
||||
type WorkOrdersListWizardProps = {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
users: WorkOrderUser[];
|
||||
rows: WorkOrderTableRow[];
|
||||
onSelectRow: (rowId: string | number) => void;
|
||||
};
|
||||
|
||||
export function WorkOrdersListWizard({
|
||||
open,
|
||||
onOpenChange,
|
||||
users,
|
||||
rows,
|
||||
onSelectRow,
|
||||
}: WorkOrdersListWizardProps) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<NewWoWizard
|
||||
open={open}
|
||||
onOpenChange={onOpenChange}
|
||||
users={users}
|
||||
existingRows={rows}
|
||||
onViewExistingWo={(row) => {
|
||||
onSelectRow(row.id);
|
||||
navigate(`/workorders/${row.id}`);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,36 +1,16 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Dialog } from "@mui/material";
|
||||
import { dialogBlurBackdropSlotProps } from "@/components/ui/dialog-blur-backdrop";
|
||||
import { Text } from "@/components/ui/text";
|
||||
import { DuplicateWoNumberDialog } from "@/app/(protected)/workorders/_components/list/duplicate-wo-number-dialog";
|
||||
import { useDropdownOptionsByCategory } from "@/domain/settings/dropdown-options/use-cases/use-dropdown-options-by-category";
|
||||
import { isWoWizardMockEnabled } from "@/domain/work-orders/mocks/is-wo-wizard-mock-enabled";
|
||||
import {
|
||||
getMockWoWizardLocationDetail,
|
||||
MOCK_WO_WIZARD_LOCATIONS,
|
||||
MOCK_WO_WIZARD_SERVICES,
|
||||
MOCK_WO_WIZARD_USERS,
|
||||
MOCK_WO_WIZARD_VENDORS,
|
||||
} from "@/domain/work-orders/mocks/wo-wizard-mock-data";
|
||||
import type { WorkOrderUser } from "@/domain/work-orders/types/work-order";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
import {
|
||||
EMPTY_WIZARD_DRAFT,
|
||||
WIZARD_STEPS,
|
||||
type WorkOrderWizardDraft,
|
||||
} from "@/domain/work-orders/types/work-order-wizard";
|
||||
import { useLocationDetail } from "@/domain/locations/use-cases/use-location-detail";
|
||||
import {
|
||||
useWorkOrderLocations,
|
||||
useWorkOrderVendors,
|
||||
} from "@/domain/work-orders/use-cases/use-work-order-detail";
|
||||
import { useCreateWorkOrderFromWizard } from "@/domain/work-orders/use-cases/use-create-work-order-from-wizard";
|
||||
import { findDuplicateWoNumberRow } from "@/domain/work-orders/utils/find-duplicate-wo-number-row";
|
||||
import { WIZARD_STEPS } from "@/domain/work-orders/types/work-order-wizard";
|
||||
import { WizardFooter } from "@/app/(protected)/workorders/_components/wizard/wizard-footer";
|
||||
import { WizardSidebar } from "@/app/(protected)/workorders/_components/wizard/wizard-sidebar";
|
||||
import { WizardStepLocationService } from "@/app/(protected)/workorders/_components/wizard/wizard-step-location-service";
|
||||
import { WizardStepTypeSchedule } from "@/app/(protected)/workorders/_components/wizard/wizard-step-type-schedule";
|
||||
import { WizardStepVendorTime } from "@/app/(protected)/workorders/_components/wizard/wizard-step-vendor-time";
|
||||
import { useNewWoWizardState } from "@/app/(protected)/workorders/_components/wizard/use-new-wo-wizard-state";
|
||||
|
||||
type NewWoWizardProps = {
|
||||
open: boolean;
|
||||
|
|
@ -87,98 +67,7 @@ export function NewWoWizard({
|
|||
existingRows = [],
|
||||
onViewExistingWo,
|
||||
}: NewWoWizardProps) {
|
||||
const mockFallback = isWoWizardMockEnabled();
|
||||
const [step, setStep] = useState(1);
|
||||
const [draft, setDraft] = useState<WorkOrderWizardDraft>({
|
||||
...EMPTY_WIZARD_DRAFT,
|
||||
status: "Incomplete",
|
||||
});
|
||||
const [pocAutoFilledFor, setPocAutoFilledFor] = useState("");
|
||||
const [duplicateRow, setDuplicateRow] = useState<WorkOrderTableRow | null>(null);
|
||||
|
||||
const { data: apiLocations = [] } = useWorkOrderLocations();
|
||||
const { data: apiProblems = [] } = useDropdownOptionsByCategory("Problem");
|
||||
const isMockLocation = draft.locationId.startsWith("mock-");
|
||||
const { data: apiLocationDetail } = useLocationDetail(
|
||||
isMockLocation ? undefined : draft.locationId || undefined,
|
||||
);
|
||||
const mockLocationDetail = isMockLocation
|
||||
? getMockWoWizardLocationDetail(draft.locationId)
|
||||
: undefined;
|
||||
const locationDetail = mockLocationDetail ?? apiLocationDetail;
|
||||
const { data: apiVendors = [] } = useWorkOrderVendors(
|
||||
undefined,
|
||||
isMockLocation ? undefined : locationDetail?.zipCode,
|
||||
);
|
||||
const createMutation = useCreateWorkOrderFromWizard(() => onOpenChange(false));
|
||||
|
||||
const wizardUsers = useMemo(() => {
|
||||
if (users.length > 0) {
|
||||
return users;
|
||||
}
|
||||
return mockFallback ? MOCK_WO_WIZARD_USERS : [];
|
||||
}, [mockFallback, users]);
|
||||
const locations =
|
||||
apiLocations.length > 0 ? apiLocations : mockFallback ? MOCK_WO_WIZARD_LOCATIONS : [];
|
||||
const problems =
|
||||
apiProblems.length > 0 ? apiProblems : mockFallback ? MOCK_WO_WIZARD_SERVICES : [];
|
||||
const vendors = apiVendors.length > 0 ? apiVendors : mockFallback ? MOCK_WO_WIZARD_VENDORS : [];
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setStep(1);
|
||||
setDraft({ ...EMPTY_WIZARD_DRAFT, status: "Incomplete" });
|
||||
setPocAutoFilledFor("");
|
||||
setDuplicateRow(null);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!draft.locationId || !locationDetail) {
|
||||
return;
|
||||
}
|
||||
if (pocAutoFilledFor === draft.locationId) {
|
||||
return;
|
||||
}
|
||||
setDraft((current) => ({
|
||||
...current,
|
||||
pocName: locationDetail.contact ?? current.pocName,
|
||||
pocPhone: locationDetail.phone ?? current.pocPhone,
|
||||
}));
|
||||
setPocAutoFilledFor(draft.locationId);
|
||||
}, [draft.locationId, locationDetail, pocAutoFilledFor]);
|
||||
|
||||
const setField = <K extends keyof WorkOrderWizardDraft>(
|
||||
key: K,
|
||||
value: WorkOrderWizardDraft[K],
|
||||
) => {
|
||||
setDraft((current) => ({ ...current, [key]: value }));
|
||||
};
|
||||
|
||||
const patchDraft = (patch: Partial<WorkOrderWizardDraft>) => {
|
||||
setDraft((current) => ({ ...current, ...patch }));
|
||||
if (patch.locationId !== undefined && patch.locationId !== pocAutoFilledFor) {
|
||||
setPocAutoFilledFor("");
|
||||
}
|
||||
};
|
||||
|
||||
const resolveDuplicate = (woNumber: string) => findDuplicateWoNumberRow(woNumber, existingRows);
|
||||
|
||||
const handleDuplicateFound = (woNumber: string) => {
|
||||
const duplicate = resolveDuplicate(woNumber);
|
||||
if (duplicate) {
|
||||
setDuplicateRow(duplicate);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = () => {
|
||||
const duplicate = resolveDuplicate(draft.woNumber);
|
||||
if (duplicate) {
|
||||
setDuplicateRow(duplicate);
|
||||
return;
|
||||
}
|
||||
createMutation.mutate(draft);
|
||||
};
|
||||
const wizard = useNewWoWizardState({ open, users, existingRows, onOpenChange });
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -203,63 +92,63 @@ export function NewWoWizard({
|
|||
<span className="sr-only">Guided setup for creating a new work order</span>
|
||||
|
||||
<div className="flex min-h-0 flex-1">
|
||||
<WizardSidebar step={step} draft={draft} />
|
||||
<WizardSidebar step={wizard.step} draft={wizard.draft} />
|
||||
|
||||
<div
|
||||
className="min-h-0 flex-1 overflow-y-auto"
|
||||
style={{ padding: 32, background: "var(--color-bg-surface)" }}
|
||||
>
|
||||
<WizardStepHeader step={step} />
|
||||
<WizardStepHeader step={wizard.step} />
|
||||
|
||||
{step === 1 && (
|
||||
{wizard.step === 1 && (
|
||||
<WizardStepTypeSchedule
|
||||
draft={draft}
|
||||
users={wizardUsers}
|
||||
onUpdate={setField}
|
||||
onPatch={patchDraft}
|
||||
onDuplicateWoNumber={handleDuplicateFound}
|
||||
draft={wizard.draft}
|
||||
users={wizard.wizardUsers}
|
||||
onUpdate={wizard.setField}
|
||||
onPatch={wizard.patchDraft}
|
||||
onDuplicateWoNumber={wizard.handleDuplicateFound}
|
||||
/>
|
||||
)}
|
||||
|
||||
{step === 2 && (
|
||||
{wizard.step === 2 && (
|
||||
<WizardStepLocationService
|
||||
draft={draft}
|
||||
locations={locations}
|
||||
locationDetail={locationDetail}
|
||||
services={problems.map((p) => ({ id: p.id, value: p.value }))}
|
||||
onUpdate={setField}
|
||||
onPatch={patchDraft}
|
||||
draft={wizard.draft}
|
||||
locations={wizard.locations}
|
||||
locationDetail={wizard.locationDetail}
|
||||
services={wizard.problems.map((p) => ({ id: p.id, value: p.value }))}
|
||||
onUpdate={wizard.setField}
|
||||
onPatch={wizard.patchDraft}
|
||||
/>
|
||||
)}
|
||||
|
||||
{step === 3 && (
|
||||
{wizard.step === 3 && (
|
||||
<WizardStepVendorTime
|
||||
draft={draft}
|
||||
vendors={vendors}
|
||||
onUpdate={setField}
|
||||
onPatch={patchDraft}
|
||||
draft={wizard.draft}
|
||||
vendors={wizard.vendors}
|
||||
onUpdate={wizard.setField}
|
||||
onPatch={wizard.patchDraft}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<WizardFooter
|
||||
step={step}
|
||||
draft={draft}
|
||||
step={wizard.step}
|
||||
draft={wizard.draft}
|
||||
onCancel={() => onOpenChange(false)}
|
||||
onBack={() => setStep((s) => s - 1)}
|
||||
onContinue={() => setStep((s) => s + 1)}
|
||||
onCreate={handleCreate}
|
||||
isCreating={createMutation.isPending}
|
||||
onBack={() => wizard.setStep((s) => s - 1)}
|
||||
onContinue={() => wizard.setStep((s) => s + 1)}
|
||||
onCreate={wizard.handleCreate}
|
||||
isCreating={wizard.isCreating}
|
||||
/>
|
||||
</Dialog>
|
||||
|
||||
<DuplicateWoNumberDialog
|
||||
open={duplicateRow != null}
|
||||
existing={duplicateRow}
|
||||
onDismiss={() => setDuplicateRow(null)}
|
||||
open={wizard.duplicateRow != null}
|
||||
existing={wizard.duplicateRow}
|
||||
onDismiss={() => wizard.setDuplicateRow(null)}
|
||||
onViewExisting={(row) => {
|
||||
setDuplicateRow(null);
|
||||
wizard.setDuplicateRow(null);
|
||||
onOpenChange(false);
|
||||
onViewExistingWo?.(row);
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,148 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { isWoWizardMockEnabled } from "@/domain/work-orders/mocks/is-wo-wizard-mock-enabled";
|
||||
import {
|
||||
getMockWoWizardLocationDetail,
|
||||
MOCK_WO_WIZARD_LOCATIONS,
|
||||
MOCK_WO_WIZARD_SERVICES,
|
||||
MOCK_WO_WIZARD_USERS,
|
||||
MOCK_WO_WIZARD_VENDORS,
|
||||
} from "@/domain/work-orders/mocks/wo-wizard-mock-data";
|
||||
import type { WorkOrderUser } from "@/domain/work-orders/types/work-order";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
import {
|
||||
EMPTY_WIZARD_DRAFT,
|
||||
type WorkOrderWizardDraft,
|
||||
} from "@/domain/work-orders/types/work-order-wizard";
|
||||
import { useLocationDetail } from "@/domain/locations/use-cases/use-location-detail";
|
||||
import { useDropdownOptionsByCategory } from "@/domain/settings/dropdown-options/use-cases/use-dropdown-options-by-category";
|
||||
import {
|
||||
useWorkOrderLocations,
|
||||
useWorkOrderVendors,
|
||||
} from "@/domain/work-orders/use-cases/use-work-order-detail";
|
||||
import { useCreateWorkOrderFromWizard } from "@/domain/work-orders/use-cases/use-create-work-order-from-wizard";
|
||||
import { findDuplicateWoNumberRow } from "@/domain/work-orders/utils/find-duplicate-wo-number-row";
|
||||
|
||||
type UseNewWoWizardStateArgs = {
|
||||
open: boolean;
|
||||
users: WorkOrderUser[];
|
||||
existingRows: WorkOrderTableRow[];
|
||||
onOpenChange: (open: boolean) => void;
|
||||
};
|
||||
|
||||
export function useNewWoWizardState({
|
||||
open,
|
||||
users,
|
||||
existingRows,
|
||||
onOpenChange,
|
||||
}: UseNewWoWizardStateArgs) {
|
||||
const mockFallback = isWoWizardMockEnabled();
|
||||
const [step, setStep] = useState(1);
|
||||
const [draft, setDraft] = useState<WorkOrderWizardDraft>({
|
||||
...EMPTY_WIZARD_DRAFT,
|
||||
status: "Incomplete",
|
||||
});
|
||||
const [pocAutoFilledFor, setPocAutoFilledFor] = useState("");
|
||||
const [duplicateRow, setDuplicateRow] = useState<WorkOrderTableRow | null>(null);
|
||||
|
||||
const { data: apiLocations = [] } = useWorkOrderLocations();
|
||||
const { data: apiProblems = [] } = useDropdownOptionsByCategory("Problem");
|
||||
const isMockLocation = draft.locationId.startsWith("mock-");
|
||||
const { data: apiLocationDetail } = useLocationDetail(
|
||||
isMockLocation ? undefined : draft.locationId || undefined,
|
||||
);
|
||||
const mockLocationDetail = isMockLocation
|
||||
? getMockWoWizardLocationDetail(draft.locationId)
|
||||
: undefined;
|
||||
const locationDetail = mockLocationDetail ?? apiLocationDetail;
|
||||
const { data: apiVendors = [] } = useWorkOrderVendors(
|
||||
undefined,
|
||||
isMockLocation ? undefined : locationDetail?.zipCode,
|
||||
);
|
||||
const createMutation = useCreateWorkOrderFromWizard(() => onOpenChange(false));
|
||||
|
||||
const wizardUsers = useMemo(() => {
|
||||
if (users.length > 0) {
|
||||
return users;
|
||||
}
|
||||
return mockFallback ? MOCK_WO_WIZARD_USERS : [];
|
||||
}, [mockFallback, users]);
|
||||
const locations =
|
||||
apiLocations.length > 0 ? apiLocations : mockFallback ? MOCK_WO_WIZARD_LOCATIONS : [];
|
||||
const problems =
|
||||
apiProblems.length > 0 ? apiProblems : mockFallback ? MOCK_WO_WIZARD_SERVICES : [];
|
||||
const vendors = apiVendors.length > 0 ? apiVendors : mockFallback ? MOCK_WO_WIZARD_VENDORS : [];
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setStep(1);
|
||||
setDraft({ ...EMPTY_WIZARD_DRAFT, status: "Incomplete" });
|
||||
setPocAutoFilledFor("");
|
||||
setDuplicateRow(null);
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!draft.locationId || !locationDetail) {
|
||||
return;
|
||||
}
|
||||
if (pocAutoFilledFor === draft.locationId) {
|
||||
return;
|
||||
}
|
||||
setDraft((current) => ({
|
||||
...current,
|
||||
pocName: locationDetail.contact ?? current.pocName,
|
||||
pocPhone: locationDetail.phone ?? current.pocPhone,
|
||||
}));
|
||||
setPocAutoFilledFor(draft.locationId);
|
||||
}, [draft.locationId, locationDetail, pocAutoFilledFor]);
|
||||
|
||||
const setField = <K extends keyof WorkOrderWizardDraft>(
|
||||
key: K,
|
||||
value: WorkOrderWizardDraft[K],
|
||||
) => {
|
||||
setDraft((current) => ({ ...current, [key]: value }));
|
||||
};
|
||||
|
||||
const patchDraft = (patch: Partial<WorkOrderWizardDraft>) => {
|
||||
setDraft((current) => ({ ...current, ...patch }));
|
||||
if (patch.locationId !== undefined && patch.locationId !== pocAutoFilledFor) {
|
||||
setPocAutoFilledFor("");
|
||||
}
|
||||
};
|
||||
|
||||
const resolveDuplicate = (woNumber: string) => findDuplicateWoNumberRow(woNumber, existingRows);
|
||||
|
||||
const handleDuplicateFound = (woNumber: string) => {
|
||||
const duplicate = resolveDuplicate(woNumber);
|
||||
if (duplicate) {
|
||||
setDuplicateRow(duplicate);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreate = () => {
|
||||
const duplicate = resolveDuplicate(draft.woNumber);
|
||||
if (duplicate) {
|
||||
setDuplicateRow(duplicate);
|
||||
return;
|
||||
}
|
||||
createMutation.mutate(draft);
|
||||
};
|
||||
|
||||
return {
|
||||
step,
|
||||
setStep,
|
||||
draft,
|
||||
duplicateRow,
|
||||
setDuplicateRow,
|
||||
wizardUsers,
|
||||
locations,
|
||||
problems,
|
||||
vendors,
|
||||
locationDetail,
|
||||
setField,
|
||||
patchDraft,
|
||||
handleDuplicateFound,
|
||||
handleCreate,
|
||||
isCreating: createMutation.isPending,
|
||||
};
|
||||
}
|
||||
|
|
@ -3,13 +3,13 @@ import { Box } from "@mui/material";
|
|||
import { useNavigate } from "react-router";
|
||||
import { PageHeader } from "@/components/ui/page-header";
|
||||
import { QueryErrorPanel } from "@/components/ui/query-error-panel";
|
||||
import { MediaUploadModal } from "@/app/(protected)/workorders/_components/media/media-upload-modal";
|
||||
import { WorkOrdersListMediaOverlay } from "@/app/(protected)/workorders/_components/list/work-orders-list-media-overlay";
|
||||
import { WorkOrdersListWizard } from "@/app/(protected)/workorders/_components/list/work-orders-list-wizard";
|
||||
import { WorkOrdersAdvancedSearchSheet } from "@/app/(protected)/workorders/_components/list/advanced-search/work-orders-advanced-search-sheet";
|
||||
import { WorkOrdersAdvancedFiltersBanner } from "@/app/(protected)/workorders/_components/list/work-orders-advanced-filters-banner";
|
||||
import { WorkOrdersFilterBar } from "@/app/(protected)/workorders/_components/list/filter-bar/work-orders-filter-bar";
|
||||
import { WorkOrdersListHeader } from "@/app/(protected)/workorders/_components/list/work-orders-list-header";
|
||||
import { WoTable } from "@/app/(protected)/workorders/_components/list/table/wo-table";
|
||||
import { NewWoWizard } from "@/app/(protected)/workorders/_components/wizard/new-wo-wizard";
|
||||
import { useWorkOrdersListFilters } from "@/app/(protected)/workorders/_hooks/use-work-orders-list-filters";
|
||||
import { useWorkOrdersTableData } from "@/app/(protected)/workorders/_hooks/use-work-orders-table-data";
|
||||
import { useDropdownOptionsByCategory } from "@/domain/settings/dropdown-options/use-cases/use-dropdown-options-by-category";
|
||||
|
|
@ -18,7 +18,7 @@ import {
|
|||
useWorkOrderVendors,
|
||||
} from "@/domain/work-orders/use-cases/use-work-order-detail";
|
||||
import { useWorkOrderUsers } from "@/domain/work-orders/use-cases/use-work-orders-list";
|
||||
import { EMPTY_MEDIA, type MediaFile } from "@/domain/work-orders/types/work-order-media";
|
||||
import type { MediaFile } from "@/domain/work-orders/types/work-order-media";
|
||||
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
|
||||
import { useWorkOrderTableMutations } from "@/domain/work-orders/use-cases/use-work-order-table-mutations";
|
||||
import { useAuthContext } from "@/providers/auth-context";
|
||||
|
|
@ -146,31 +146,23 @@ export default function WorkOrdersListPage() {
|
|||
vendorTechs={vendorTechs}
|
||||
/>
|
||||
|
||||
<NewWoWizard
|
||||
<WorkOrdersListWizard
|
||||
open={wizardOpen}
|
||||
onOpenChange={setWizardOpen}
|
||||
users={users}
|
||||
existingRows={tableData.rows}
|
||||
onViewExistingWo={(row) => {
|
||||
tableData.setSelectedId(row.id);
|
||||
navigate(`/workorders/${row.id}`);
|
||||
}}
|
||||
rows={tableData.rows}
|
||||
onSelectRow={tableData.setSelectedId}
|
||||
/>
|
||||
|
||||
{activeMediaRow != null && (
|
||||
<MediaUploadModal
|
||||
row={activeMediaRow}
|
||||
open={!!activeMediaRow}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) setMediaRow(null);
|
||||
}}
|
||||
uploads={mediaFiles[String(activeMediaRow.id)] ?? EMPTY_MEDIA}
|
||||
onChange={(files) => {
|
||||
setMediaFiles((prev) => ({ ...prev, [String(activeMediaRow.id)]: files }));
|
||||
patchField(activeMediaRow.id, { mediaCount: files.length });
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<WorkOrdersListMediaOverlay
|
||||
activeMediaRow={activeMediaRow}
|
||||
onCloseMedia={() => setMediaRow(null)}
|
||||
mediaFiles={mediaFiles}
|
||||
onMediaChange={(rowId, files) => {
|
||||
setMediaFiles((prev) => ({ ...prev, [String(rowId)]: files }));
|
||||
patchField(rowId, { mediaCount: files.length });
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue