114 lines
3.3 KiB
JavaScript
114 lines
3.3 KiB
JavaScript
function OptionLabel({ opt }) {
|
|
const images = Array.isArray(opt.images) ? opt.images : [];
|
|
return (
|
|
<span className="option-body">
|
|
{images.length > 0 ? (
|
|
<span className="option-images">
|
|
{images.map((src) => (
|
|
<img key={src} src={src} alt="" className="option-image" />
|
|
))}
|
|
</span>
|
|
) : null}
|
|
<span className="option-text">{opt.label}</span>
|
|
</span>
|
|
);
|
|
}
|
|
|
|
export default function QuestionField({ question, value, otherValue, onChange, onOtherChange }) {
|
|
if (!question) return null;
|
|
|
|
if (question.type === 'number') {
|
|
return (
|
|
<div className="field">
|
|
<label className="field-label" htmlFor={question.code}>
|
|
{question.label} <span className="req">*</span>
|
|
</label>
|
|
<input
|
|
id={question.code}
|
|
type="number"
|
|
min={question.min ?? 0}
|
|
max={question.max ?? 120}
|
|
className="field-input"
|
|
value={value ?? ''}
|
|
onChange={(e) => onChange(e.target.value === '' ? '' : Number(e.target.value))}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (question.type === 'single') {
|
|
return (
|
|
<fieldset className="field">
|
|
<legend className="field-label">
|
|
{question.label} <span className="req">*</span>
|
|
</legend>
|
|
<div className="option-list">
|
|
{question.options.map((opt) => (
|
|
<label key={opt.value} className="option-row">
|
|
<input
|
|
type="radio"
|
|
name={question.code}
|
|
value={opt.value}
|
|
checked={value === opt.value}
|
|
onChange={() => onChange(opt.value)}
|
|
/>
|
|
<OptionLabel opt={opt} />
|
|
</label>
|
|
))}
|
|
</div>
|
|
{question.otherField && value === 'others' && (
|
|
<input
|
|
className="field-input mt"
|
|
type="text"
|
|
placeholder="Please specify"
|
|
value={otherValue || ''}
|
|
onChange={(e) => onOtherChange(e.target.value)}
|
|
/>
|
|
)}
|
|
</fieldset>
|
|
);
|
|
}
|
|
|
|
const selected = Array.isArray(value) ? value : [];
|
|
|
|
return (
|
|
<fieldset className="field">
|
|
<legend className="field-label">
|
|
{question.label} <span className="req">*</span>
|
|
</legend>
|
|
<p className="field-hint">Multiple answers can be selected</p>
|
|
<div className="option-list">
|
|
{question.options.map((opt) => {
|
|
const checked = selected.includes(opt.value);
|
|
return (
|
|
<label key={opt.value} className="option-row">
|
|
<input
|
|
type="checkbox"
|
|
value={opt.value}
|
|
checked={checked}
|
|
onChange={() => {
|
|
if (checked) {
|
|
onChange(selected.filter((v) => v !== opt.value));
|
|
} else {
|
|
onChange([...selected, opt.value]);
|
|
}
|
|
}}
|
|
/>
|
|
<OptionLabel opt={opt} />
|
|
</label>
|
|
);
|
|
})}
|
|
</div>
|
|
{question.otherField && selected.includes('others') && (
|
|
<input
|
|
className="field-input mt"
|
|
type="text"
|
|
placeholder="Please specify"
|
|
value={otherValue || ''}
|
|
onChange={(e) => onOtherChange(e.target.value)}
|
|
/>
|
|
)}
|
|
</fieldset>
|
|
);
|
|
}
|