687 lines
20 KiB
TypeScript
687 lines
20 KiB
TypeScript
import { GlobeIcon, MoneyIcon } from "@/assets/icons";
|
|
import TagInput from "@/components/FormElements/InputGroup/tag-input";
|
|
import { TextAreaGroup } from "@/components/FormElements/InputGroup/text-area";
|
|
import MultiSelect from "@/components/FormElements/MultiSelect";
|
|
import { Select } from "@/components/FormElements/select";
|
|
import type { DynamicFormSection } from "@/components/forms/DynamicFormBuilder";
|
|
import { REGEX } from "@/constants/regex";
|
|
import { FormErrorMessages } from "@/constants/Texts";
|
|
import type { ICreateCompanyCredentials } from "@/lib/api";
|
|
import type { ILabelValue } from "@/types/shared";
|
|
import type { UseFormSetValue, UseFormWatch } from "react-hook-form";
|
|
import { v4 as uuidv4 } from "uuid";
|
|
import CompanyDocuments from "./documents/CompanyDocuments";
|
|
import CompanyLinks from "./links/CompanyLinks";
|
|
|
|
const companyInformationSectionId = uuidv4();
|
|
const businessInformationSectionId = uuidv4();
|
|
const settingsSectionId = uuidv4();
|
|
const addressSectionId = uuidv4();
|
|
const tagsSectionId = uuidv4();
|
|
const documentsSectionId = uuidv4();
|
|
const linksSectionId = uuidv4();
|
|
|
|
interface CompanyFormSectionsOptions {
|
|
editMode?: boolean;
|
|
id?: string;
|
|
categoryItems: ILabelValue[];
|
|
watch: UseFormWatch<ICreateCompanyCredentials>;
|
|
setValue: UseFormSetValue<ICreateCompanyCredentials>;
|
|
persistDocumentFileIds?: (ids: string[]) => Promise<void>;
|
|
}
|
|
|
|
const optionalNumber = (value: unknown) => {
|
|
if (value === "" || value === null || value === undefined) return undefined;
|
|
return Number(value);
|
|
};
|
|
|
|
const optionalNumberRange = ({
|
|
min,
|
|
max,
|
|
integer = false,
|
|
}: {
|
|
min: number;
|
|
max: number;
|
|
integer?: boolean;
|
|
}) => {
|
|
return (value: unknown) => {
|
|
const numberValue = optionalNumber(value);
|
|
|
|
if (numberValue === undefined) return true;
|
|
if (!Number.isFinite(numberValue)) return "Enter a valid number";
|
|
if (integer && !Number.isInteger(numberValue)) {
|
|
return "This field must be a whole number";
|
|
}
|
|
if (numberValue < min) return FormErrorMessages.min(min);
|
|
if (numberValue > max) return FormErrorMessages.max(max);
|
|
return true;
|
|
};
|
|
};
|
|
|
|
const languageItems: ILabelValue[] = [
|
|
{ value: "en", label: "EN" },
|
|
{ value: "ar", label: "AR" },
|
|
{ value: "fr", label: "FR" },
|
|
{ value: "es", label: "ES" },
|
|
{ value: "de", label: "DE" },
|
|
{ value: "zh", label: "ZH" },
|
|
{ value: "jEna", label: "jEna" },
|
|
{ value: "ko", label: "KO" },
|
|
];
|
|
|
|
const currencyItems: ILabelValue[] = [
|
|
{ label: "USD", value: "USD" },
|
|
{ label: "EUR", value: "EUR" },
|
|
{ label: "GBP", value: "GBP" },
|
|
{ label: "JPY", value: "JPY" },
|
|
{ label: "CAD", value: "CAD" },
|
|
{ label: "AUD", value: "AUD" },
|
|
{ label: "CHF", value: "CHF" },
|
|
{ label: "CNY", value: "CNY" },
|
|
{ label: "INR", value: "INR" },
|
|
{ label: "BRL", value: "BRL" },
|
|
];
|
|
|
|
const allTimezones: Record<string, string> = {
|
|
"Pacific/Midway": "Midway Island, Samoa",
|
|
"Pacific/Honolulu": "Hawaii",
|
|
"America/Juneau": "Alaska",
|
|
"America/Boise": "Mountain Time",
|
|
"America/Dawson": "Dawson, Yukon",
|
|
"America/Chihuahua": "Chihuahua, La Paz, Mazatlan",
|
|
"America/Phoenix": "Arizona",
|
|
"America/Los_Angeles": "Pacific Time",
|
|
"America/Chicago": "Central Time",
|
|
"America/Regina": "Saskatchewan",
|
|
"America/Mexico_City": "Guadalajara, Mexico City, Monterrey",
|
|
"America/Belize": "Central America",
|
|
"America/Detroit": "Eastern Time",
|
|
"America/Bogota": "Bogota, Lima, Quito",
|
|
"America/Caracas": "Caracas, La Paz",
|
|
"America/Santiago": "Santiago",
|
|
"America/St_Johns": "Newfoundland and Labrador",
|
|
"America/Sao_Paulo": "Brasilia",
|
|
"America/Tijuana": "Tijuana",
|
|
"America/Montevideo": "Montevideo",
|
|
"America/Argentina/Buenos_Aires": "Buenos Aires, Georgetown",
|
|
"America/Godthab": "Greenland",
|
|
"Atlantic/Azores": "Azores",
|
|
"Atlantic/Cape_Verde": "Cape Verde Islands",
|
|
GMT: "UTC",
|
|
"Europe/London": "Edinburgh, London",
|
|
"Europe/Dublin": "Dublin",
|
|
"Europe/Lisbon": "Lisbon",
|
|
"Africa/Casablanca": "Casablanca, Monrovia",
|
|
"Atlantic/Canary": "Canary Islands",
|
|
"Europe/Belgrade": "Belgrade, Bratislava, Budapest, Ljubljana, Prague",
|
|
"Europe/Sarajevo": "Sarajevo, Skopje, Warsaw, Zagreb",
|
|
"Europe/Brussels": "Brussels, Copenhagen, Madrid, Paris",
|
|
"Europe/Amsterdam": "Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna",
|
|
"Africa/Algiers": "West Central Africa",
|
|
"Europe/Bucharest": "Bucharest",
|
|
"Africa/Cairo": "Cairo",
|
|
"Europe/Helsinki": "Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius",
|
|
"Europe/Athens": "Athens",
|
|
"Asia/Jerusalem": "Jerusalem",
|
|
"Africa/Harare": "Harare, Pretoria",
|
|
"Europe/Moscow": "Istanbul, Minsk, Moscow, St. Petersburg, Volgograd",
|
|
"Asia/Kuwait": "Kuwait, Riyadh",
|
|
"Africa/Nairobi": "Nairobi",
|
|
"Asia/Baghdad": "Baghdad",
|
|
"Asia/Tehran": "Tehran",
|
|
"Asia/Dubai": "Abu Dhabi, Muscat",
|
|
"Asia/Baku": "Baku, Tbilisi, Yerevan",
|
|
"Asia/Kabul": "Kabul",
|
|
"Asia/Yekaterinburg": "Ekaterinburg",
|
|
"Asia/Karachi": "Islamabad, Karachi, Tashkent",
|
|
"Asia/Kolkata": "Chennai, Kolkata, Mumbai, New Delhi",
|
|
"Asia/Kathmandu": "Kathmandu",
|
|
"Asia/Dhaka": "Astana, Dhaka",
|
|
"Asia/Colombo": "Sri Jayawardenepura",
|
|
"Asia/Almaty": "Almaty, Novosibirsk",
|
|
"Asia/Rangoon": "Yangon Rangoon",
|
|
"Asia/Bangkok": "Bangkok, Hanoi, Jakarta",
|
|
"Asia/Krasnoyarsk": "Krasnoyarsk",
|
|
"Asia/Shanghai": "Beijing, Chongqing, Hong Kong SAR, Urumqi",
|
|
"Asia/Kuala_Lumpur": "Kuala Lumpur, Singapore",
|
|
"Asia/Taipei": "Taipei",
|
|
"Australia/Perth": "Perth",
|
|
"Asia/Irkutsk": "Irkutsk, Ulaanbaatar",
|
|
"Asia/Seoul": "Seoul",
|
|
"Asia/Tokyo": "Osaka, Sapporo, Tokyo",
|
|
"Asia/Yakutsk": "Yakutsk",
|
|
"Australia/Darwin": "Darwin",
|
|
"Australia/Adelaide": "Adelaide",
|
|
"Australia/Sydney": "Canberra, Melbourne, Sydney",
|
|
"Australia/Brisbane": "Brisbane",
|
|
"Australia/Hobart": "Hobart",
|
|
"Asia/Vladivostok": "Vladivostok",
|
|
"Pacific/Guam": "Guam, Port Moresby",
|
|
"Asia/Magadan": "Magadan, Solomon Islands, New Caledonia",
|
|
"Asia/Kamchatka": "Kamchatka, Marshall Islands",
|
|
"Pacific/Fiji": "Fiji Islands",
|
|
"Pacific/Auckland": "Auckland, Wellington",
|
|
"Pacific/Tongatapu": "Nuku'alofa",
|
|
};
|
|
|
|
const getTimezoneOffsetMinutes = (timezone: string, date = new Date()) => {
|
|
try {
|
|
const formatter = new Intl.DateTimeFormat("en", {
|
|
timeZone: timezone,
|
|
timeZoneName: "shortOffset",
|
|
});
|
|
const offset =
|
|
formatter.formatToParts(date).find((part) => part.type === "timeZoneName")
|
|
?.value ?? "";
|
|
const label = offset.replace(/^GMT/, "") || "+0";
|
|
const match = label.match(/^([+-])(\d{1,2})(?::(\d{2}))?$/);
|
|
|
|
if (!match) return 0;
|
|
|
|
const sign = match[1] === "-" ? -1 : 1;
|
|
const hours = Number(match[2]);
|
|
const minutes = Number(match[3] ?? 0);
|
|
|
|
return sign * (hours * 60 + minutes);
|
|
} catch {
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
const formatTimezoneOffset = (offsetMinutes: number) => {
|
|
const sign = offsetMinutes < 0 ? "-" : "+";
|
|
const absoluteMinutes = Math.abs(offsetMinutes);
|
|
const hours = Math.trunc(absoluteMinutes / 60);
|
|
const minutes = absoluteMinutes % 60;
|
|
|
|
return `${sign}${hours}:${minutes.toString().padStart(2, "0")}`;
|
|
};
|
|
|
|
const hasTimezoneDst = (timezone: string) => {
|
|
const januaryOffset = getTimezoneOffsetMinutes(
|
|
timezone,
|
|
new Date(new Date().getFullYear(), 0, 1),
|
|
);
|
|
const julyOffset = getTimezoneOffsetMinutes(
|
|
timezone,
|
|
new Date(new Date().getFullYear(), 6, 1),
|
|
);
|
|
|
|
return januaryOffset !== julyOffset;
|
|
};
|
|
|
|
const timezoneItems: ILabelValue[] = Object.entries(allTimezones)
|
|
.map(([timezone, name]) => {
|
|
const offsetMinutes = getTimezoneOffsetMinutes(timezone);
|
|
|
|
return {
|
|
timezone,
|
|
name,
|
|
hasDst: hasTimezoneDst(timezone),
|
|
offsetMinutes,
|
|
};
|
|
})
|
|
.sort((a, b) => a.offsetMinutes - b.offsetMinutes)
|
|
.filter((item, index, items) => {
|
|
return (
|
|
items.findIndex(
|
|
(timezone) =>
|
|
timezone.offsetMinutes === item.offsetMinutes &&
|
|
timezone.hasDst === item.hasDst,
|
|
) === index
|
|
);
|
|
})
|
|
.map(({ timezone, name, offsetMinutes }) => ({
|
|
label: `(GMT${formatTimezoneOffset(offsetMinutes)}) ${name}`,
|
|
value: timezone,
|
|
}));
|
|
|
|
export const createCompanyFormSections = ({
|
|
editMode,
|
|
id,
|
|
categoryItems,
|
|
watch,
|
|
setValue,
|
|
persistDocumentFileIds,
|
|
}: CompanyFormSectionsOptions): DynamicFormSection<ICreateCompanyCredentials>[] => [
|
|
{
|
|
id: companyInformationSectionId,
|
|
title: "Company information",
|
|
rootClassName: "lg:col-span-2",
|
|
className: "gap-x-5 gap-y-5 sm:grid-cols-2 md:grid-cols-2",
|
|
fields: [
|
|
{
|
|
kind: "input",
|
|
name: "name",
|
|
label: "Name",
|
|
type: "text",
|
|
placeholder: "Legal name as registered",
|
|
required: true,
|
|
className: "sm:col-span-2",
|
|
rules: {
|
|
required: { message: FormErrorMessages.required, value: true },
|
|
minLength: { value: 2, message: FormErrorMessages.minLength(2) },
|
|
maxLength: { value: 200, message: FormErrorMessages.maxLength(200) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "email",
|
|
label: "Email",
|
|
type: "email",
|
|
placeholder: "name@company.com",
|
|
required: true,
|
|
rules: {
|
|
required: { message: FormErrorMessages.required, value: true },
|
|
pattern: {
|
|
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
message: FormErrorMessages.invalidEmail,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "phone",
|
|
label: "Phone",
|
|
type: "tel",
|
|
placeholder: "+971 50 123 4567",
|
|
required: true,
|
|
rules: {
|
|
required: { message: FormErrorMessages.required, value: true },
|
|
minLength: { value: 10, message: FormErrorMessages.minLength(10) },
|
|
maxLength: { value: 20, message: FormErrorMessages.maxLength(20) },
|
|
pattern: {
|
|
value: REGEX.PHONE,
|
|
message: FormErrorMessages.invalidPattern,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "type",
|
|
render: ({ register, errors }) => (
|
|
<Select<ICreateCompanyCredentials>
|
|
{...register("type", {
|
|
required: { message: FormErrorMessages.required, value: true },
|
|
})}
|
|
errors={errors}
|
|
name="type"
|
|
label="Company type"
|
|
required
|
|
items={[
|
|
{ value: "private", label: "Private" },
|
|
{ value: "public", label: "Public" },
|
|
{ value: "government", label: "Government" },
|
|
{ value: "ngo", label: "NGO" },
|
|
{ value: "startup", label: "Startup" },
|
|
]}
|
|
defaultValue="Private"
|
|
prefixIcon={<GlobeIcon />}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "industry",
|
|
label: "Industry",
|
|
type: "text",
|
|
placeholder: "e.g. construction, software, logistics",
|
|
rules: {
|
|
minLength: { value: 2, message: FormErrorMessages.minLength(2) },
|
|
maxLength: { value: 100, message: FormErrorMessages.maxLength(100) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "registration_number",
|
|
label: "Registration number",
|
|
type: "text",
|
|
placeholder: "Registry or license number",
|
|
rules: {
|
|
minLength: { value: 5, message: FormErrorMessages.minLength(5) },
|
|
maxLength: { value: 50, message: FormErrorMessages.maxLength(50) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "tax_id",
|
|
label: "Tax id",
|
|
type: "text",
|
|
placeholder: "National tax identification number",
|
|
rules: {
|
|
minLength: { value: 5, message: FormErrorMessages.minLength(5) },
|
|
maxLength: { value: 50, message: FormErrorMessages.maxLength(50) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "website",
|
|
label: "Website",
|
|
type: "text",
|
|
placeholder: "https://www.example.com",
|
|
required: true,
|
|
className: "sm:col-span-2",
|
|
rules: {
|
|
required: { message: FormErrorMessages.required, value: true },
|
|
minLength: { value: 2, message: FormErrorMessages.minLength(2) },
|
|
maxLength: { value: 100, message: FormErrorMessages.maxLength(100) },
|
|
pattern: {
|
|
value: REGEX.URL,
|
|
message: FormErrorMessages.invalidPattern,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "description",
|
|
className: "sm:col-span-2",
|
|
render: ({ register, errors }) => (
|
|
<TextAreaGroup<ICreateCompanyCredentials>
|
|
label="Description"
|
|
{...register("description", {
|
|
minLength: {
|
|
value: 10,
|
|
message: FormErrorMessages.minLength(10),
|
|
},
|
|
maxLength: {
|
|
value: 1000,
|
|
message: FormErrorMessages.maxLength(1000),
|
|
},
|
|
})}
|
|
errors={errors}
|
|
name="description"
|
|
/>
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: businessInformationSectionId,
|
|
title: "Business information",
|
|
className: "gap-x-5 gap-y-5 sm:grid-cols-2 md:grid-cols-2",
|
|
fields: [
|
|
{
|
|
kind: "input",
|
|
name: "employee_count",
|
|
label: "Employee count",
|
|
type: "number",
|
|
rules: {
|
|
setValueAs: optionalNumber,
|
|
validate: optionalNumberRange({ min: 1, max: 100000, integer: true }),
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "annual_revenue",
|
|
label: "Annual revenue",
|
|
type: "number",
|
|
rules: {
|
|
setValueAs: optionalNumber,
|
|
validate: optionalNumberRange({ min: 0, max: 999999999999 }),
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "founded_year",
|
|
label: "Founded year",
|
|
type: "number",
|
|
className: "sm:col-span-2",
|
|
rules: {
|
|
setValueAs: optionalNumber,
|
|
validate: optionalNumberRange({
|
|
min: 1800,
|
|
max: 2100,
|
|
integer: true,
|
|
}),
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: settingsSectionId,
|
|
title: "Settings",
|
|
className: "gap-x-5 gap-y-5 sm:grid-cols-2 md:grid-cols-2",
|
|
fields: [
|
|
{
|
|
kind: "custom",
|
|
name: "language",
|
|
render: ({ register, errors }) => (
|
|
<Select<ICreateCompanyCredentials>
|
|
{...register("language")}
|
|
errors={errors}
|
|
name="language"
|
|
label="Language"
|
|
items={languageItems}
|
|
defaultValue="en"
|
|
prefixIcon={<GlobeIcon />}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "currency",
|
|
render: ({ register, errors }) => (
|
|
<Select<ICreateCompanyCredentials>
|
|
{...register("currency")}
|
|
errors={errors}
|
|
name="currency"
|
|
label="Currency"
|
|
items={currencyItems}
|
|
defaultValue="USD"
|
|
prefixIcon={<MoneyIcon />}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "timezone",
|
|
className: "sm:col-span-2",
|
|
render: ({ register, errors }) => (
|
|
<Select<ICreateCompanyCredentials>
|
|
{...register("timezone")}
|
|
errors={errors}
|
|
name="timezone"
|
|
label="Timezone"
|
|
items={timezoneItems}
|
|
value={watch("timezone") ?? ""}
|
|
placeholder="Select timezone"
|
|
searchable
|
|
searchPlaceholder="Search timezone..."
|
|
clearable
|
|
onClear={() => setValue("timezone", "")}
|
|
/>
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: addressSectionId,
|
|
title: "Address",
|
|
className: "gap-x-5 gap-y-5 sm:grid-cols-2 md:grid-cols-2",
|
|
fields: [
|
|
{
|
|
kind: "input",
|
|
name: "address.street",
|
|
label: "Street",
|
|
type: "text",
|
|
placeholder: "Building, street, suite or unit",
|
|
className: "sm:col-span-2",
|
|
rules: {
|
|
minLength: { value: 5, message: FormErrorMessages.minLength(5) },
|
|
maxLength: { value: 200, message: FormErrorMessages.maxLength(200) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "address.city",
|
|
label: "City",
|
|
type: "text",
|
|
placeholder: "City or town",
|
|
rules: {
|
|
minLength: { value: 2, message: FormErrorMessages.minLength(2) },
|
|
maxLength: { value: 100, message: FormErrorMessages.maxLength(100) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "address.state",
|
|
label: "State",
|
|
type: "text",
|
|
placeholder: "State, province, or region",
|
|
rules: {
|
|
minLength: { value: 2, message: FormErrorMessages.minLength(2) },
|
|
maxLength: { value: 100, message: FormErrorMessages.maxLength(100) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "address.postal_code",
|
|
label: "Postal code",
|
|
type: "text",
|
|
placeholder: "Postal or ZIP code",
|
|
rules: {
|
|
minLength: { value: 3, message: FormErrorMessages.minLength(3) },
|
|
maxLength: { value: 20, message: FormErrorMessages.maxLength(20) },
|
|
},
|
|
},
|
|
{
|
|
kind: "input",
|
|
name: "address.country",
|
|
label: "Country",
|
|
type: "text",
|
|
placeholder: "Full country name",
|
|
rules: {
|
|
minLength: { value: 2, message: FormErrorMessages.minLength(2) },
|
|
maxLength: { value: 100, message: FormErrorMessages.maxLength(100) },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: tagsSectionId,
|
|
title: "Tags",
|
|
className: "gap-x-5 gap-y-5 sm:grid-cols-2 md:grid-cols-2",
|
|
fields: [
|
|
{
|
|
kind: "custom",
|
|
name: "tags.keywords",
|
|
render: ({ register }) => (
|
|
<TagInput<ICreateCompanyCredentials>
|
|
{...register("tags.keywords")}
|
|
name="tags.keywords"
|
|
label="Keywords"
|
|
placeholder=""
|
|
register={register}
|
|
setValue={setValue}
|
|
watch={watch}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "tags.categories",
|
|
render: ({ register }) => (
|
|
<MultiSelect<ICreateCompanyCredentials>
|
|
{...register("tags.categories")}
|
|
value={watch("tags.categories")}
|
|
name="tags.categories"
|
|
label="Categories"
|
|
items={categoryItems}
|
|
placeholder=""
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "tags.cpv_codes",
|
|
render: ({ register }) => (
|
|
<TagInput<ICreateCompanyCredentials>
|
|
{...register("tags.cpv_codes")}
|
|
label="CPV codes"
|
|
name="tags.cpv_codes"
|
|
shouldAddWithSpace
|
|
watch={watch}
|
|
setValue={setValue}
|
|
placeholder=""
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "tags.certifications",
|
|
render: ({ register }) => (
|
|
<TagInput<ICreateCompanyCredentials>
|
|
{...register("tags.certifications")}
|
|
label="Certifications"
|
|
name="tags.certifications"
|
|
watch={watch}
|
|
setValue={setValue}
|
|
placeholder=""
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
kind: "custom",
|
|
name: "tags.specializations",
|
|
className: "sm:col-span-2",
|
|
render: ({ register, error }) => (
|
|
<>
|
|
<TagInput<ICreateCompanyCredentials>
|
|
{...register("tags.specializations")}
|
|
label="Specializations"
|
|
name="tags.specializations"
|
|
watch={watch}
|
|
setValue={setValue}
|
|
placeholder=""
|
|
/>
|
|
{error ? (
|
|
<p className="mt-1.5 text-sm font-medium text-error">{error}</p>
|
|
) : null}
|
|
</>
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: documentsSectionId,
|
|
title: "Documents",
|
|
rootClassName: "lg:col-span-2",
|
|
className: "md:grid-cols-1",
|
|
fields: [
|
|
{
|
|
kind: "custom",
|
|
name: "document_file_ids",
|
|
render: () => (
|
|
<CompanyDocuments
|
|
companyId={editMode ? id : undefined}
|
|
value={watch("document_file_ids") ?? []}
|
|
onChange={(ids) =>
|
|
setValue("document_file_ids", ids, {
|
|
shouldDirty: true,
|
|
shouldTouch: true,
|
|
shouldValidate: true,
|
|
})
|
|
}
|
|
onRemovePersist={persistDocumentFileIds}
|
|
/>
|
|
),
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: linksSectionId,
|
|
title: "Links",
|
|
rootClassName: "lg:col-span-2",
|
|
className: "md:grid-cols-1",
|
|
fields: [
|
|
{
|
|
kind: "custom",
|
|
name: "links",
|
|
render: ({ control, errors, register }) => (
|
|
<CompanyLinks control={control} errors={errors} register={register} />
|
|
),
|
|
},
|
|
],
|
|
},
|
|
];
|