60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { type ChangeEvent, type Dispatch, type SetStateAction } from "react";
|
|
import type { CreateRecipeFormDirtyEntries } from "../../pages/Create";
|
|
|
|
export interface RecipeCreateDropdownOption {
|
|
value: string;
|
|
name: string;
|
|
}
|
|
|
|
interface RecipeCreateFormDropdownProps {
|
|
label: string;
|
|
name: string;
|
|
desc: string;
|
|
required?: boolean;
|
|
valid: boolean;
|
|
value: string;
|
|
setValue: Dispatch<SetStateAction<string>>;
|
|
setDirty: Dispatch<SetStateAction<CreateRecipeFormDirtyEntries>>;
|
|
options: RecipeCreateDropdownOption[];
|
|
error: string;
|
|
parentClasses?: string;
|
|
classes: string;
|
|
};
|
|
|
|
export default function RecipeCreateDropdownInput({ label, name, desc, required = false, valid, value, setDirty, setValue, options, error, parentClasses = "", classes }: RecipeCreateFormDropdownProps) {
|
|
const handleChange = (e: ChangeEvent<HTMLSelectElement>) => {
|
|
setDirty(prev => ({ ...prev, [name]: true }));
|
|
setValue(e.target.value);
|
|
}
|
|
|
|
return (
|
|
<div className={`flex flex-col ${parentClasses}`}>
|
|
<label htmlFor={name} className="text-sm">
|
|
{label}
|
|
{required && <span className="text-red-500">*</span>}
|
|
</label>
|
|
<p className="text-xs pt-1 pb-2 text-gray-700">
|
|
{desc}
|
|
</p>
|
|
<select
|
|
className={`${!valid ? "border-red-500" : ""} ${classes}`}
|
|
name={name}
|
|
value={value}
|
|
onChange={handleChange}
|
|
required={required}
|
|
>
|
|
{options?.map(opt => (
|
|
<option key={opt.value} value={opt.value}>{opt.name}</option>
|
|
))}
|
|
</select>
|
|
{!valid && (
|
|
<p className="text-xs text-red-500 my-1">
|
|
{error}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
|