feat: implement OptionsInput component for handling select field options
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
|
||||
import Field from './ui/Field';
|
||||
import Input from './ui/Input';
|
||||
@@ -13,6 +14,50 @@ const TYPE_OPTIONS = [
|
||||
|
||||
const MAX_FIELDS = 20;
|
||||
|
||||
const parseOptions = (raw: string) =>
|
||||
raw.split(/[,،]/).map((o) => o.trim()).filter((o) => o !== '');
|
||||
|
||||
/**
|
||||
* ورودی متنی گزینههای فیلد `select`.
|
||||
*
|
||||
* متن خام را در state خودش نگه میدارد و آرایه را فقط موقع emit میسازد. اگر مقدار
|
||||
* input مستقیم از آرایه ساخته میشد، کاما و فاصلهٔ انتهایی در همان keystroke حذف
|
||||
* میشد (چون عنصر خالی filter میشود) و کاربر اصلاً نمیتوانست کاما تایپ کند.
|
||||
*/
|
||||
function OptionsInput({ id, options, disabled, onChange }: {
|
||||
id: string;
|
||||
options: TreatmentFormField['options'];
|
||||
disabled?: boolean;
|
||||
onChange: (options: string[]) => void;
|
||||
}) {
|
||||
const [draft, setDraft] = useState(() => (options ?? []).join(', '));
|
||||
const emitted = useRef(options);
|
||||
|
||||
// فقط وقتی آرایه از بیرون عوض شود (نه با تایپ خودِ کاربر) متن را همگام کن.
|
||||
useEffect(() => {
|
||||
if (options !== emitted.current) {
|
||||
emitted.current = options;
|
||||
setDraft((options ?? []).join(', '));
|
||||
}
|
||||
}, [options]);
|
||||
|
||||
return (
|
||||
<Input
|
||||
id={id}
|
||||
value={draft}
|
||||
disabled={disabled}
|
||||
dir="ltr"
|
||||
placeholder="7, 8, 9, 10, 12, 14, 16, 18"
|
||||
onChange={(e) => {
|
||||
setDraft(e.target.value);
|
||||
const next = parseOptions(e.target.value);
|
||||
emitted.current = next;
|
||||
onChange(next);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* فرمی که اپراتور بعد از درمانِ هر ناحیه با این نوع منبع پر میکند.
|
||||
*
|
||||
@@ -77,18 +122,11 @@ export default function FieldSchemaEditor({ value, onChange, disabled }: {
|
||||
|
||||
{field.type === 'select' && (
|
||||
<Field label="گزینهها (با کاما جدا کنید)" htmlFor={`fs-options-${index}`}>
|
||||
<Input
|
||||
<OptionsInput
|
||||
id={`fs-options-${index}`}
|
||||
value={(field.options ?? []).join('، ')}
|
||||
options={field.options}
|
||||
disabled={disabled}
|
||||
dir="ltr"
|
||||
placeholder="7, 8, 9, 10, 12, 14, 16, 18"
|
||||
onChange={(e) => patch(index, {
|
||||
options: e.target.value
|
||||
.split(/[,،]/)
|
||||
.map((o) => o.trim())
|
||||
.filter((o) => o !== ''),
|
||||
})}
|
||||
onChange={(options) => patch(index, { options })}
|
||||
/>
|
||||
</Field>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user