Files
jam-session-web/src/app/components/ConfigEditor.tsx
T
2025-01-13 12:37:08 +01:00

128 lines
5.1 KiB
TypeScript

import React from "react";
function ConfigEditor({config, setConfig}) {
const handleValueChange = (key, value) => {
setConfig((prev) => ({...prev, [key]: value}));
};
const handleAddToList = (key) => {
setConfig((prev) => ({
...prev,
[key]: [...prev[key], {}], // Add an empty object
}));
};
const handleRemoveFromList = (key, index) => {
setConfig((prev) => ({
...prev,
[key]: prev[key].filter((_, i) => i !== index),
}));
};
const handleNestedChange = (key, nestedKey, value) => {
setConfig((prev) => ({
...prev,
[key]: {...prev[key], [nestedKey]: value},
}));
};
const handleObjectInListChange = (listKey, index, fieldKey, value) => {
setConfig((prev) => ({
...prev,
[listKey]: prev[listKey].map((item, i) =>
i === index ? {...item, [fieldKey]: value} : item
),
}));
};
const renderField = (key, value) => {
if (Array.isArray(value)) {
// Render a list editor
return (
<div key={key}>
<label>{key}</label>
{value.map((item, index) => (
<div key={index} style={{marginLeft: "20px", marginBottom: "10px"}}>
{typeof item === "object" && item !== null ? (
// Render object fields
<div>
{Object.entries(item).map(([fieldKey, fieldValue]: [string, any]) => (
<div key={fieldKey}>
<label>{fieldKey}</label>
<input
type="text"
value={fieldValue}
onChange={(e) =>
handleObjectInListChange(
key,
index,
fieldKey,
e.target.value
)
}
/>
</div>
))}
<button
onClick={() => handleRemoveFromList(key, index)}
style={{marginTop: "5px"}}
>
Remove Object
</button>
</div>
) : (
// Render primitive values in the list
<div>
<input
type="text"
value={item}
onChange={(e) =>
handleValueChange(key, [
...value.slice(0, index),
e.target.value,
...value.slice(index + 1),
])
}
/>
<button onClick={() => handleRemoveFromList(key, index)}>
Remove
</button>
</div>
)}
</div>
))}
<button onClick={() => handleAddToList(key)}>Add Item</button>
</div>
);
} else if (typeof value === "object" && value !== null) {
// Render nested objects
return (
<div key={key}>
<label>{key}</label>
<div style={{marginLeft: "20px"}}>
{Object.entries(value).map(([nestedKey, nestedValue]) =>
renderField(nestedKey, nestedValue)
)}
</div>
</div>
);
} else {
// Render a single value editor
return (
<div key={key}>
<label>{key}</label>
<input
type="text"
value={value}
onChange={(e) => handleValueChange(key, e.target.value)}
/>
</div>
);
}
};
return <div>{Object.entries(config).map(([key, value]) => renderField(key, value))}</div>;
}
export default ConfigEditor;