
* Tax configuration - implement channels view (#2048) * Add channels view * Fix channels view import * Remove legacy stories references * Fix link in configuration * Update snapshots * Remove sample checkboxes props * Disable hover in country exceptions * Update snapshots * Extract country exception rows to seperate component * Extract components to seperate files * Remove duplicated section name * Remove backlink * Add translations to section names * Extract messages * Add ListItemLink component * Replace navigator with link in TaxChannelsMenu * Fix horizontal scroll in TaxChannelsMenu * Change codegen to build from custom schema * Build types * Update fragments * Add fixtures * Change any to proper types * Add story for tax channels page * Replace MUI Skeleton with Saleor Skeleton * Change clsx import to classnames * Fix checkboxes shadows in settings card * Update IDs in fixtures * Fix offset in TaxChannelsMenu * Update snapshots * Remove any from TaxSettings * Fix todos * Change relative marginLeft to before pseudoelement * Extract styles to seperate files * Change folder structure * Extract redirect logic to custom hook * Update snapshots * Fix comment * Add early return in channels view * Tax configuration - implement countries view (#2053) * Add channels view * Remove sample checkboxes props * Disable hover in country exceptions * Extract country exception rows to seperate component * Extract components to seperate files * Remove duplicated section name * Remove backlink * Add translations to section names * Replace navigator with link in TaxChannelsMenu * Fix horizontal scroll in TaxChannelsMenu * Change any to proper types * Add story for tax channels page * Replace MUI Skeleton with Saleor Skeleton * Change clsx import to classnames * Fix checkboxes shadows in settings card * Update IDs in fixtures * Fix offset in TaxChannelsMenu * Remove any from TaxSettings * Add countries list view * Add TaxCountryMenu component * Add CountryList page * Change channels menu rows height * Change countries menu rows height * Add TaxInput component * Add tax classes rates to countries page * Fix search input padding * Add minmax to TaxInput * Add searching through tax class rates * Extract messages * Add better handlers * Add fullWidth to TaxInput * Specify type for TaxInputs * Remove spinboxes on firefox * Remove custom spinboxes * Remove maxHeight from menu rows * Post-rebase fix * Change setter to formchagne * Add TaxConfiguration fragment * Add isDefault field to taxClass * Add fixtures * Shape data * Replace useEffect with useTaxUrlRedirect * Fix country names in menu * Add country page story * Add early return in countries view * Unify loading states between channels and countries pages * Handle special chars and case insensitiveness in local search * Replace navigate function with ListItemLink * Move styles to seperate file * Move styles to seperate file * Migrate to strict null checks * Remove unnecessary optional chaining * Change overflow scroll to Y only * Add useMemo on finding selected country * Add useMemo on local search * Translate labels in page tabs * Change url from /taxes/classes to /taxes/tax-classes * Remove capitalization from strings * Extract messages * Bump macaw to 0.6.2 * Update snapshots * Add spinboxes explanation comment * Handle empty state * Add tax classes view (#2093) * Add TaxClass fragment * Build types * Add tax classes to fixtures * Add tax classes view * wip Add tax classes page * Add tax classes menu * Add TaxRate fragment * Extract logic * Handle loading state & add story * Extract messages * Update snapshots * Change schema building from schema back to introspection * Update schema * Update fragments * Build types * Update fixtures * Reshape data * Move styles to seperate file * Use getById * Add explicit undefined * Comment out unfinished modal stories * Update snapshots * Taxes - add API calls in channels view (#2106) * Build types * Add TaxRate fragment * Update snapshots * Add taxConfigurationList query * Add taxCountriesList query * Add TaxClassesList query * Rename TaxConfigurationsList query * Handle empty state * Fix types post-rebase * Add form to TaxChannelsPage * wip Add dialog for handling country exceptions * wip Fix dialog url * wip Add update exceptions handlers * Add dialog story * Fix type errors * Add mutation support * Fix types in story * Add transition state to submit button * Add notifier * Extract messages * Remove unused import * Add backlink in savebar * Update snapshots * Fix link in navigation * Update snapshots * Remove message from tax config error fragment * Add hook description * Use useStateFromProps * Remove error handling * Improve url & path function names * Use theme.spacing in TaxCountryDialog styles * Remove redundant key modification * Revert "Use useStateFromProps" This reverts commit d3c68b04701cf935e917d7baa3ed1361ca3446d5. * Move initial map to parent & add open dependency to countries state * Use useModalDialogOpen * Fix state update * Remove scrolls & add ellipsis in side menu * Center checkboxes * Update snapshots * Add fake div for list alignment * Trigger deployment * Close modal on submit * Remove divider on last ListItem * Align add country button * Wrap grid child in div to avoid card stretching * Update snapshots * Trigger changes in add/delete exceptions * Trigger change on expcetion checkboxes * Add trailing commas * Connect countries view to API (#2178) * Add empty states * Update countries view urls * Remove unused import * Add country modal to countries view * Update schema * Implement country view mutations & error fragments * Implement tax class update mutation * Add sidebar temporary state for new configs * Remove unused imports * Wrap in form * Add savebar & fix search * Update schema * Add form wrapper * Fix types * Extract messages * Bump macaw * Update snapshots * Fix comma dangles * Update snapshots * Notify about mutation success * Add logic for mixing current and new rates * Workaround for sending null rates * Fix filling form with correct data after submitting * Handle deleting configuration * Fix selected banner * Remove leftover comment * Add handler for country configuration delete * Trigger deployment * Clean up useEffects causing infinite render loops * Sort countries from api by name * Fix card bottom padding * Remove bottom divider & fix padding * Remove scroll wrapper in side menu * Update snapshots * Remove scroll wrapper from tax classes menu * Update snapshots * Refresh form to initial onSubmit * Revert "Refresh form to initial onSubmit" This reverts commit 42414237d35086da63f4aa088c8072411429b1d8. * Allow only 3 decimal characters in tax inputs * Update snapshots * Update schema * Update types * Change logic from default tax class to null class * Fix sorting * Send empty country rates as nulls in mutation * Extract messages * Update lockfile * Update schema * Drop default tax classes * Update snapshots * Post-rebase fixes * Connect tax classes view to API (#2334) * Add mutations * Handle empty state * Wrap page in form * Update stories * Build types * Handle tax class delete * Handle update tax class * Update stories * Handle tax class change name * Add mutation state to savebar * Handle creating new tax classes * Extract messages * Specify type * Update stories * Sort rates * Fix skeleton rendering * Remove placeholders * Fix skeleton rendering on country list * Update snapshots * Change initial pagination to 100 * Disallow creating multiple new tax classes * Disallow creating multiple country configurations * Fix messages * Autofocus on new tax class name * Add country name to header * Temporarily comment out broken code in tax channels * Update snapshots * Update snapshots post-rebase * Add tax strategies & assigning tax classes (#2369) * Update fragments * Add optional merging in useForm * Handle tax strategies * Update snapshots * Update fixtures * Extract messages * Remove unused shop query fields * Fix breaking bug when fetchMore is used in non-searchable SingleAutocompleteSelectFields * Migrate product types to tax classes * Add tax classes to shipping methods * Use encapsulated logic in product types * Fix product type stories * Fix shipping fixtures * Fix product type type mismatch * Fix shipping stories * Fix product type fixtures * Fix mismatching types * Extract messages * Update snapshots * Update snapshots * Fix comment * Drop deprecated graphql fields * Replace tax types with tax classes in product create view * Replace tax types with tax classes in product update view * Fix tests, stories, fixtures * Extract messages * Update snapshots * Move status messages to commonStatusMessages * Handle empty array case in tax class change handler * Reuse messages * Simple taxes bugfixes (#2395) * Fix tax channels menu - dense layout * Change view names to fit convention * Fix per country exceptions in tax channels view * Fix skeleton rendering on tax countries card title * Filter out existing countries from modal * Update snapshots * Fix deleting country configuration * Disallow negative values in tax inputs * Handle empty tax classes view * Allow empty options in shipping & product types views tax class assignment field * Modify undefined rates in tax classes view * Update macaw-ui * Fix UI on channels view * Fix UI on countries view * Fix UI on countries view * Align tax class rate label to the right * Updaste snapshots * Extract messages * Fix adding rates on new tax class * Fix key errors * Update schema * Build types * Allow empty rates in taxClassUpdate mutation * Extract tax channels change country function as a handler * Deprecate useStateFromProps * Change useStateFromProps to useStateUpdate * Fix dividers * Delete delete icon on new tax classes * Update snapshots * Update lockfile * Update macaw to 0.6.6 * Update snapshots * Specify type of input in country change handler * Extract autofocus logic to custom hook * Replace alternative with switch statement * Extract country exclusion logic from JSX * Update lockfile * Update lockfile * Trigger deployment * Fix invisible select markers * Fix linter issue * Fix crashing product details page * Fix e2e error * Update snapshots * Allow view taxes with any staff permissions (#2510) * Update after rebase Co-authored-by: Dawid <tarasiukdawid@gmail.com>
286 lines
9.7 KiB
TypeScript
286 lines
9.7 KiB
TypeScript
import { ChannelShippingData } from "@saleor/channels/utils";
|
|
import { Backlink } from "@saleor/components/Backlink";
|
|
import CardSpacer from "@saleor/components/CardSpacer";
|
|
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
|
import Container from "@saleor/components/Container";
|
|
import { WithFormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
|
import Grid from "@saleor/components/Grid";
|
|
import Metadata from "@saleor/components/Metadata/Metadata";
|
|
import PageHeader from "@saleor/components/PageHeader";
|
|
import Savebar from "@saleor/components/Savebar";
|
|
import {
|
|
PermissionEnum,
|
|
PostalCodeRuleInclusionTypeEnum,
|
|
ShippingChannelsErrorFragment,
|
|
ShippingErrorFragment,
|
|
ShippingMethodTypeEnum,
|
|
ShippingMethodTypeFragment,
|
|
ShippingZoneQuery,
|
|
TaxClassFragment,
|
|
} from "@saleor/graphql";
|
|
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
|
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
|
import useNavigator from "@saleor/hooks/useNavigator";
|
|
import { useStateUpdate } from "@saleor/hooks/useStateUpdate";
|
|
import { ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
|
import { validatePrice } from "@saleor/products/utils/validation";
|
|
import { handleTaxClassChange } from "@saleor/productTypes/handlers";
|
|
import OrderValue from "@saleor/shipping/components/OrderValue";
|
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
|
import ShippingMethodProducts from "@saleor/shipping/components/ShippingMethodProducts";
|
|
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
|
import { FetchMoreProps, ListActions, ListProps } from "@saleor/types";
|
|
import { mapEdgesToItems, mapMetadataItemToInput } from "@saleor/utils/maps";
|
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
|
import { RichTextContext } from "@saleor/utils/richText/context";
|
|
import useRichText from "@saleor/utils/richText/useRichText";
|
|
import React, { FormEventHandler } from "react";
|
|
import { FormattedMessage } from "react-intl";
|
|
|
|
import ShippingMethodTaxes from "../ShippingMethodTaxes";
|
|
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
|
import { ShippingZoneRateUpdateFormData } from "./types";
|
|
|
|
export interface ShippingZoneRatesPageProps
|
|
extends Pick<ListProps, Exclude<keyof ListProps, "getRowHref">>,
|
|
ListActions,
|
|
WithFormId {
|
|
allChannelsCount?: number;
|
|
shippingChannels: ChannelShippingData[];
|
|
disabled: boolean;
|
|
rate: ShippingZoneQuery["shippingZone"]["shippingMethods"][0];
|
|
channelErrors: ShippingChannelsErrorFragment[];
|
|
errors: ShippingErrorFragment[];
|
|
saveButtonBarState: ConfirmButtonTransitionState;
|
|
postalCodeRules: ShippingZoneQuery["shippingZone"]["shippingMethods"][0]["postalCodeRules"];
|
|
backHref: string;
|
|
onDelete?: () => void;
|
|
onSubmit: (data: ShippingZoneRateUpdateFormData) => SubmitPromise;
|
|
onPostalCodeInclusionChange: (
|
|
inclusion: PostalCodeRuleInclusionTypeEnum,
|
|
) => void;
|
|
onPostalCodeAssign: () => void;
|
|
onPostalCodeUnassign: (
|
|
code: ShippingMethodTypeFragment["postalCodeRules"][0],
|
|
) => void;
|
|
onChannelsChange: (data: ChannelShippingData[]) => void;
|
|
openChannelsModal: () => void;
|
|
onProductAssign: () => void;
|
|
onProductUnassign: (ids: string[]) => void;
|
|
variant: ShippingMethodTypeEnum;
|
|
taxClasses: Array<Omit<TaxClassFragment, "countries">>;
|
|
fetchMoreTaxClasses: FetchMoreProps;
|
|
}
|
|
|
|
export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|
allChannelsCount,
|
|
shippingChannels,
|
|
channelErrors,
|
|
disabled,
|
|
errors,
|
|
backHref,
|
|
onDelete,
|
|
onSubmit,
|
|
onPostalCodeInclusionChange,
|
|
onChannelsChange,
|
|
onPostalCodeAssign,
|
|
onPostalCodeUnassign,
|
|
onProductAssign,
|
|
onProductUnassign,
|
|
openChannelsModal,
|
|
rate,
|
|
saveButtonBarState,
|
|
postalCodeRules,
|
|
variant,
|
|
formId,
|
|
taxClasses,
|
|
fetchMoreTaxClasses,
|
|
...listProps
|
|
}) => {
|
|
const navigate = useNavigator();
|
|
|
|
const isPriceVariant = variant === ShippingMethodTypeEnum.PRICE;
|
|
|
|
const initialForm: Omit<
|
|
ShippingZoneRateUpdateFormData,
|
|
"description"
|
|
> = React.useMemo(
|
|
() => ({
|
|
channelListings: shippingChannels,
|
|
maxDays: rate?.maximumDeliveryDays?.toString() || "",
|
|
maxValue: rate?.maximumOrderWeight?.value.toString() || "",
|
|
metadata: rate?.metadata.map(mapMetadataItemToInput),
|
|
minDays: rate?.minimumDeliveryDays?.toString() || "",
|
|
minValue: rate?.minimumOrderWeight?.value.toString() || "",
|
|
name: rate?.name || "",
|
|
orderValueRestricted: !!rate?.channelListings.length,
|
|
privateMetadata: rate?.privateMetadata.map(mapMetadataItemToInput),
|
|
type: rate?.type || null,
|
|
taxClassId: rate?.taxClass?.id || "",
|
|
}),
|
|
[shippingChannels, rate],
|
|
);
|
|
|
|
const {
|
|
change,
|
|
data: formData,
|
|
setIsSubmitDisabled,
|
|
triggerChange,
|
|
} = useForm(initialForm, undefined, { confirmLeave: true, formId });
|
|
|
|
const [taxClassDisplayName, setTaxClassDisplayName] = useStateUpdate(
|
|
rate?.taxClass?.name ?? "",
|
|
);
|
|
|
|
const handleFormSubmit = useHandleFormSubmit({
|
|
formId,
|
|
onSubmit,
|
|
});
|
|
|
|
const richText = useRichText({
|
|
initial: rate?.description,
|
|
loading: !rate,
|
|
triggerChange,
|
|
});
|
|
|
|
const {
|
|
makeChangeHandler: makeMetadataChangeHandler,
|
|
} = useMetadataChangeTrigger();
|
|
|
|
const data: ShippingZoneRateUpdateFormData = {
|
|
...formData,
|
|
description: null,
|
|
};
|
|
|
|
// Prevents closing ref in submit functions
|
|
const getData = async (): Promise<ShippingZoneRateUpdateFormData> => ({
|
|
...data,
|
|
description: await richText.getValue(),
|
|
});
|
|
|
|
const handleFormElementSubmit: FormEventHandler = async event => {
|
|
event.preventDefault();
|
|
handleFormSubmit(await getData());
|
|
};
|
|
const handleSubmit = async () => handleFormSubmit(await getData());
|
|
|
|
const handleChannelsChange = createChannelsChangeHandler(
|
|
shippingChannels,
|
|
onChannelsChange,
|
|
triggerChange,
|
|
);
|
|
const isValid = !formData.channelListings?.some(channel =>
|
|
validatePrice(channel.price),
|
|
);
|
|
|
|
const changeMetadata = makeMetadataChangeHandler(change);
|
|
|
|
const isSaveDisabled = disabled || !isValid;
|
|
setIsSubmitDisabled(isSaveDisabled);
|
|
|
|
return (
|
|
<RichTextContext.Provider value={richText}>
|
|
<form onSubmit={handleFormElementSubmit}>
|
|
<Container>
|
|
<Backlink href={backHref}>
|
|
<FormattedMessage id="PRlD0A" defaultMessage="Shipping" />
|
|
</Backlink>
|
|
<PageHeader title={rate?.name} />
|
|
<Grid>
|
|
<div>
|
|
<ShippingRateInfo
|
|
data={data}
|
|
disabled={disabled}
|
|
errors={errors}
|
|
onChange={change}
|
|
/>
|
|
<CardSpacer />
|
|
{isPriceVariant ? (
|
|
<OrderValue
|
|
channels={data.channelListings}
|
|
errors={channelErrors}
|
|
orderValueRestricted={data.orderValueRestricted}
|
|
disabled={disabled}
|
|
onChange={change}
|
|
onChannelsChange={handleChannelsChange}
|
|
/>
|
|
) : (
|
|
<OrderWeight
|
|
orderValueRestricted={data.orderValueRestricted}
|
|
disabled={disabled}
|
|
minValue={data.minValue}
|
|
maxValue={data.maxValue}
|
|
onChange={change}
|
|
errors={errors}
|
|
/>
|
|
)}
|
|
<CardSpacer />
|
|
<PricingCard
|
|
channels={data.channelListings}
|
|
onChange={handleChannelsChange}
|
|
disabled={disabled}
|
|
errors={channelErrors}
|
|
/>
|
|
<CardSpacer />
|
|
<ShippingZonePostalCodes
|
|
disabled={disabled}
|
|
onPostalCodeDelete={onPostalCodeUnassign}
|
|
onPostalCodeInclusionChange={onPostalCodeInclusionChange}
|
|
onPostalCodeRangeAdd={onPostalCodeAssign}
|
|
postalCodes={postalCodeRules}
|
|
/>
|
|
<CardSpacer />
|
|
<ShippingMethodProducts
|
|
products={mapEdgesToItems(rate?.excludedProducts)}
|
|
onProductAssign={onProductAssign}
|
|
onProductUnassign={onProductUnassign}
|
|
disabled={disabled}
|
|
{...listProps}
|
|
/>
|
|
<CardSpacer />
|
|
<Metadata data={data} onChange={changeMetadata} />
|
|
</div>
|
|
<div>
|
|
<ChannelsAvailabilityCard
|
|
managePermissions={[PermissionEnum.MANAGE_SHIPPING]}
|
|
allChannelsCount={allChannelsCount}
|
|
channelsList={data.channelListings.map(channel => ({
|
|
id: channel.id,
|
|
name: channel.name,
|
|
}))}
|
|
openModal={openChannelsModal}
|
|
/>
|
|
<CardSpacer />
|
|
<ShippingMethodTaxes
|
|
value={formData.taxClassId}
|
|
taxClassDisplayName={taxClassDisplayName}
|
|
taxClasses={taxClasses}
|
|
disabled={false}
|
|
onChange={event =>
|
|
handleTaxClassChange(
|
|
event,
|
|
taxClasses,
|
|
change,
|
|
setTaxClassDisplayName,
|
|
)
|
|
}
|
|
onFetchMore={fetchMoreTaxClasses}
|
|
/>
|
|
</div>
|
|
</Grid>
|
|
<Savebar
|
|
disabled={isSaveDisabled}
|
|
onCancel={() => navigate(backHref)}
|
|
onDelete={onDelete}
|
|
onSubmit={handleSubmit}
|
|
state={saveButtonBarState}
|
|
/>
|
|
</Container>
|
|
</form>
|
|
</RichTextContext.Provider>
|
|
);
|
|
};
|
|
|
|
export default ShippingZoneRatesPage;
|