shoc-frontend-new/src/app/(protected)/workorders/index.tsx
Arthur Bassi 93c5a35b46 chore: merge origin/dev into slide-over media branch
Sync with latest dev (CompDoc/completedDate from PR #45) and resolve
conflicts while preserving slide-over detail, workOrderVersion on media
mutations, and the consolidated list page hook.
2026-08-11 16:46:32 -03:00

158 lines
6 KiB
TypeScript

import { Box } from "@mui/material";
import { PageHeader } from "@/components/ui/page-header";
import { QueryErrorPanel } from "@/components/ui/query-error-panel";
import { CompDocDialog } from "@/app/(protected)/workorders/_components/comp-doc/comp-doc-dialog";
import { WorkOrderSlideOver } from "@/app/(protected)/workorders/_components/detail/work-order-slide-over";
import { MediaUploadModal } from "@/app/(protected)/workorders/_components/media/media-upload-modal";
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 { WorkOrderCancelDialog } from "@/app/(protected)/workorders/_components/list/work-order-cancel-dialog";
import { WoTable } from "@/app/(protected)/workorders/_components/list/table/wo-table";
import { NewWoWizard } from "@/app/(protected)/workorders/_components/wizard/new-wo-wizard";
import { useWorkOrdersListPage } from "@/app/(protected)/workorders/_hooks/use-work-orders-list-page";
import { useAuthContext } from "@/providers/auth-context";
export default function WorkOrdersListPage() {
const { user } = useAuthContext();
const page = useWorkOrdersListPage();
const { filters, tableData, activeDocRow } = page;
return (
<Box className="flex h-full flex-col overflow-hidden p-2.5">
<PageHeader
surface
eyebrow="OPERATIONS"
title="Work Orders"
actions={
<WorkOrdersListHeader
search={filters.search}
onSearchChange={filters.handleSearchChange}
onOpenAdvancedFilters={() => filters.setAdvOpen(true)}
onNewWorkOrder={() => page.setWizardOpen(true)}
activeFilterCount={filters.activeFilterCount}
isFetching={tableData.isFetching && !tableData.isLoading}
/>
}
/>
<WorkOrdersFilterBar
weekMonday={filters.weekMonday}
onWeekChange={filters.setWeekMonday}
dispatcherIds={filters.dispatcherIds}
onDispatcherChange={filters.setDispatcherIds}
typeFilter={filters.typeFilter}
onTypeChange={filters.setTypeFilter}
users={page.users}
usersLoading={page.usersLoading}
currentUserId={user?.id}
filteredCount={tableData.totalCount}
scopeTotalCount={tableData.scopeTotalCount}
/>
{filters.advApplied != null && (
<WorkOrdersAdvancedFiltersBanner
applied={filters.advApplied}
totalCount={tableData.totalCount}
sites={page.locations}
users={page.users}
onClearChip={filters.clearAdvancedFilterChip}
onClearAll={filters.clearAdvancedFilters}
/>
)}
{Boolean(tableData.error) && (
<QueryErrorPanel
className="mb-2 shrink-0"
compact
message={
tableData.error instanceof Error
? tableData.error.message
: "Failed to load work orders."
}
onRetry={() => void tableData.refetch()}
/>
)}
<WoTable
tableData={tableData}
users={page.users}
sites={page.locations}
vendors={page.vendors}
pmTypes={page.pmTypes}
weekMonday={filters.weekMonday}
onWeekChange={filters.setWeekMonday}
onOpenSlideOver={page.handleOpenSlideOver}
onOpenCompDoc={page.setDocRow}
onOpenMedia={page.setMediaRow}
onClearSearch={() => filters.handleSearchChange("")}
onOpenAdvancedFilters={() => filters.setAdvOpen(true)}
onPatch={page.patchField}
/>
<NewWoWizard open={page.wizardOpen} onOpenChange={page.setWizardOpen} users={page.users} />
<WorkOrdersAdvancedSearchSheet
open={filters.advOpen}
onOpenChange={filters.setAdvOpen}
initial={filters.advInitial}
onApply={filters.applyAdvancedFilters}
onClearAll={filters.clearAdvancedFilters}
sites={page.locations}
users={page.users}
pmTypes={page.pmTypes}
vendorTechs={page.vendorTechs}
/>
<WorkOrderSlideOver
row={page.activeSlideOverRow}
editMode={page.slideOverEdit}
users={page.users}
sites={page.locations}
vendors={page.vendors}
pmTypes={page.pmTypes}
allOrders={tableData.rows}
onSave={(id, patch, options) => page.patchField(id, patch, options)}
onOpenCompletionDoc={page.setDocRow}
onCancelWO={page.setConfirmCancel}
onDuplicateFound={(existing) => page.handleOpenSlideOver(existing, false)}
saving={page.isPatchPending}
onClose={page.handleCloseSlideOver}
/>
<WorkOrderCancelDialog
row={page.confirmCancel}
isPending={page.isPatchPending}
onDialogClose={page.cancelDialogClose}
onKeepWO={() => page.setConfirmCancel(null)}
onConfirm={page.handleConfirmCancel}
/>
{page.activeMediaRow != null && (
<MediaUploadModal
row={page.activeMediaRow}
open={Boolean(page.activeMediaRow)}
onOpenChange={(open) => {
if (!open) page.setMediaRow(null);
}}
/>
)}
{activeDocRow != null && (
<CompDocDialog
row={activeDocRow}
open={Boolean(activeDocRow)}
onOpenChange={(open) => {
if (!open) page.setDocRow(null);
}}
data={page.completionDocs[String(activeDocRow.id)]}
onSave={(data, status) => page.saveCompletionDoc(activeDocRow, data, status)}
onDateCompletedChange={async (date) => {
await page.patchFieldAsync(activeDocRow.id, { completedDate: date });
}}
/>
)}
</Box>
);
}