@toolpad/core
Version:
Dashboard framework powered by Material UI.
178 lines (177 loc) • 6.01 kB
JavaScript
'use client';
import * as React from 'react';
import PropTypes from 'prop-types';
import invariant from 'invariant';
import { useNotifications } from "../useNotifications/index.js";
import { CrudContext } from "../shared/context.js";
import { useLocaleText } from "../AppProvider/LocalizationProvider.js";
import { CrudForm } from "./CrudForm.js";
import { DataSourceCache } from "./cache.js";
import { useCachedDataSource } from "./useCachedDataSource.js";
import { CRUD_DEFAULT_LOCALE_TEXT } from "./localeText.js";
import { jsx as _jsx } from "react/jsx-runtime";
/**
*
* Demos:
*
* - [CRUD](https://mui.com/toolpad/core/react-crud/)
*
* API:
*
* - [Create API](https://mui.com/toolpad/core/api/create)
*/
function Create(props) {
const {
initialValues = {},
onSubmitSuccess,
resetOnSubmit = false,
dataSourceCache,
localeText: propsLocaleText
} = props;
const globalLocaleText = useLocaleText();
const localeText = {
...CRUD_DEFAULT_LOCALE_TEXT,
...globalLocaleText,
...propsLocaleText
};
const crudContext = React.useContext(CrudContext);
const dataSource = props.dataSource ?? crudContext.dataSource;
const notifications = useNotifications();
invariant(dataSource, 'No data source found.');
const cache = React.useMemo(() => {
const manualCache = dataSourceCache ?? crudContext.dataSourceCache;
return typeof manualCache !== 'undefined' ? manualCache : new DataSourceCache();
}, [crudContext.dataSourceCache, dataSourceCache]);
const cachedDataSource = useCachedDataSource(dataSource, cache);
const {
fields,
createOne,
validate
} = cachedDataSource;
const [formState, setFormState] = React.useState(() => ({
values: {
...Object.fromEntries(fields.filter(({
field
}) => field !== 'id').map(({
field,
type
}) => [field, type === 'boolean' ? initialValues[field] ?? false : initialValues[field]])),
...initialValues
},
errors: {}
}));
const formValues = formState.values;
const formErrors = formState.errors;
const setFormValues = React.useCallback(newFormValues => {
setFormState(previousState => ({
...previousState,
values: newFormValues
}));
}, []);
const setFormErrors = React.useCallback(newFormErrors => {
setFormState(previousState => ({
...previousState,
errors: newFormErrors
}));
}, []);
const handleFormFieldChange = React.useCallback((name, value) => {
const validateField = async values => {
if (validate) {
const {
issues
} = await validate(values);
setFormErrors({
...formErrors,
[name]: issues?.find(issue => issue.path?.[0] === name)?.message
});
}
};
const newFormValues = {
...formValues,
[name]: value
};
setFormValues(newFormValues);
validateField(newFormValues);
}, [formErrors, formValues, setFormErrors, setFormValues, validate]);
const handleFormReset = React.useCallback(() => {
setFormValues(initialValues);
}, [initialValues, setFormValues]);
const handleFormSubmit = React.useCallback(async () => {
if (validate) {
const {
issues
} = await validate(formValues);
if (issues && issues.length > 0) {
setFormErrors(Object.fromEntries(issues.map(issue => [issue.path?.[0], issue.message])));
throw new Error('Form validation failed');
}
}
setFormErrors({});
try {
await createOne(formValues);
notifications.show(localeText.createSuccessMessage, {
severity: 'success',
autoHideDuration: 3000
});
if (onSubmitSuccess) {
await onSubmitSuccess(formValues);
}
if (resetOnSubmit) {
handleFormReset();
}
} catch (createError) {
notifications.show(`${localeText.createErrorMessage} ${createError.message}`, {
severity: 'error',
autoHideDuration: 3000
});
throw createError;
}
}, [createOne, formValues, handleFormReset, localeText.createErrorMessage, localeText.createSuccessMessage, notifications, onSubmitSuccess, resetOnSubmit, setFormErrors, validate]);
return /*#__PURE__*/_jsx(CrudForm, {
dataSource: dataSource,
formState: formState,
onFieldChange: handleFormFieldChange,
onSubmit: handleFormSubmit,
onReset: handleFormReset,
submitButtonLabel: localeText.createLabel
});
}
process.env.NODE_ENV !== "production" ? Create.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
/**
* Server-side [data source](https://mui.com/toolpad/core/react-crud/#data-sources).
*/
dataSource: PropTypes.object,
/**
* [Cache](https://mui.com/toolpad/core/react-crud/#data-caching) for the data source.
*/
dataSourceCache: PropTypes.shape({
cache: PropTypes.object.isRequired,
clear: PropTypes.func.isRequired,
get: PropTypes.func.isRequired,
set: PropTypes.func.isRequired,
ttl: PropTypes.number.isRequired
}),
/**
* Initial form values.
* @default {}
*/
initialValues: PropTypes.object,
/**
* Locale text for the component.
*/
localeText: PropTypes.object,
/**
* Callback fired when the form is successfully submitted.
*/
onSubmitSuccess: PropTypes.func,
/**
* Whether the form fields should reset after the form is submitted.
* @default false
*/
resetOnSubmit: PropTypes.bool
} : void 0;
export { Create };