Skip to content

Commit 3034549

Browse files
1682 Adds initial version of back functionality, including cache based on previous steps input
1 parent c6bb754 commit 3034549

File tree

4 files changed

+55
-6
lines changed

4 files changed

+55
-6
lines changed

frontend/apps/example/src/app/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export default function Home() {
9494
alert('Form cancelled');
9595
}}
9696
config={{
97+
allowUntouchedSubmit: true,
9798
apiProvider: pydanticFormApiProvider,
9899
labelProvider: pydanticLabelProvider,
99100
customDataProvider: pydanticCustomDataProvider,

frontend/packages/pydantic-forms/src/components/form/Footer.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const Footer = () => {
1212
resetForm,
1313
rhf,
1414
onCancel,
15+
onPrevious,
1516
cancelButton,
1617
resetButtonAlternative,
1718
sendLabel,
@@ -23,6 +24,15 @@ const Footer = () => {
2324
<div style={{ height: '200px' }}>
2425
{footerComponent && <div>{footerComponent}</div>}{' '}
2526
<div>
27+
{rhf.formState.isValid &&
28+
!allowUntouchedSubmit &&
29+
!rhf.formState.isDirty && (
30+
<div>Het formulier is nog niet aangepast</div>
31+
)}
32+
33+
<button type="button" onClick={() => onPrevious?.()} style={{ padding: '4px' }}>
34+
Back
35+
</button>
2636
{resetButtonAlternative ?? (
2737
<button
2838
type="button"
@@ -36,12 +46,6 @@ const Footer = () => {
3646
</button>
3747
)}
3848

39-
{rhf.formState.isValid &&
40-
!allowUntouchedSubmit &&
41-
!rhf.formState.isDirty && (
42-
<div>Het formulier is nog niet aangepast</div>
43-
)}
44-
4549
{!!onCancel &&
4650
(cancelButton ?? (
4751
<button type="button" onClick={onCancel}>

frontend/packages/pydantic-forms/src/core/PydanticFormContextProvider.tsx

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,40 @@ function PydanticFormContextProvider({
8888
cancelButton,
8989
} = config;
9090

91+
const [formInputHistory, setFormInputHistory] = useState(new Map<string, object>());
9192
const [formInputData, setFormInputData] = useState<object[]>([]);
9293

94+
const getHashForArray = async (array: object[]) => {
95+
const arrayString = JSON.stringify(array);
96+
const arrayBuffer = new TextEncoder().encode(arrayString);
97+
98+
const digest = await crypto.subtle.digest('SHA-256', arrayBuffer)
99+
const hashHex = Array.from(new Uint8Array(digest), b => b.toString(16).padStart(2, '0')).join('');
100+
101+
return hashHex
102+
}
103+
104+
const updateHistory = async (formInput: object, previousSteps: object[]) => {
105+
const hashOfPreviousSteps = await getHashForArray(previousSteps);
106+
107+
console.log('Saving combination', {hashOfPreviousSteps, formInput})
108+
109+
setFormInputHistory((prevState) => prevState.set(hashOfPreviousSteps, formInput));
110+
111+
}
112+
113+
const goToPreviousStep = (formInput: object) => {
114+
console.log('Going back one step');
115+
setFormInputData((prevState) => {
116+
updateHistory(formInput, prevState)
117+
return prevState.slice(0, -1);
118+
})
119+
}
120+
93121
const addFormInputData = (formInput: object) => {
94122
setFormInputData((currentInputs) => {
123+
console.log('addFormInputData', { formInput, currentInputs });
124+
updateHistory(formInput, currentInputs)
95125
return [...currentInputs, formInput];
96126
});
97127
};
@@ -233,6 +263,18 @@ function PydanticFormContextProvider({
233263
useEffect(() => {
234264
// this makes sure default values are set.
235265
resetFormData();
266+
getHashForArray(formInputData).then(hash => {
267+
const currentStepFromHistory = formInputHistory.get(hash);
268+
269+
if(currentStepFromHistory) {
270+
console.log('Found history', {currentStepFromHistory})
271+
272+
Object.entries(currentStepFromHistory).forEach(([fieldName, fieldValue]) => {
273+
console.log('forEach loop:', {fieldName, fieldValue})
274+
rhf.setValue(fieldName, fieldValue, { shouldDirty: true, shouldTouch: true, shouldValidate: true });
275+
})
276+
}
277+
})
236278
}, [resetFormData]);
237279

238280
// this is to show an error whenever there is an unexpected error from the backend
@@ -326,6 +368,7 @@ function PydanticFormContextProvider({
326368
headerComponent,
327369
footerComponent,
328370
loadingComponent,
371+
onPrevious: () => goToPreviousStep(rhf?.getValues()),
329372
onCancel,
330373
title,
331374
sendLabel,

frontend/packages/pydantic-forms/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export interface PydanticFormContextProps {
5555
pydanticFormSchema?: PydanticFormSchema;
5656
title?: string | boolean;
5757
sendLabel?: string;
58+
onPrevious?: () => void;
5859
onCancel?: () => void;
5960
cancelButton?: React.ReactNode;
6061
resetButtonAlternative?: React.ReactNode;

0 commit comments

Comments
 (0)