saleor-dashboard/src/collections/components/CollectionCreatePage/form.tsx
Magdalena Markusik 3d636f4789
Exit dirty form (#1816)
* Add Exit form prompt component and change some minor styles in other components to match

* Add Exit form prompt provider

* Adjust generic form and useform hook to allow using exit form prompt provider

* Add exit form prompt provider to index

* wip

* Fix types

* Fix styling

* Fix types

* Revert warehouse details refactor

* Add handling of edge cases to exit prompt

* Refactor, add comments, fix some types

* Refactor after exit form dialog name change

* fix types

* Fixes after review

* Add default value for useform prop opts so the app doesn't crash

* Add missing category prop to getting initial data for category details form

* Add exit dialog to everywhere WIP (#1600)

* Add Exit form prompt component and change some minor styles in other components to match

* Add Exit form prompt provider

* Adjust generic form and useform hook to allow using exit form prompt provider

* Add exit form prompt provider to index

* wip

* Fix types

* Fix styling

* Fix types

* Revert warehouse details refactor

* Add handling of edge cases to exit prompt

* Refactor, add comments, fix some types

* Refactor after exit form dialog name change

* fix types

* Add CommonUseFormResultWithHandlers type for later use and refactor handleFormSubmit util

* Refactor login form not to use custom form since it doesn't need to

* Add exit form dialog to order refund page

* Add exit form dialog to order return page

* Add exit form dialog to order order settings  page

* Add exit form dialog to product variant page

* Add exit form dialog to product create page

* Add exit form dialog to product update page

* Add exit form dialog to product variant create page

* Fix confirm leave prop passing in generic Form

* Add util function to handle for submit to extract errors

* Add confirmLeave prop to generic forms

* Move handleChange for custom forms to useForm

* Add exit dialog to more forms

* Add extract mutation errors util function

* Add extracting errors to submit functions that use metadata create handler

* Fix typo

* Add missing category prop to getting initial data for category details form

* Fix types

* wip

* wip

* wip

* wip

* Fix types & refactor

* Fix types & refactor

* Fix typescript

* Fix unmatching tag

* Fixes

* Add handling of multiple forms at once to exit dirty form provider

* Change all usages of ExitFormDialogContext to designated hook

* wip

* wip

* wip

* Fix types wip

* Fix types

* Remove console logs

* Add isSubmitting prop to exit form dialog in order to avoid enabling exit dialog while submit is still in progresS

* Replace handleSubmit global util with a hook to use exit form dialog props inside

* Move useHandleSubmit to general hooks dir, update imports

* Small fixes

* Update snapshots

* Fix types

* Small fixes due to extensive rebase

* Update package lock

* Fixes after rebase

* Remove exit form from customer address dialog

* Fix types and update messages

* Fix types

* Change imports names

* Refactor

* Remove unnecessary console.log

* Update types, snapshots. etc after rebase
2022-02-01 10:58:06 +01:00

150 lines
4 KiB
TypeScript

import { OutputData } from "@editorjs/editorjs";
import { ChannelCollectionData } from "@saleor/channels/utils";
import { createChannelsChangeHandler } from "@saleor/collections/utils";
import { COLLECTION_CREATE_FORM_ID } from "@saleor/collections/views/consts";
import { useExitFormDialog } from "@saleor/components/Form/useExitFormDialog";
import { MetadataFormData } from "@saleor/components/Metadata";
import { RichTextEditorChange } from "@saleor/components/RichTextEditor";
import useForm, {
CommonUseFormResultWithHandlers,
FormChange,
SubmitPromise
} from "@saleor/hooks/useForm";
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
import useRichText from "@saleor/utils/richText/useRichText";
import React, { useEffect } from "react";
export interface CollectionCreateFormData extends MetadataFormData {
backgroundImage: {
url: string;
value: string;
};
backgroundImageAlt: string;
channelListings: ChannelCollectionData[];
name: string;
slug: string;
seoDescription: string;
seoTitle: string;
}
export interface CollectionCreateData extends CollectionCreateFormData {
description: OutputData;
}
interface CollectionCreateHandlers {
changeMetadata: FormChange;
changeDescription: RichTextEditorChange;
changeChannels: (
id: string,
data: Omit<ChannelCollectionData, "name" | "id">
) => void;
}
export type UseCollectionCreateFormResult = CommonUseFormResultWithHandlers<
CollectionCreateData,
CollectionCreateHandlers
>;
export interface CollectionCreateFormProps {
currentChannels: ChannelCollectionData[];
setChannels: (data: ChannelCollectionData[]) => void;
children: (props: UseCollectionCreateFormResult) => React.ReactNode;
onSubmit: (data: CollectionCreateData) => SubmitPromise;
}
const getInitialData = (
currentChannels: ChannelCollectionData[]
): CollectionCreateFormData => ({
backgroundImage: {
url: null,
value: null
},
backgroundImageAlt: "",
channelListings: currentChannels,
metadata: [],
name: "",
privateMetadata: [],
seoDescription: "",
seoTitle: "",
slug: ""
});
function useCollectionCreateForm(
currentChannels: ChannelCollectionData[],
setChannels: (data: ChannelCollectionData[]) => void,
onSubmit: (data: CollectionCreateData) => SubmitPromise
): UseCollectionCreateFormResult {
const {
handleChange,
data: formData,
triggerChange,
setChanged,
hasChanged,
formId
} = useForm(getInitialData(currentChannels), undefined, {
confirmLeave: true,
formId: COLLECTION_CREATE_FORM_ID
});
const handleFormSubmit = useHandleFormSubmit({
formId,
onSubmit,
setChanged
});
const { setExitDialogSubmitRef } = useExitFormDialog({
formId
});
const [description, changeDescription] = useRichText({
initial: null,
triggerChange
});
const {
makeChangeHandler: makeMetadataChangeHandler
} = useMetadataChangeTrigger();
const changeMetadata = makeMetadataChangeHandler(handleChange);
// Need to make it function to always have description.current up to date
const getData = (): CollectionCreateData => ({
...formData,
description: description.current
});
const handleChannelChange = createChannelsChangeHandler(
currentChannels,
setChannels,
triggerChange
);
const submit = () => handleFormSubmit(getData());
useEffect(() => setExitDialogSubmitRef(submit), [submit]);
return {
change: handleChange,
data: getData(),
handlers: {
changeChannels: handleChannelChange,
changeDescription,
changeMetadata
},
hasChanged,
submit
};
}
const CollectionCreateForm: React.FC<CollectionCreateFormProps> = ({
currentChannels,
setChannels,
children,
onSubmit
}) => {
const props = useCollectionCreateForm(currentChannels, setChannels, onSubmit);
return <form onSubmit={props.submit}>{children(props)}</form>;
};
CollectionCreateForm.displayName = "CollectionCreateForm";
export default CollectionCreateForm;