Files
oranguru/src/Former/Former.store.tsx
Hein e777e1fa3a chore(form): 🗑️ remove unused form components and types
* Refactor Former components to streamline functionality
* Update stories to reflect changes in form structure
2026-01-14 21:56:55 +02:00

213 lines
6.1 KiB
TypeScript

import { newUUID } from '@warkypublic/artemis-kit';
import { createSyncStore } from '@warkypublic/zustandsyncstore';
import { produce } from 'immer';
import type { FormerProps, FormerState } from './Former.types';
const { Provider: FormerProvider, useStore: useFormerStore } = createSyncStore<
FormerState<any> & Partial<FormerProps<any>>,
FormerProps<any>
>(
(set, get) => ({
getState: (key) => {
const current = get();
return current?.[key];
},
load: async (reset?: boolean) => {
try {
set({ loading: true });
const keyName = get()?.uniqueKeyField || 'id';
const keyValue = (get().values as any)?.[keyName] ?? (get().primeData as any)?.[keyName];
if (get().onAPICall && keyValue !== undefined) {
let data = await get().onAPICall!(
'read',
get().request || 'insert',
get().values,
keyValue
);
if (get().afterGet) {
data = await get().afterGet!({ ...data });
}
set({ loading: false, values: data });
get().onChange?.(data);
}
if (reset && get().getFormMethods) {
const formMethods = get().getFormMethods!();
formMethods.reset();
}
} catch (e) {
set({ error: (e as Error)?.message ?? e, loading: false });
}
set({ loading: false });
},
onChange: (values) => {
set({ values });
},
request: 'insert',
reset: async () => {
const state = get();
if (state.getFormMethods) {
if (state.request !== 'insert') {
await state.load(true);
}
const formMethods = state.getFormMethods!();
formMethods.reset({ ...state.values, ...state.primeData });
}
},
save: async (e?: React.BaseSyntheticEvent<object, any, any> | undefined) => {
try {
const keepOpen = get().keepOpen ?? false;
set({ loading: true });
if (get().getFormMethods) {
const formMethods = get().getFormMethods!();
let data = formMethods.getValues();
if (get().beforeSave) {
const newData = await get().beforeSave!(data);
data = newData;
}
let exit = false;
const handler = formMethods.handleSubmit(
(newdata) => {
data = newdata;
},
(errors) => {
set({ error: errors.root?.message || 'Validation errors', loading: false });
exit = true;
}
);
await handler(e);
//console.log('Former.store.tsx save called', success, e, data, get().getFormMethods);
if (exit) {
set({ loading: false });
return undefined;
}
if (get().request === 'delete' && !get().deleteConfirmed) {
const confirmed = (await get().onConfirmDelete?.(data)) ?? false;
if (!confirmed) {
set({ loading: false });
return undefined;
}
}
if (get().onAPICall) {
const keyName = get()?.uniqueKeyField || 'id';
const keyValue =
(get().values as any)?.[keyName] ?? (get().primeData as any)?.[keyName];
const savedData = await get().onAPICall!(
'mutate',
get().request || 'insert',
data,
keyValue
);
if (get().afterSave) {
await get().afterSave!(savedData);
}
set({ loading: false, values: savedData });
get().onChange?.(savedData);
formMethods.reset(savedData); //reset with saved data to clear dirty state
if (!keepOpen) {
get().onClose?.(savedData);
}
return savedData;
}
set({ loading: false, values: data });
formMethods.reset(data); //reset with saved data to clear dirty state
get().onChange?.(data);
if (!keepOpen) {
get().onClose?.(data);
}
return data;
}
} catch (e) {
set({ error: (e as Error)?.message ?? e, loading: false });
}
return undefined;
},
setRequest: (request) => {
set({ request });
},
setState: (key, value) => {
set(
produce((state) => {
state[key] = value;
})
);
},
setStateFN: (key, value) => {
const p = new Promise<void>((resolve, reject) => {
set(
produce((state) => {
if (typeof value === 'function') {
state[key] = (value as (value: unknown) => unknown)(state[key]);
} else {
reject(new Error(`Not a function ${value}`));
throw Error(`Not a function ${value}`);
}
})
);
resolve();
});
return p;
},
validate: async () => {
if (get().getFormMethods) {
const formMethods = get().getFormMethods!();
const isValid = await formMethods.trigger();
return isValid;
}
return true;
},
values: undefined,
}),
({ id, onClose, onConfirmDelete, primeData, request, useStoreApi, values }) => {
let _onConfirmDelete = onConfirmDelete;
if (!onConfirmDelete) {
_onConfirmDelete = async () => {
return confirm('Are you sure you want to delete this item?');
};
}
return {
id: !id ? newUUID() : id,
onClose: () => {
const dirty = useStoreApi.getState().dirty;
const setState = useStoreApi.getState().setState;
if (dirty) {
if (confirm('You have unsaved changes. Are you sure you want to close?')) {
if (onClose) {
onClose();
} else {
setState('opened', false);
}
}
} else {
if (onClose) {
onClose();
} else {
setState('opened', false);
}
}
},
onConfirmDelete: _onConfirmDelete,
primeData,
request: (request || 'insert').replace('change', 'update'),
values: { ...primeData, ...values },
};
}
);
export { FormerProvider };
export { useFormerStore };