fix(work-orders): extract hooks to satisfy max-lines governance gate

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Arthur Bassi 2026-08-11 11:14:08 -03:00
parent c6c11b9f04
commit 647c7a7b3d
4 changed files with 181 additions and 108 deletions

View file

@ -0,0 +1,58 @@
import { useState } from "react";
import { toast } from "react-toastify";
import type { LocationOption, WorkOrderUser } from "@/domain/work-orders/types/work-order";
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
import { workOrdersApi } from "@/domain/work-orders/api/work-orders-api";
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 type { ReturnTypeOfUseWorkOrdersTableData } from "./wo-table-types";
import { buildInlineDraftCreateInput } from "./build-inline-draft-create-input";
type UseWoTableInlineCreateArgs = {
tableData: ReturnTypeOfUseWorkOrdersTableData;
users: WorkOrderUser[];
sites: LocationOption[];
onDuplicateFound: (row: WorkOrderTableRow) => void;
};
export function useWoTableInlineCreate({
tableData,
users,
sites,
onDuplicateFound,
}: UseWoTableInlineCreateArgs) {
const [isCheckingInlineDuplicate, setIsCheckingInlineDuplicate] = useState(false);
const createMutation = useCreateWorkOrderFromWizard(() => {
tableData.cancelDraft();
});
const handleInlineSave = () => {
void (async () => {
const draftSnapshot = tableData.draft;
const woNumber = draftSnapshot.woNumber.trim();
if (woNumber) {
setIsCheckingInlineDuplicate(true);
try {
const duplicate =
findDuplicateWoNumberRow(woNumber, tableData.rows, "draft") ??
(await workOrdersApi.findByWoNumber(woNumber));
if (duplicate && String(duplicate.id) !== "draft") {
onDuplicateFound(duplicate);
return;
}
} catch {
toast.error("Unable to verify the work order number. Please try again.");
return;
} finally {
setIsCheckingInlineDuplicate(false);
}
}
createMutation.mutate(buildInlineDraftCreateInput(tableData.draft, users, sites));
})();
};
return {
handleInlineSave,
saving: createMutation.isPending || isCheckingInlineDuplicate,
};
}

View file

