saleor-dashboard/src/orders/components/OrderCustomerAddressesEditDialog/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

221 lines
6.4 KiB
TypeScript

import { useExitFormDialog } from "@saleor/components/Form/useExitFormDialog";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import { AddressTypeInput } from "@saleor/customers/types";
import {
CustomerAddresses_user_addresses,
CustomerAddresses_user_defaultBillingAddress,
CustomerAddresses_user_defaultShippingAddress
} from "@saleor/customers/types/CustomerAddresses";
import useForm, {
CommonUseFormResultWithHandlers,
FormChange,
SubmitPromise
} from "@saleor/hooks/useForm";
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import React, { useEffect, useState } from "react";
export enum AddressInputOptionEnum {
CUSTOMER_ADDRESS = "customerAddress",
NEW_ADDRESS = "newAddress"
}
export interface OrderCustomerAddressesEditFormData {
billingSameAsShipping: boolean;
shippingAddressInputOption: AddressInputOptionEnum;
billingAddressInputOption: AddressInputOptionEnum;
customerShippingAddress: CustomerAddresses_user_defaultShippingAddress;
customerBillingAddress: CustomerAddresses_user_defaultBillingAddress;
shippingAddress: AddressTypeInput;
billingAddress: AddressTypeInput;
}
export interface OrderCustomerAddressesEditData
extends OrderCustomerAddressesEditFormData {
shippingCountryDisplayName: string;
billingCountryDisplayName: string;
}
export interface OrderCustomerAddressesEditHandlers {
changeFormAddress: (
event: React.ChangeEvent<any>,
addressType: "shippingAddress" | "billingAddress"
) => void;
changeCustomerAddress: (
customerAddress: CustomerAddresses_user_addresses,
addressType: "customerShippingAddress" | "customerBillingAddress"
) => void;
selectShippingCountry: FormChange;
selectBillingCountry: FormChange;
}
interface UseOrderCustomerAddressesEditFormResult
extends CommonUseFormResultWithHandlers<
OrderCustomerAddressesEditData,
OrderCustomerAddressesEditHandlers
> {
submit: (event: React.FormEvent<any>) => SubmitPromise<any[]>;
}
interface UseOrderCustomerAddressesEditFormOpts {
countryChoices: SingleAutocompleteChoiceType[];
defaultShippingAddress: CustomerAddresses_user_defaultShippingAddress;
defaultBillingAddress: CustomerAddresses_user_defaultBillingAddress;
}
export interface OrderCustomerAddressesEditFormProps
extends UseOrderCustomerAddressesEditFormOpts {
children: (props: UseOrderCustomerAddressesEditFormResult) => React.ReactNode;
initial?: Partial<OrderCustomerAddressesEditFormData>;
onSubmit: (data: OrderCustomerAddressesEditData) => SubmitPromise<any[]>;
}
const initialAddress: AddressTypeInput = {
city: "",
country: "",
phone: "",
postalCode: "",
streetAddress1: ""
};
const getDefaultInitialFormData = (
opts: UseOrderCustomerAddressesEditFormOpts
): OrderCustomerAddressesEditFormData => ({
billingSameAsShipping: true,
shippingAddressInputOption: AddressInputOptionEnum.CUSTOMER_ADDRESS,
billingAddressInputOption: AddressInputOptionEnum.CUSTOMER_ADDRESS,
customerShippingAddress: opts.defaultShippingAddress,
customerBillingAddress: opts.defaultBillingAddress,
shippingAddress: initialAddress,
billingAddress: initialAddress
});
function useOrderCustomerAddressesEditForm(
initial: Partial<OrderCustomerAddressesEditFormData>,
onSubmit: (data: OrderCustomerAddressesEditData) => SubmitPromise<any[]>,
opts: UseOrderCustomerAddressesEditFormOpts
): UseOrderCustomerAddressesEditFormResult {
const {
handleChange,
hasChanged,
change,
data: formData,
setChanged
} = useForm({
...initial,
...getDefaultInitialFormData(opts)
});
const { setExitDialogSubmitRef } = useExitFormDialog();
const [shippingCountryDisplayName, setShippingCountryDisplayName] = useState(
""
);
const [billingCountryDisplayName, setBillingCountryDisplayName] = useState(
""
);
const handleFormAddressChange = (
event: React.ChangeEvent<any>,
addressType: "shippingAddress" | "billingAddress"
) =>
change({
target: {
name: addressType,
value: {
...formData[addressType],
[event.target.name]: event.target.value
}
}
});
const handleCustomerAddressChange = (
customerAddress: CustomerAddresses_user_addresses,
addressType: "customerShippingAddress" | "customerBillingAddress"
) =>
change({
target: {
name: addressType,
value: customerAddress
}
});
const handleShippingCountrySelect = createSingleAutocompleteSelectHandler(
event =>
change({
target: {
name: "shippingAddress",
value: {
...formData.shippingAddress,
[event.target.name]: event.target.value
}
}
}),
setShippingCountryDisplayName,
opts.countryChoices
);
const handleBillingCountrySelect = createSingleAutocompleteSelectHandler(
event =>
change({
target: {
name: "billingAddress",
value: {
...formData.billingAddress,
[event.target.name]: event.target.value
}
}
}),
setBillingCountryDisplayName,
opts.countryChoices
);
const data = {
...formData,
shippingCountryDisplayName,
billingCountryDisplayName
};
const handleFormSubmit = useHandleFormSubmit({
onSubmit,
setChanged
});
const handleSubmit = () => handleFormSubmit(data);
const submit = (event: React.FormEvent<any>) => {
event.stopPropagation();
event.preventDefault();
return handleSubmit();
};
useEffect(() => setExitDialogSubmitRef(submit), [handleSubmit]);
return {
change: handleChange,
submit,
hasChanged,
data,
handlers: {
changeCustomerAddress: handleCustomerAddressChange,
changeFormAddress: handleFormAddressChange,
selectShippingCountry: handleShippingCountrySelect,
selectBillingCountry: handleBillingCountrySelect
}
};
}
const OrderCustomerAddressesEditForm: React.FC<OrderCustomerAddressesEditFormProps> = ({
children,
initial,
onSubmit,
...rest
}) => {
const props = useOrderCustomerAddressesEditForm(
initial || {},
onSubmit,
rest
);
return <form onSubmit={props.submit}>{children(props)}</form>;
};
OrderCustomerAddressesEditForm.displayName = "OrderCustomerAddressesEditForm";
export default OrderCustomerAddressesEditForm;