feat(form): enhance form functionality and API integration

* Refactor key handling to use uniqueKeyField
* Add reset functionality to clear dirty state after save
* Introduce new API call specifications for REST and resolve
* Implement predefined wrappers for dialogs and popovers
* Update todo list to reflect completed tasks
This commit is contained in:
2026-01-14 21:51:39 +02:00
parent e6507f44af
commit cd2f6db880
11 changed files with 462 additions and 74 deletions

View File

@@ -2,14 +2,38 @@ import { Button, Drawer, Group, Paper, Select, Stack, Switch } from '@mantine/co
import { useRef, useState } from 'react';
import { Controller } from 'react-hook-form';
import type { FormerProps, FormerRef } from '../Former.types';
import type { FormerAPICallType, FormerProps, FormerRef } from '../Former.types';
import { Former } from '../Former';
import { ApiFormData } from './apiFormData';
import { FormerRestHeadSpecAPI } from '../FormerRestHeadSpecAPI';
import { FormerDialog, FormerModel } from '../FormerWrappers';
const StubAPI = (): FormerAPICallType => (mode, request, value) => {
console.log('API Call', mode, request, value);
if (mode === 'read') {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ a: 'Another Value', test: 'Loaded Value' });
}, 1000);
});
}
return new Promise((resolve) => {
setTimeout(() => {
resolve(value || {});
}, 1000);
});
};
export const FormTest = () => {
const [request, setRequest] = useState<null | string>('insert');
const [wrapped, setWrapped] = useState(false);
const [disableHTML, setDisableHTML] = useState(false);
const [apiOptions, setApiOptions] = useState({
url: '',
authToken: '',
type: '',
});
const [layout, setLayout] = useState({
buttonOnTop: false,
title: 'Custom Former Title',
@@ -17,8 +41,8 @@ export const FormTest = () => {
} as FormerProps['layout']);
const [open, setOpen] = useState(false);
const [formData, setFormData] = useState({ a: 99 });
console.log('formData', formData);
const [formData, setFormData] = useState({ a: 99, rid_usernote: 3047 });
//console.log('formData render', formData);
const ref = useRef<FormerRef>(null);
return (
@@ -44,6 +68,13 @@ export const FormTest = () => {
label="Button On Top"
onChange={(event) => setLayout({ ...layout, buttonOnTop: event.currentTarget.checked })}
/>
<Switch
checked={apiOptions.type === 'api'}
label="Use API"
onChange={(event) =>
setApiOptions({ ...apiOptions, type: event.currentTarget.checked ? 'api' : '' })
}
/>
</Group>
<Button onClick={() => setOpen(true)}>Open Former Drawer</Button>
<Group>
@@ -65,25 +96,21 @@ export const FormTest = () => {
Test Show/Hide
</Button>
</Group>
<FormerModel opened={open} onClose={() => setOpen(false)} former={{ request: 'insert' }}>
<div>Test</div>
</FormerModel>
<Former
//wrapper={(children, getState) => <div>{children}</div>}
//opened={true}
apiKeyField="a"
onAPICall={(mode, request, value) => {
console.log('API Call', mode, request, value);
if (mode === 'read') {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ a: 'Another Value', test: 'Loaded Value' });
}, 1000);
});
}
return new Promise((resolve) => {
setTimeout(() => {
resolve(value || {});
}, 1000);
});
}}
uniqueKeyField="rid_usernote"
onAPICall={
apiOptions.type === 'api'
? FormerRestHeadSpecAPI({
authToken: apiOptions.authToken,
url: apiOptions.url,
})
: StubAPI()
}
disableHTMlForm={disableHTML}
onChange={setFormData}
onClose={() => setOpen(false)}
@@ -94,29 +121,28 @@ export const FormTest = () => {
useFormProps={{ criteriaMode: 'all', shouldUseNativeValidation: false }}
values={formData}
layout={layout}
wrapper={
wrapped
? (children, opened, onClose, _onOpen, getState) => {
const values = getState('values');
return (
<Drawer
h={'100%'}
onClose={() => onClose?.()}
opened={opened ?? false}
title={`Drawer Former - Current A Value: ${values?.a}`}
w={'50%'}
>
<Paper h="100%" shadow="sm" w="100%" withBorder>
{children}
<Button>Test Save</Button>
</Paper>
</Drawer>
);
}
: undefined
}
// wrapper={
// wrapped
// ? (children, opened, onClose, _onOpen, getState) => {
// const values = getState('values');
// return (
// <Drawer
// h={'100%'}
// onClose={() => onClose?.()}
// opened={opened ?? false}
// title={`Drawer Former - Current A Value: ${values?.a}`}
// w={'50%'}
// >
// <Paper h="100%" shadow="sm" w="100%" withBorder>
// {children}
// </Paper>
// </Drawer>
// );
// }
// : undefined
// }
>
<Stack h="1200px">
<Stack pb={'400px'}>
<Stack>
<Controller
name="test"
@@ -127,6 +153,11 @@ export const FormTest = () => {
render={({ field }) => <input type="text" {...field} placeholder="B" />}
rules={{ required: 'Field is required' }}
/>
<Controller
name="note"
render={({ field }) => <input type="text" {...field} placeholder="note" />}
rules={{ required: 'Field is required' }}
/>
</Stack>
{!disableHTML && (
<Stack>
@@ -136,6 +167,14 @@ export const FormTest = () => {
)}
</Stack>
</Former>
{apiOptions.type === 'api' && (
<ApiFormData
values={apiOptions}
onChange={(values) => {
setApiOptions({ ...apiOptions, ...values });
}}
/>
)}
</Stack>
);
};