mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-06 05:22:04 +00:00
fix(work-orders): extract completed vendor dialog to pass maintainability
This commit is contained in:
parent
eeb415951c
commit
17ad0e5098
4 changed files with 127 additions and 69 deletions
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Button } from "@mui/material";
|
||||||
|
import type { VendorEditorState } from "./work-order-vendor-editor-types";
|
||||||
|
import { isVendorEditorValid } from "./work-order-vendor-editor-utils";
|
||||||
|
|
||||||
|
type WorkOrderVendorEditorActionsProps = {
|
||||||
|
viewOnly: boolean;
|
||||||
|
editor: VendorEditorState | null;
|
||||||
|
loading: boolean;
|
||||||
|
isSaving: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSave: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function WorkOrderVendorEditorActions({
|
||||||
|
viewOnly,
|
||||||
|
editor,
|
||||||
|
loading,
|
||||||
|
isSaving,
|
||||||
|
onClose,
|
||||||
|
onSave,
|
||||||
|
}: WorkOrderVendorEditorActionsProps) {
|
||||||
|
if (viewOnly) {
|
||||||
|
return <Button onClick={onClose}>Close</Button>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button onClick={onClose} disabled={isSaving}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
onClick={onSave}
|
||||||
|
disabled={!editor || loading || isSaving || !isVendorEditorValid(editor)}
|
||||||
|
>
|
||||||
|
{isSaving ? "Saving..." : "Save"}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
Stack,
|
Stack,
|
||||||
TextField,
|
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import type { VendorEditorState } from "./work-order-vendor-editor-types";
|
import type { VendorEditorState } from "./work-order-vendor-editor-types";
|
||||||
import { formatPhoneMask, isVendorEditorValid } from "./work-order-vendor-editor-utils";
|
import { WorkOrderVendorEditorActions } from "./work-order-vendor-editor-actions";
|
||||||
|
import { WorkOrderVendorEditorFields } from "./work-order-vendor-editor-fields";
|
||||||
|
|
||||||
type WorkOrderVendorEditorDialogProps = {
|
type WorkOrderVendorEditorDialogProps = {
|
||||||
editor: VendorEditorState | null;
|
editor: VendorEditorState | null;
|
||||||
|
|
@ -51,75 +50,23 @@ export function WorkOrderVendorEditorDialog({
|
||||||
<CircularProgress size={28} />
|
<CircularProgress size={28} />
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<WorkOrderVendorEditorFields
|
||||||
<TextField
|
editor={editor}
|
||||||
label="Technician name"
|
disabled={viewOnly}
|
||||||
value={editor?.contactName ?? ""}
|
onEditorChange={onEditorChange}
|
||||||
disabled={viewOnly}
|
/>
|
||||||
onChange={(event) =>
|
|
||||||
onEditorChange((current) =>
|
|
||||||
current ? { ...current, contactName: event.target.value } : current,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
slotProps={{ htmlInput: { maxLength: 200 } }}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label="Phone"
|
|
||||||
value={editor?.phone ?? ""}
|
|
||||||
disabled={viewOnly}
|
|
||||||
onChange={(event) =>
|
|
||||||
onEditorChange((current) =>
|
|
||||||
current ? { ...current, phone: formatPhoneMask(event.target.value) } : current,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
error={Boolean(editor?.phone && !/^\(\d{3}\) \d{3}-\d{4}$/.test(editor.phone))}
|
|
||||||
helperText="Use (XXX) XXX-XXXX"
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label="Email"
|
|
||||||
type="email"
|
|
||||||
value={editor?.email ?? ""}
|
|
||||||
disabled={viewOnly}
|
|
||||||
onChange={(event) =>
|
|
||||||
onEditorChange((current) =>
|
|
||||||
current ? { ...current, email: event.target.value } : current,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
label="Notes"
|
|
||||||
multiline
|
|
||||||
minRows={3}
|
|
||||||
value={editor?.notes ?? ""}
|
|
||||||
disabled={viewOnly}
|
|
||||||
onChange={(event) =>
|
|
||||||
onEditorChange((current) =>
|
|
||||||
current ? { ...current, notes: event.target.value } : current,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
slotProps={{ htmlInput: { maxLength: 2000 } }}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
{viewOnly ? (
|
<WorkOrderVendorEditorActions
|
||||||
<Button onClick={onClose}>Close</Button>
|
viewOnly={viewOnly}
|
||||||
) : (
|
editor={editor}
|
||||||
<>
|
loading={loading}
|
||||||
<Button onClick={onClose} disabled={isSaving}>
|
isSaving={isSaving}
|
||||||
Cancel
|
onClose={onClose}
|
||||||
</Button>
|
onSave={onSave}
|
||||||
<Button
|
/>
|
||||||
variant="contained"
|
|
||||||
onClick={onSave}
|
|
||||||
disabled={!editor || loading || isSaving || !isVendorEditorValid(editor)}
|
|
||||||
>
|
|
||||||
{isSaving ? "Saving..." : "Save"}
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { TextField } from "@mui/material";
|
||||||
|
import type { VendorEditorState } from "./work-order-vendor-editor-types";
|
||||||
|
import { formatPhoneMask } from "./work-order-vendor-editor-utils";
|
||||||
|
|
||||||
|
type VendorEditorChange = (
|
||||||
|
updater: (current: VendorEditorState | null) => VendorEditorState | null,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
type WorkOrderVendorEditorFieldsProps = {
|
||||||
|
editor: VendorEditorState | null;
|
||||||
|
disabled: boolean;
|
||||||
|
onEditorChange: VendorEditorChange;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function WorkOrderVendorEditorFields({
|
||||||
|
editor,
|
||||||
|
disabled,
|
||||||
|
onEditorChange,
|
||||||
|
}: WorkOrderVendorEditorFieldsProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TextField
|
||||||
|
label="Technician name"
|
||||||
|
value={editor?.contactName ?? ""}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={(event) =>
|
||||||
|
onEditorChange((current) =>
|
||||||
|
current ? { ...current, contactName: event.target.value } : current,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
slotProps={{ htmlInput: { maxLength: 200 } }}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label="Phone"
|
||||||
|
value={editor?.phone ?? ""}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={(event) =>
|
||||||
|
onEditorChange((current) =>
|
||||||
|
current ? { ...current, phone: formatPhoneMask(event.target.value) } : current,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
error={Boolean(editor?.phone && !/^\(\d{3}\) \d{3}-\d{4}$/.test(editor.phone))}
|
||||||
|
helperText="Use (XXX) XXX-XXXX"
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label="Email"
|
||||||
|
type="email"
|
||||||
|
value={editor?.email ?? ""}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={(event) =>
|
||||||
|
onEditorChange((current) =>
|
||||||
|
current ? { ...current, email: event.target.value } : current,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
label="Notes"
|
||||||
|
multiline
|
||||||
|
minRows={3}
|
||||||
|
value={editor?.notes ?? ""}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={(event) =>
|
||||||
|
onEditorChange((current) =>
|
||||||
|
current ? { ...current, notes: event.target.value } : current,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
slotProps={{ htmlInput: { maxLength: 2000 } }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ function WizardVendorDetail({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type WizardApptTimeFieldsProps = Omit<WizardStepVendorTimeProps, "vendors">;
|
type WizardApptTimeFieldsProps = Pick<WizardStepVendorTimeProps, "draft" | "onUpdate" | "onPatch">;
|
||||||
|
|
||||||
function WizardApptTimeFields({ draft, onUpdate, onPatch }: WizardApptTimeFieldsProps) {
|
function WizardApptTimeFields({ draft, onUpdate, onPatch }: WizardApptTimeFieldsProps) {
|
||||||
const duration = calcDuration(draft.apptStart, draft.apptEnd);
|
const duration = calcDuration(draft.apptStart, draft.apptEnd);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue