mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
refactor(vendors): isolate contact fields
This commit is contained in:
parent
2b889aa277
commit
96415d59d0
2 changed files with 91 additions and 71 deletions
89
src/app/(protected)/vendors/_components/vendor-company-contact-fields.tsx
vendored
Normal file
89
src/app/(protected)/vendors/_components/vendor-company-contact-fields.tsx
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import { Controller, useWatch, type Control, type FieldErrors } from "react-hook-form";
|
||||
import { Stack, TextField } from "@mui/material";
|
||||
import { Text } from "@/components/ui/text";
|
||||
import {
|
||||
VENDOR_COMPANY_CONTACT_REQUIRED_MESSAGE,
|
||||
type VendorCompanyRosterFormValues,
|
||||
} from "@/domain/vendors/schemas/vendor-roster-schema";
|
||||
import { formatNorthAmericanPhone } from "@/lib/format/na-phone";
|
||||
|
||||
const COMPANY_CONTACT_ERROR_ID = "vendor-company-contact-error";
|
||||
const COMPANY_PHONE_HELPER_ID = "vendor-company-phone-helper";
|
||||
const COMPANY_EMAIL_HELPER_ID = "vendor-company-email-helper";
|
||||
|
||||
interface VendorCompanyContactFieldsProps {
|
||||
control: Control<VendorCompanyRosterFormValues>;
|
||||
errors: FieldErrors<VendorCompanyRosterFormValues>;
|
||||
}
|
||||
|
||||
export function VendorCompanyContactFields({ control, errors }: VendorCompanyContactFieldsProps) {
|
||||
const companyPhone = useWatch({ control, name: "companyPhone" }) ?? "";
|
||||
const companyEmail = useWatch({ control, name: "email" }) ?? "";
|
||||
const showCompanyContactError = Boolean(
|
||||
errors.companyContact && !companyPhone.trim() && !companyEmail.trim(),
|
||||
);
|
||||
const contactDescribedBy = (helperId: string, hasHelper: boolean) =>
|
||||
[hasHelper ? helperId : null, showCompanyContactError ? COMPANY_CONTACT_ERROR_ID : null]
|
||||
.filter(Boolean)
|
||||
.join(" ") || undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
|
||||
<Controller
|
||||
control={control}
|
||||
name="companyPhone"
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
label="Company Phone (optional)"
|
||||
placeholder="(214) 555-0100"
|
||||
inputMode="tel"
|
||||
value={field.value ?? ""}
|
||||
onChange={(event) => field.onChange(formatNorthAmericanPhone(event.target.value))}
|
||||
error={Boolean(errors.companyPhone)}
|
||||
helperText={errors.companyPhone?.message}
|
||||
slotProps={{
|
||||
formHelperText: { id: COMPANY_PHONE_HELPER_ID },
|
||||
htmlInput: {
|
||||
"aria-describedby": contactDescribedBy(
|
||||
COMPANY_PHONE_HELPER_ID,
|
||||
Boolean(errors.companyPhone?.message),
|
||||
),
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
label="Email (optional)"
|
||||
placeholder="dispatch@vendor.com"
|
||||
type="email"
|
||||
error={Boolean(errors.email)}
|
||||
helperText={errors.email?.message}
|
||||
slotProps={{
|
||||
formHelperText: { id: COMPANY_EMAIL_HELPER_ID },
|
||||
htmlInput: {
|
||||
"aria-describedby": contactDescribedBy(
|
||||
COMPANY_EMAIL_HELPER_ID,
|
||||
Boolean(errors.email?.message),
|
||||
),
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
<Text variant="error" id={COMPANY_CONTACT_ERROR_ID} when={showCompanyContactError}>
|
||||
{VENDOR_COMPANY_CONTACT_REQUIRED_MESSAGE}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -23,13 +23,12 @@ import {
|
|||
import { VendorTradeSpecialtiesField } from "./vendor-trade-specialties-field";
|
||||
import { formatNorthAmericanPhone } from "@/lib/format/na-phone";
|
||||
import {
|
||||
VENDOR_COMPANY_CONTACT_REQUIRED_MESSAGE,
|
||||
VENDOR_NOTES_MAX_LENGTH,
|
||||
type RosterTechnicianValues,
|
||||
type VendorCompanyRosterFormValues,
|
||||
} from "@/domain/vendors/schemas/vendor-roster-schema";
|
||||
import type { VendorFacetCompany } from "@/domain/vendors/types/vendor";
|
||||
import { Text } from "@/components/ui/text";
|
||||
import { VendorCompanyContactFields } from "./vendor-company-contact-fields";
|
||||
|
||||
interface VendorRosterFormFieldsProps {
|
||||
control: Control<VendorCompanyRosterFormValues>;
|
||||
|
|
@ -43,10 +42,6 @@ interface VendorRosterFormFieldsProps {
|
|||
showTechnicianStatus?: boolean;
|
||||
}
|
||||
|
||||
const COMPANY_CONTACT_ERROR_ID = "vendor-company-contact-error";
|
||||
const COMPANY_PHONE_HELPER_ID = "vendor-company-phone-helper";
|
||||
const COMPANY_EMAIL_HELPER_ID = "vendor-company-email-helper";
|
||||
|
||||
function CompanyNameField({
|
||||
control,
|
||||
errors,
|
||||
|
|
@ -142,16 +137,6 @@ function CompanyFields({
|
|||
onClearSelectedCompany,
|
||||
}: VendorRosterFormFieldsProps) {
|
||||
const notes = useWatch({ control, name: "notes" }) ?? "";
|
||||
const companyPhone = useWatch({ control, name: "companyPhone" }) ?? "";
|
||||
const companyEmail = useWatch({ control, name: "email" }) ?? "";
|
||||
const companyContactError = errors.companyContact;
|
||||
const showCompanyContactError = Boolean(
|
||||
companyContactError && !companyPhone.trim() && !companyEmail.trim(),
|
||||
);
|
||||
const contactDescribedBy = (helperId: string, hasHelper: boolean) =>
|
||||
[hasHelper ? helperId : null, showCompanyContactError ? COMPANY_CONTACT_ERROR_ID : null]
|
||||
.filter(Boolean)
|
||||
.join(" ") || undefined;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
|
|
@ -164,61 +149,7 @@ function CompanyFields({
|
|||
onSelectCompany={onSelectCompany}
|
||||
onClearSelectedCompany={onClearSelectedCompany}
|
||||
/>
|
||||
<Stack direction={{ xs: "column", sm: "row" }} spacing={2}>
|
||||
<Controller
|
||||
control={control}
|
||||
name="companyPhone"
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
label="Company Phone (optional)"
|
||||
placeholder="(214) 555-0100"
|
||||
inputMode="tel"
|
||||
value={field.value ?? ""}
|
||||
onChange={(event) => field.onChange(formatNorthAmericanPhone(event.target.value))}
|
||||
error={Boolean(errors.companyPhone)}
|
||||
helperText={errors.companyPhone?.message}
|
||||
slotProps={{
|
||||
formHelperText: { id: COMPANY_PHONE_HELPER_ID },
|
||||
htmlInput: {
|
||||
"aria-describedby": contactDescribedBy(
|
||||
COMPANY_PHONE_HELPER_ID,
|
||||
Boolean(errors.companyPhone?.message),
|
||||
),
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name="email"
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
label="Email (optional)"
|
||||
placeholder="dispatch@vendor.com"
|
||||
type="email"
|
||||
error={Boolean(errors.email)}
|
||||
helperText={errors.email?.message}
|
||||
slotProps={{
|
||||
formHelperText: { id: COMPANY_EMAIL_HELPER_ID },
|
||||
htmlInput: {
|
||||
"aria-describedby": contactDescribedBy(
|
||||
COMPANY_EMAIL_HELPER_ID,
|
||||
Boolean(errors.email?.message),
|
||||
),
|
||||
},
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
<Text variant="error" id={COMPANY_CONTACT_ERROR_ID} when={showCompanyContactError}>
|
||||
{VENDOR_COMPANY_CONTACT_REQUIRED_MESSAGE}
|
||||
</Text>
|
||||
<VendorCompanyContactFields control={control} errors={errors} />
|
||||
<Controller
|
||||
control={control}
|
||||
name="address"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue