mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
fix(work-orders): split comp-doc dialog hook under max-lines gate
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
31dd9d5b72
commit
db2ca4d933
3 changed files with 135 additions and 59 deletions
|
|
@ -0,0 +1,58 @@
|
|||
import { useEffect, useRef, type Dispatch, type SetStateAction } from "react";
|
||||
import type { CompDocData, DocState } from "@/domain/work-orders/types/completion-doc";
|
||||
import { docStateOf } from "@/domain/work-orders/utils/completion-doc-state";
|
||||
|
||||
type UseCompDocDialogSeedArgs = {
|
||||
open: boolean;
|
||||
infoId: string | number;
|
||||
infoDocStatus?: string | null;
|
||||
infoCompletedDate?: string | null;
|
||||
completionDocStatus?: string | null;
|
||||
data?: CompDocData;
|
||||
setNotes: Dispatch<SetStateAction<string>>;
|
||||
setDocState: Dispatch<SetStateAction<DocState>>;
|
||||
setGeneratedAt: Dispatch<SetStateAction<string>>;
|
||||
setEditDateCompleted: Dispatch<SetStateAction<string>>;
|
||||
};
|
||||
|
||||
/** Prototype seeds once per open/WO session; detail refetches must not wipe edits. */
|
||||
export function useCompDocDialogSeed({
|
||||
open,
|
||||
infoId,
|
||||
infoDocStatus,
|
||||
infoCompletedDate,
|
||||
completionDocStatus,
|
||||
data,
|
||||
setNotes,
|
||||
setDocState,
|
||||
setGeneratedAt,
|
||||
setEditDateCompleted,
|
||||
}: UseCompDocDialogSeedArgs) {
|
||||
const seedKeyRef = useRef<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
seedKeyRef.current = null;
|
||||
return;
|
||||
}
|
||||
const key = String(infoId);
|
||||
if (seedKeyRef.current === key) return;
|
||||
seedKeyRef.current = key;
|
||||
setNotes(data?.notes ?? "");
|
||||
setDocState(docStateOf(completionDocStatus || infoDocStatus));
|
||||
setGeneratedAt(data?.generatedAt ?? "");
|
||||
setEditDateCompleted(infoCompletedDate || "");
|
||||
}, [
|
||||
open,
|
||||
infoId,
|
||||
infoDocStatus,
|
||||
infoCompletedDate,
|
||||
completionDocStatus,
|
||||
data?.notes,
|
||||
data?.generatedAt,
|
||||
setNotes,
|
||||
setDocState,
|
||||
setGeneratedAt,
|
||||
setEditDateCompleted,
|
||||
]);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import { useLocationDetail } from "@/domain/locations/use-cases/use-location-detail";
|
||||
import type {
|
||||
|
|
@ -11,8 +11,10 @@ import type { WorkOrderTableRow } from "@/domain/work-orders/types/work-order-ta
|
|||
import { useWorkOrderBoardDetail } from "@/domain/work-orders/use-cases/use-work-order-detail";
|
||||
import { useUploadCompletionDoc } from "@/domain/work-orders/use-cases/use-work-order-mutations";
|
||||
import { resolveCompDocSite } from "@/domain/work-orders/utils/completion-doc-site";
|
||||
import { DOC_STATE_CFG, docStateOf } from "@/domain/work-orders/utils/completion-doc-state";
|
||||
import { DOC_STATE_CFG } from "@/domain/work-orders/utils/completion-doc-state";
|
||||
import { isWorkOrderDocumentsReadOnly } from "@/domain/work-orders/utils/work-order-media-limits";
|
||||
import { useCompDocDialogSeed } from "./use-comp-doc-dialog-seed";
|
||||
import { useCompDocNotRequiredActions } from "./use-comp-doc-not-required-actions";
|
||||
import { useCompDocPdfActions } from "./use-comp-doc-pdf-actions";
|
||||
import { useCompDocPersistFlow } from "./use-comp-doc-persist-flow";
|
||||
|
||||
|
|
@ -71,45 +73,31 @@ export function useCompDocDialog({
|
|||
const signOffAttachment = completion?.signOffAttachment;
|
||||
const rowVersion = info.rowVersion || row.rowVersion;
|
||||
const isDocumentsReadOnly = isWorkOrderDocumentsReadOnly(info.status);
|
||||
|
||||
const site = useMemo(() => resolveCompDocSite(info, locationDetail), [info, locationDetail]);
|
||||
|
||||
const [notes, setNotes] = useState("");
|
||||
const [docState, setDocState] = useState<DocState>("draft");
|
||||
const [generatedAt, setGeneratedAt] = useState("");
|
||||
const [editDateCompleted, setEditDateCompleted] = useState("");
|
||||
const seedKeyRef = useRef<string | null>(null);
|
||||
|
||||
// Prototype seeds once per open/WO session. Detail refetches must not wipe
|
||||
// in-progress PM comments or date edits (Bugbot: dialog effect clears edits).
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
seedKeyRef.current = null;
|
||||
return;
|
||||
}
|
||||
const key = String(info.id);
|
||||
if (seedKeyRef.current === key) return;
|
||||
seedKeyRef.current = key;
|
||||
setNotes(data?.notes ?? "");
|
||||
setDocState(docStateOf(completion?.docStatus || info.docStatus));
|
||||
setGeneratedAt(data?.generatedAt ?? "");
|
||||
setEditDateCompleted(info.completedDate || "");
|
||||
}, [
|
||||
useCompDocDialogSeed({
|
||||
open,
|
||||
info.id,
|
||||
info.docStatus,
|
||||
info.completedDate,
|
||||
completion?.docStatus,
|
||||
data?.notes,
|
||||
data?.generatedAt,
|
||||
]);
|
||||
infoId: info.id,
|
||||
infoDocStatus: info.docStatus,
|
||||
infoCompletedDate: info.completedDate,
|
||||
completionDocStatus: completion?.docStatus,
|
||||
data,
|
||||
setNotes,
|
||||
setDocState,
|
||||
setGeneratedAt,
|
||||
setEditDateCompleted,
|
||||
});
|
||||
|
||||
const amazonRep = info.pocName || "";
|
||||
const seaRep = info.tech || "";
|
||||
const cfg = DOC_STATE_CFG[docState];
|
||||
const isNotRequired = docState === "not-required";
|
||||
const isGenerated = docState === "generated" || Boolean(signOffAttachment);
|
||||
const isBusy = uploadCompletionMutation.isPending || isFinalizing;
|
||||
|
||||
const docFields: DocFields = {
|
||||
street: site.street,
|
||||
|
|
@ -137,37 +125,13 @@ export function useCompDocDialog({
|
|||
onDraftSaved: notifyDraftSaved,
|
||||
});
|
||||
|
||||
async function handleMarkNotRequired() {
|
||||
const previous = docState;
|
||||
setDocState("not-required");
|
||||
setIsFinalizing(true);
|
||||
try {
|
||||
await persist({}, "NN");
|
||||
} catch (error) {
|
||||
setDocState(previous);
|
||||
refreshAuthoritativeState();
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Failed to mark document as not required",
|
||||
);
|
||||
} finally {
|
||||
setIsFinalizing(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleUndo() {
|
||||
const previous = docState;
|
||||
setDocState("draft");
|
||||
setIsFinalizing(true);
|
||||
try {
|
||||
await persist({}, "No");
|
||||
} catch (error) {
|
||||
setDocState(previous);
|
||||
refreshAuthoritativeState();
|
||||
toast.error(error instanceof Error ? error.message : "Failed to undo not-required");
|
||||
} finally {
|
||||
setIsFinalizing(false);
|
||||
}
|
||||
}
|
||||
const { handleMarkNotRequired, handleUndo } = useCompDocNotRequiredActions({
|
||||
docState,
|
||||
setDocState,
|
||||
persist,
|
||||
refreshAuthoritativeState,
|
||||
setIsFinalizing,
|
||||
});
|
||||
|
||||
const { handleDownloadPdf, handleUploadPdf } = useCompDocPdfActions({
|
||||
info,
|
||||
|
|
@ -203,7 +167,7 @@ export function useCompDocDialog({
|
|||
cfg,
|
||||
isNotRequired,
|
||||
isGenerated,
|
||||
isUploading: isBusy,
|
||||
isUploading: uploadCompletionMutation.isPending || isFinalizing,
|
||||
pdfInputRef,
|
||||
handleMarkNotRequired,
|
||||
handleUndo,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
import { toast } from "react-toastify";
|
||||
import type { CompDocSaveStatus, DocState } from "@/domain/work-orders/types/completion-doc";
|
||||
|
||||
type PersistFn = (data: Record<string, never>, status: CompDocSaveStatus) => void | Promise<void>;
|
||||
|
||||
type UseCompDocNotRequiredActionsArgs = {
|
||||
docState: DocState;
|
||||
setDocState: (state: DocState) => void;
|
||||
persist: PersistFn;
|
||||
refreshAuthoritativeState: () => void;
|
||||
setIsFinalizing: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export function useCompDocNotRequiredActions({
|
||||
docState,
|
||||
setDocState,
|
||||
persist,
|
||||
refreshAuthoritativeState,
|
||||
setIsFinalizing,
|
||||
}: UseCompDocNotRequiredActionsArgs) {
|
||||
async function handleMarkNotRequired() {
|
||||
const previous = docState;
|
||||
setDocState("not-required");
|
||||
setIsFinalizing(true);
|
||||
try {
|
||||
await persist({}, "NN");
|
||||
} catch (error) {
|
||||
setDocState(previous);
|
||||
refreshAuthoritativeState();
|
||||
toast.error(
|
||||
error instanceof Error ? error.message : "Failed to mark document as not required",
|
||||
);
|
||||
} finally {
|
||||
setIsFinalizing(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleUndo() {
|
||||
const previous = docState;
|
||||
setDocState("draft");
|
||||
setIsFinalizing(true);
|
||||
try {
|
||||
await persist({}, "No");
|
||||
} catch (error) {
|
||||
setDocState(previous);
|
||||
refreshAuthoritativeState();
|
||||
toast.error(error instanceof Error ? error.message : "Failed to undo not-required");
|
||||
} finally {
|
||||
setIsFinalizing(false);
|
||||
}
|
||||
}
|
||||
|
||||
return { handleMarkNotRequired, handleUndo };
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue