mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 08:09:00 +00:00
Two groups of components were calling the API directly instead of using this codebase's standard React Query hooks, with no shared caching and duplicated submit/error-handling boilerplate. - checklist-section.tsx, comments-section.tsx, signoff-section.tsx, uplift-requests-section.tsx: replace direct vendorPortalApi calls and hand-rolled submitting/error state with mutation hooks in the new use-vendor-portal-dispatch-actions.ts. uplift-requests-section keeps its existing multi-step evidence-upload orchestration intact and only swaps the 3 raw API calls for mutateAsync, since restructuring that flow around declarative mutation callbacks carried more risk than value. Caught and fixed a real bug along the way: two components were passing a prop callback directly as a mutation's onSuccess, which would have forwarded React Query's extra callback arguments into it. - followups/index.tsx, vendors/preferences.tsx: split from a single file doing state, API calls, and rendering into a hook (owns data and handlers) plus small presentational components, matching the task-templates refactor pattern. Added a missing centralized query key (vendorOperations.sitePreferences) that preferences.tsx was building as a raw inline array. - use-list-page-filters.ts: small shared hook for search/page/pageSize state, used by the new followups hook. 29 new/updated tests across all touched files; none of these had coverage for their mutation/error paths before.
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import { Autocomplete, Box, Button, Paper, Stack, TextField } from "@mui/material";
|
|
import { Text } from "@/components/ui/text";
|
|
import { AddVendorPreferenceControls } from "./_components/add-vendor-preference-controls";
|
|
import { PreferenceRow } from "./_components/preference-row";
|
|
import { useVendorPreferencesEditor } from "./_components/use-vendor-preferences-editor";
|
|
|
|
export default function VendorPreferencesPage() {
|
|
const {
|
|
locationId,
|
|
selectLocation,
|
|
locations,
|
|
draft,
|
|
trade,
|
|
setTrade,
|
|
vendorId,
|
|
setVendorId,
|
|
vendors,
|
|
vendorOptions,
|
|
error,
|
|
isSaving,
|
|
save,
|
|
move,
|
|
add,
|
|
remove,
|
|
} = useVendorPreferencesEditor();
|
|
|
|
return (
|
|
<Box className="flex flex-col gap-4 p-4">
|
|
<Box>
|
|
<Text variant="title" as="h1">
|
|
Preferred vendors by site
|
|
</Text>
|
|
<Text variant="description" tone="muted">
|
|
Preferred vendors rank first, but availability, conflict, trade, active-state, and
|
|
permission checks still apply.
|
|
</Text>
|
|
</Box>
|
|
<Paper variant="outlined" className="p-4">
|
|
<Autocomplete
|
|
options={locations}
|
|
getOptionLabel={(option) => option.name}
|
|
value={locations.find((location) => location.id === locationId) ?? null}
|
|
onChange={(_event, option) => selectLocation(option?.id ?? "")}
|
|
renderInput={(params) => <TextField {...params} label="Site" />}
|
|
/>
|
|
</Paper>
|
|
<Text variant="error" when={Boolean(error)}>
|
|
Unable to load preferred vendors. Please try again.
|
|
</Text>
|
|
{locationId !== "" && (
|
|
<>
|
|
<AddVendorPreferenceControls
|
|
trade={trade}
|
|
onTradeChange={setTrade}
|
|
vendorOptions={vendorOptions}
|
|
vendors={vendors}
|
|
vendorId={vendorId}
|
|
onVendorChange={setVendorId}
|
|
onAdd={add}
|
|
/>
|
|
<Stack spacing={1}>
|
|
{draft.map((item, index) => (
|
|
<PreferenceRow
|
|
key={`${item.vendorId}-${item.trade ?? "all"}`}
|
|
item={item}
|
|
index={index}
|
|
total={draft.length}
|
|
onMove={move}
|
|
onRemove={remove}
|
|
/>
|
|
))}
|
|
</Stack>
|
|
<Button variant="contained" onClick={save} disabled={isSaving}>
|
|
{isSaving ? "Saving…" : "Save preferences"}
|
|
</Button>
|
|
</>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|