import { useState } from '@wordpress/element';
|
import { Button, Panel, PanelBody } from '@wordpress/components';
|
import Fields from '../Fields';
|
|
const templateLabel = (template, row, fields) => {
|
if (!template?.includes('{{')) return template;
|
return template.replace(/{{(.*?)}}/g, (_, name) => {
|
const val = row[name];
|
if (val === undefined) return '';
|
return Array.isArray(val) ? val.join(', ') : String(val);
|
});
|
};
|
|
const emptyRow = (fields) =>
|
Object.fromEntries(Object.entries(fields || {}).map(([name, f]) => [name, f.default ?? '']));
|
|
const RepeaterField = ({ field, value, onChange, meta }) => {
|
const rows = Array.isArray(value) ? value : [];
|
const subFields = field.fields || {};
|
const [openIndex, setOpenIndex] = useState(null);
|
|
const updateRow = (index, name, val) => {
|
const next = rows.map((row, i) => (i === index ? { ...row, [name]: val } : row));
|
onChange(next);
|
};
|
|
const addRow = () => onChange([...rows, emptyRow(subFields)]);
|
const removeRow = (index) => onChange(rows.filter((_, i) => i !== index));
|
|
return (
|
<div className="jvb-repeater-field" id={field.name}>
|
<p className="jvb-field-label">{field.label}</p>
|
|
<Panel>
|
{rows.map((row, index) => (
|
<PanelBody
|
key={index}
|
title={templateLabel(field.row_label, row, subFields) || `Row ${index + 1}`}
|
initialOpen={openIndex === index}
|
onToggle={() => setOpenIndex(openIndex === index ? null : index)}
|
>
|
{Object.entries(subFields).map(([name, subField]) => (
|
<Fields
|
key={name}
|
field={{ ...subField, name }}
|
value={row[name]}
|
onChange={(val) => updateRow(index, name, val)}
|
meta={ meta }
|
/>
|
))}
|
<Button variant="link" isDestructive onClick={() => removeRow(index)}>
|
Remove
|
</Button>
|
</PanelBody>
|
))}
|
</Panel>
|
|
<Button variant="secondary" onClick={addRow}>
|
{field.add_label || 'Add Row'}
|
</Button>
|
</div>
|
);
|
};
|
|
export default RepeaterField;
|