import type { ReactNode } from "react";
import { useEffect, useState } from "react";
import type { InferredTypeMap } from "ra-core";
import {
EditBase,
InferredElement,
useResourceContext,
useEditContext,
getElementsFromRecords,
} from "ra-core";
import { capitalize, singularize } from "inflection";
import { EditView } from "@/components/admin/edit";
import { SimpleForm } from "@/components/admin/simple-form";
import { TextInput } from "@/components/admin/text-input";
import { BooleanInput } from "@/components/admin/boolean-input";
import { ReferenceInput } from "@/components/admin/reference-input";
import { AutocompleteInput } from "@/components/admin/autocomplete-input";
import { ReferenceArrayInput } from "@/components/admin/reference-array-input";
/**
* An edit page that automatically generates a form from your data.
*
* Inspects the record to infer field types and automatically creates appropriate inputs.
* Useful for rapid prototyping. Logs generated code to console.
*
* @see {@link https://marmelab.com/shadcn-admin-kit/docs/edit/#scaffolding-an-edit-page EditGuesser documentation}
*
* @example
* import { Admin, EditGuesser } from '@/components/admin';
* import { Resource } from 'ra-core';
* import dataProvider from './dataProvider';
*
* const App = () => (
*
* ...
*
*
* );
*/
export const EditGuesser = (props: { enableLog?: boolean }) => {
return (
);
};
const EditViewGuesser = (props: { enableLog?: boolean }) => {
const resource = useResourceContext();
if (!resource) {
throw new Error(`Cannot use outside of a ResourceContext`);
}
const { record } = useEditContext();
const [child, setChild] = useState(null);
const { enableLog = process.env.NODE_ENV === "development", ...rest } = props;
useEffect(() => {
setChild(null);
}, [resource]);
useEffect(() => {
if (record && !child) {
const inferredElements = getElementsFromRecords([record], editFieldTypes);
const inferredChild = new InferredElement(
editFieldTypes.form,
null,
inferredElements,
);
setChild(inferredChild.getElement());
if (!enableLog) return;
const representation = inferredChild.getRepresentation();
const components = ["Edit"]
.concat(
Array.from(
new Set(
Array.from(representation.matchAll(/<([^/\s>]+)/g))
.map((match) => match[1])
.filter((component) => component !== "span"),
),
),
)
.sort();
// eslint-disable-next-line no-console
console.log(
`Guessed Edit:
${components
.map(
(component) =>
`import { ${component} } from "@/components/admin/${kebabCase(
component,
)}";`,
)
.join("\n")}
export const ${capitalize(singularize(resource))}Edit = () => (
${representation}
);`,
);
}
}, [record, child, resource, enableLog]);
return {child};
};
const editFieldTypes: InferredTypeMap = {
form: {
component: (props: any) => ,
representation: (
_props: any,
children: { getRepresentation: () => string }[],
) => `
${children
.map((child) => ` ${child.getRepresentation()}`)
.join("\n")}
`,
},
reference: {
component: (props: any) => (
),
representation: (props: any) =>
`
`,
},
referenceArray: {
component: (props: any) => ,
representation: (props: any) =>
``,
},
boolean: {
component: (props: any) => ,
representation: (props: any) => ``,
},
string: {
component: (props: any) => ,
representation: (props: any) => ``,
},
};
const kebabCase = (name: string) => {
return name
.replace(/([a-z])([A-Z])/g, "$1-$2")
.replace(/([A-Z])([A-Z][a-z])/g, "$1-$2")
.toLowerCase();
};