sendou.ink/app/components/form/TextArrayFormField.tsx
Kalle 9312fad90f
Tournament organization page (#1811)
* Initial

* Calendar initial

* Extract EventCalendar

* Events list initial

* Winners

* SQL fixes

* List events by series

* Leaderboards

* Series leaderboard

* Own entry peek

* Edit page skeleton

* RHF initial test

* RHF stuff

* Form etc. progress

* Fix tournament series description

* Fix tabs layout

* Fix socials insert

* Check for not removing admin

* Adding series

* TODOs

* Allow updating org with no series

* FormFieldset

* Allow series without events

* TextAreaFormfield accepting array syntax

* Input form array field

* ToggleFormField

* SelectFormField

* UserSearchFormField

* Fetch badgeOptions

* Badge editing

* Progress

* Use native preventScrollReset

* Rename func

* Fix sticky scroll

* Fix translation

* i18n errors

* handle,meta in edit

* Add ref to user search

* TODOs

* Done
2024-07-25 23:06:29 +03:00

73 lines
1.7 KiB
TypeScript

import { useFieldArray, useFormContext } from "react-hook-form";
import type { z } from "zod";
import { FormMessage } from "~/components/FormMessage";
import { Label } from "~/components/Label";
import { AddFieldButton } from "./AddFieldButton";
import { RemoveFieldButton } from "./RemoveFieldButton";
export function TextArrayFormField<T extends z.ZodTypeAny>({
label,
name,
defaultFieldValue,
bottomText,
}: {
label: string;
name: keyof z.infer<T> & string;
defaultFieldValue: string;
bottomText?: string;
}) {
const {
register,
formState: { errors },
clearErrors,
} = useFormContext();
const { fields, append, remove } = useFieldArray({
name,
});
const rootError = errors[name]?.root;
return (
<div>
<Label>{label}</Label>
<div className="stack md">
{fields.map((field, index) => {
// @ts-expect-error
const error = errors[name]?.[index]?.value;
return (
<div key={field.id}>
<div className="stack horizontal md">
<input {...register(`${name}.${index}.value`)} />
{fields.length > 1 ? (
<RemoveFieldButton
onClick={() => {
remove(index);
clearErrors(`${name}.root`);
}}
/>
) : null}
</div>
{error && (
<FormMessage type="error">
{error.message as string}
</FormMessage>
)}
</div>
);
})}
<AddFieldButton
// @ts-expect-error
onClick={() => append({ value: defaultFieldValue })}
/>
{rootError && (
<FormMessage type="error">{rootError.message as string}</FormMessage>
)}
{bottomText && !rootError ? (
<FormMessage type="info">{bottomText}</FormMessage>
) : null}
</div>
</div>
);
}