generic src for react admin

This commit is contained in:
2026-04-01 14:22:14 +05:30
parent 4d06859cb0
commit 14dcd19b17
13 changed files with 1137 additions and 7 deletions

View File

@@ -0,0 +1,163 @@
import * as React from 'react';
import {
Box,
TextField,
Button,
FormControl,
InputLabel,
Select,
MenuItem,
FormControlLabel,
Checkbox,
Typography,
Divider,
} from '@mui/material';
import { ResourceConfig, ResourceField } from '../types/config';
interface GenericFormProps {
config: ResourceConfig;
initialData?: any;
onSave: (data: any) => Promise<void>;
onCancel: () => void;
loading?: boolean;
}
export default function GenericForm({
config,
initialData = {},
onSave,
onCancel,
loading,
}: GenericFormProps) {
const [formData, setFormData] = React.useState(initialData);
const handleChange = (key: string, value: any) => {
setFormData((prev: any) => ({ ...prev, [key]: value }));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
onSave(formData);
};
return (
<Box component="form" onSubmit={handleSubmit} sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
<Typography variant="h5">
{initialData[config.primaryKey] ? `Edit ${config.label}` : `New ${config.label}`}
</Typography>
<Divider />
{Object.entries(config.fields).map(([key, field]) => (
<FormField
key={key}
name={key}
field={field}
value={formData[key]}
onChange={(val) => handleChange(key, val)}
disabled={field.readOnly}
/>
))}
<Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 2, mt: 4 }}>
<Button variant="outlined" onClick={onCancel} disabled={loading}>
Cancel
</Button>
<Button variant="contained" type="submit" loading={loading} disabled={loading}>
Save {config.label}
</Button>
</Box>
</Box>
);
}
function FormField({ name, field, value, onChange, disabled }: any) {
const label = field.label;
if (field.type === 'boolean') {
return (
<FormControlLabel
control={
<Checkbox
checked={!!value}
onChange={(e) => onChange(e.target.checked)}
disabled={disabled}
/>
}
label={label}
/>
);
}
if (field.type === 'enum' && field.options) {
return (
<FormControl fullWidth>
<InputLabel>{label}</InputLabel>
<Select
value={value || ''}
label={label}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
>
{field.options.map((opt: string) => (
<MenuItem key={opt} value={opt}>
{opt}
</MenuItem>
))}
</Select>
</FormControl>
);
}
if (field.type === 'markdown' || field.type === 'string') {
return (
<TextField
fullWidth
label={label}
value={value || ''}
multiline={field.type === 'markdown'}
rows={field.type === 'markdown' ? 4 : 1}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
required={field.required}
/>
);
}
if (field.type === 'number') {
return (
<TextField
fullWidth
label={label}
type="number"
value={value || 0}
onChange={(e) => onChange(Number(e.target.value))}
disabled={disabled}
required={field.required}
/>
);
}
if (field.type === 'date') {
return (
<TextField
fullWidth
label={label}
type="date"
InputLabelProps={{ shrink: true }}
value={value ? new Date(value).toISOString().split('T')[0] : ''}
onChange={(e) => onChange(e.target.value)}
disabled={disabled}
required={field.required}
/>
);
}
return (
<TextField
fullWidth
label={label}
value={JSON.stringify(value)}
disabled
/>
);
}