@ -1,5 +1,4 @@
import { useMemo, useState } from "react";
import { toast } from "react-toastify";
import { useLocationSites } from "@/domain/locations/use-cases/use-location-sites";
import type {
LocationOption,
@ -10,14 +9,11 @@ import type {
WorkOrderTablePatch,
WorkOrderTableRow,
} from "@/domain/work-orders/types/work-order-table-row";
import { workOrdersApi } from "@/domain/work-orders/api/work-orders-api";
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 { DuplicateWoNumberDialog } from "@/app/(protected)/workorders/_components/list/duplicate-wo-number-dialog";
import { WoTableSkeleton } from "@/app/(protected)/workorders/_components/loading/wo-table-skeleton";
import type { ReturnTypeOfUseWorkOrdersTableData } from "./wo-table-types";
import { buildInlineDraftCreateInput } from "./build-inline-draft-create-input";
import { buildSitePlaceLookups, resolveSitePlace } from "./site-place-lookup";
import { useWoTableInlineCreate } from "./use-wo-table-inline-create";
import { useWoTableRowHandlers } from "./use-wo-table-row-handlers";
import { WoTableBody } from "./wo-table-body";
import { WoTableHead } from "./wo-table-head";
@ -60,11 +56,13 @@ export function WoTable({
}: WoTableProps) {
const [scheduleHighlightId, setScheduleHighlightId] = useState<string | number | null>(null);
const [duplicateRow, setDuplicateRow] = useState<WorkOrderTableRow | null>(null);
const [isCheckingInlineDuplicate, setIsCheckingInlineDuplicate] = useState(false);
const { data: locationSites = [] } = useLocationSites();
const sitePlaceLookups = useMemo(() => buildSitePlaceLookups(locationSites), [locationSites]);
const createMutation = useCreateWorkOrderFromWizard(() => {
tableData.cancelDraft();
const { handleInlineSave, saving } = useWoTableInlineCreate({
tableData,
users,
sites,
onDuplicateFound: setDuplicateRow,
});
const handlers = useWoTableRowHandlers({
@ -79,31 +77,6 @@ export function WoTable({
onDuplicateFound: setDuplicateRow,
});
const handleInlineSave = () => {
void (async () => {
const draftSnapshot = tableData.draft;
const woNumber = draftSnapshot.woNumber.trim();
if (woNumber) {
setIsCheckingInlineDuplicate(true);
try {
const duplicate =
findDuplicateWoNumberRow(woNumber, tableData.rows, "draft") ??
(await workOrdersApi.findByWoNumber(woNumber));
if (duplicate && String(duplicate.id) !== "draft") {
setDuplicateRow(duplicate);
return;
}
} catch {
toast.error("Unable to verify the work order number. Please try again.");
return;
} finally {
setIsCheckingInlineDuplicate(false);
}
}
createMutation.mutate(buildInlineDraftCreateInput(tableData.draft, users, sites));
})();
};
const renderRow = (row: WorkOrderTableRow, forceScheduleHighlight = false) => (
<WoTableRow
key={String(row.id)}
@ -138,7 +111,7 @@ export function WoTable({
vendors={vendors}
pmTypes={pmTypes}
allRows={tableData.rows}
saving={createMutation.isPending || isCheckingInlineDuplicate}
saving={saving}
onChange={tableData.setDraft}
onSave={handleInlineSave}
onCancel={tableData.cancelDraft}

View file

@ -1,5 +1,4 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { toast } from "react-toastify";
import { useEffect, useMemo, useState } from "react";
import { isWoWizardMockEnabled } from "@/domain/work-orders/mocks/is-wo-wizard-mock-enabled";
import {
getMockWoWizardLocationDetail,
@ -21,8 +20,7 @@ import {
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 { workOrdersApi } from "@/domain/work-orders/api/work-orders-api";
import { useWizardDuplicateActions } from "./use-wizard-duplicate-actions";
type UseNewWoWizardStateArgs = {
open: boolean;
@ -44,18 +42,6 @@ export function useNewWoWizardState({
status: "Incomplete",
});
const [pocAutoFilledFor, setPocAutoFilledFor] = useState("");
const [duplicateRow, setDuplicateRow] = useState<WorkOrderTableRow | null>(null);
const [isCheckingDuplicate, setIsCheckingDuplicate] = useState(false);
const openRef = useRef(open);
const draftRef = useRef(draft);
useEffect(() => {
openRef.current = open;
}, [open]);
useEffect(() => {
draftRef.current = draft;
}, [draft]);
const { data: apiLocations = [] } = useWorkOrderLocations();
const { data: apiProblems = [] } = useDropdownOptionsByCategory("Problem");
@ -72,6 +58,18 @@ export function useNewWoWizardState({
isMockLocation ? undefined : locationDetail?.zipCode,
);
const createMutation = useCreateWorkOrderFromWizard(() => onOpenChange(false));
const {
duplicateRow,
setDuplicateRow,
handleDuplicateFound,
handleCreate,
isCreating,
} = useWizardDuplicateActions({
open,
draft,
existingRows,
createMutation,
});
const wizardUsers = useMemo(() => {
if (users.length > 0) {
@ -92,7 +90,7 @@ export function useNewWoWizardState({
setPocAutoFilledFor("");
setDuplicateRow(null);
}
}, [open]);
}, [open, setDuplicateRow]);
useEffect(() => {
if (!draft.locationId || !locationDetail) {
@ -123,62 +121,6 @@ export function useNewWoWizardState({
}
};
const resolveDuplicate = async (woNumber: string) => {
const localDuplicate = findDuplicateWoNumberRow(woNumber, existingRows);
if (localDuplicate) {
return localDuplicate;
}
// The loaded board rows are only an immediate UX hint; the unfiltered API lookup is authoritative.
return workOrdersApi.findByWoNumber(woNumber);
};
const handleDuplicateFound = (woNumber: string) => {
void (async () => {
try {
const duplicate = await resolveDuplicate(woNumber);
// Ignore stale lookups after dismiss or after the user edits the WO#.
if (!openRef.current || woNumber !== draftRef.current.woNumber) {
return;
}
if (duplicate) {
setDuplicateRow(duplicate);
}
} catch {
if (!openRef.current) {
return;
}
toast.error("Unable to verify the work order number. Please try again.");
}
})();
};
const handleCreate = () => {
const woNumberAtSubmit = draft.woNumber;
void (async () => {
setIsCheckingDuplicate(true);
try {
const duplicate = await resolveDuplicate(woNumberAtSubmit);
// Ignore after dismiss or if the WO# changed while the request was in flight.
if (!openRef.current || woNumberAtSubmit !== draftRef.current.woNumber) {
return;
}
if (duplicate) {
setDuplicateRow(duplicate);
return;
}
createMutation.mutate(draftRef.current);
} catch {
if (!openRef.current) {
return;
}
toast.error("Unable to verify the work order number. Please try again.");
} finally {
setIsCheckingDuplicate(false);
}
})();
};
return {
step,
setStep,
@ -194,6 +136,6 @@ export function useNewWoWizardState({
patchDraft,
handleDuplicateFound,
handleCreate,
isCreating: createMutation.isPending || isCheckingDuplicate,
isCreating,
};
}

View file

@ -0,0 +1,100 @@
import { useEffect, useRef, useState } from "react";
import { toast } from "react-toastify";
import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-table-row";
import type { WorkOrderWizardDraft } from "@/domain/work-orders/types/work-order-wizard";
import { findDuplicateWoNumberRow } from "@/domain/work-orders/utils/find-duplicate-wo-number-row";
import { workOrdersApi } from "@/domain/work-orders/api/work-orders-api";
type UseWizardDuplicateActionsArgs = {
open: boolean;
draft: WorkOrderWizardDraft;
existingRows: WorkOrderTableRow[];
createMutation: {
mutate: (draft: WorkOrderWizardDraft) => void;
isPending: boolean;
};
};
export function useWizardDuplicateActions({
open,
draft,
existingRows,
createMutation,
}: UseWizardDuplicateActionsArgs) {
const [duplicateRow, setDuplicateRow] = useState<WorkOrderTableRow | null>(null);
const [isCheckingDuplicate, setIsCheckingDuplicate] = useState(false);
const openRef = useRef(open);
const draftRef = useRef(draft);
useEffect(() => {
openRef.current = open;
}, [open]);
useEffect(() => {
draftRef.current = draft;
}, [draft]);
const resolveDuplicate = async (woNumber: string) => {
const localDuplicate = findDuplicateWoNumberRow(woNumber, existingRows);
if (localDuplicate) {
return localDuplicate;
}
// The loaded board rows are only an immediate UX hint; the unfiltered API lookup is authoritative.
return workOrdersApi.findByWoNumber(woNumber);
};
const handleDuplicateFound = (woNumber: string) => {
void (async () => {
try {
const duplicate = await resolveDuplicate(woNumber);
// Ignore stale lookups after dismiss or after the user edits the WO#.
if (!openRef.current || woNumber !== draftRef.current.woNumber) {
return;
}
if (duplicate) {
setDuplicateRow(duplicate);
}
} catch {
if (!openRef.current) {
return;
}
toast.error("Unable to verify the work order number. Please try again.");
}
})();
};
const handleCreate = () => {
const woNumberAtSubmit = draft.woNumber;
void (async () => {
setIsCheckingDuplicate(true);
try {
const duplicate = await resolveDuplicate(woNumberAtSubmit);
// Ignore after dismiss or if the WO# changed while the request was in flight.
if (!openRef.current || woNumberAtSubmit !== draftRef.current.woNumber) {
return;
}
if (duplicate) {
setDuplicateRow(duplicate);
return;
}
createMutation.mutate(draftRef.current);
} catch {
if (!openRef.current) {
return;
}
toast.error("Unable to verify the work order number. Please try again.");
} finally {
setIsCheckingDuplicate(false);
}
})();
};
return {
duplicateRow,
setDuplicateRow,
handleDuplicateFound,
handleCreate,
isCreating: createMutation.isPending || isCheckingDuplicate,
};
}