Skip to content

Commit

Permalink
Support mutliple condition types (#4644)
Browse files Browse the repository at this point in the history
* Refactor rule model

* Add changeset

* Add discount type component

* Add type to initial form values

* Bump macaw

* Refactor Add button

* Update test

* Refactor DiscountRule isLoaded

* Add type support

* Remve useeffect

* Add changeset

* Extract messages

* Init context

* Context intro

* Remove empty import

* Fix tests, fix useDiscountRulesContext imports

* Add changeset

* Support mutliple condition types

* Update label map after rule add

* Add sorting

* Extract messages

* Add changeset

* Improve useVariantOptions

* Remove unused hooks
  • Loading branch information
poulch committed Jan 30, 2024
1 parent a423387 commit 01115af
Show file tree
Hide file tree
Showing 36 changed files with 661 additions and 277 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-keys-compete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": minor
---

Support mutliple condition types
12 changes: 12 additions & 0 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1965,6 +1965,9 @@
"BtErCZ": {
"string": "Search Plugins..."
},
"BvGp1I": {
"string": "between"
},
"BvRyoX": {
"context": "alert message",
"string": "There are no available shipping methods in this channel."
Expand Down Expand Up @@ -3352,6 +3355,9 @@
"context": "mark as paid strategy checkbox label",
"string": "Use Transaction flow when marking order as paid"
},
"L5IuDw": {
"string": "lower"
},
"L5io1l": {
"context": "returned products list title",
"string": "Products returned"
Expand Down Expand Up @@ -3913,6 +3919,9 @@
"PFXGaR": {
"string": "Shipping Zones"
},
"PFnobO": {
"string": "greater"
},
"PHUcrU": {
"context": "date when order was placed",
"string": "Date"
Expand Down Expand Up @@ -6514,6 +6523,9 @@
"h2vipu": {
"string": "Code"
},
"h5P++h": {
"string": "Variants"
},
"h65vZI": {
"context": "times voucher used",
"string": "Used"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export const useRulesHandlers = (
}, [discountType]);

const onDeleteRule = (ruleDeleteIndex: number) => {
setRules(rules => rules.filter((_, index) => index !== ruleDeleteIndex));
setRules(rules =>
sortRules(rules.filter((_, index) => index !== ruleDeleteIndex)),
);
};

const onRuleSubmit = async (data: Rule, ruleEditIndex: number | null) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
searchCollectionsMock,
searchProductsMock,
searchVariantsMock,
} from "../DiscountRules/componenets/RuleFormModal/mocks";
} from "../DiscountRules/componenets/RuleForm/components/RuleConditionValues/hooks/options/mocks";
import {
DiscountCreatePage,
DiscountCreatePageProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const DiscountCreatePage = ({
/>

<DiscountRules
discountType="catalog"
errors={errors as DiscountRulesErrors<PromotionCreateErrorCode>}
channels={channels}
disabled={disabled}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { mapAPIRuleToForm, Rule } from "@dashboard/discounts/models";
import { sortRules } from "@dashboard/discounts/utils";
import {
PromotionDetailsFragment,
PromotionRuleCreateErrorFragment,
Expand Down Expand Up @@ -31,9 +32,10 @@ export const useRulesHandlers = ({
const [rulesErrors, setRulesErrors] = useState<Array<CommonError<any>>>([]);
const [labelsMap, setLabelMap] = useState<Record<string, string>>({});

const rules =
const rules = sortRules(
data?.rules?.map(rule => mapAPIRuleToForm("catalog", rule, labelsMap)) ??
[];
[],
);

useEffect(() => {
setLabelMap(labels => {
Expand All @@ -57,9 +59,9 @@ export const useRulesHandlers = ({
PromotionRuleUpdateErrorFragment | PromotionRuleCreateErrorFragment
>
> = [];
updateLabels(rule);

if (ruleEditIndex !== null) {
updateLabels(rule);
errors = await onRuleUpdateSubmit(rule);

if (errors.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
searchCollectionsMock,
searchProductsMock,
searchVariantsMock,
} from "../DiscountRules/componenets/RuleFormModal/mocks";
} from "../DiscountRules/componenets/RuleForm/components/RuleConditionValues/hooks/options/mocks";
import {
DiscountDetailsPage,
DiscountDetailsPageProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const DiscountDetailsPage = ({
/>

<DiscountRules
discountType="catalog"
errors={rulesErrors}
rules={rules}
loading={ruleConditionsOptionsDetailsLoading}
Expand Down
10 changes: 8 additions & 2 deletions src/discounts/components/DiscountRules/DiscountRules.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
searchCollectionsMock,
searchProductsMock,
searchVariantsMock,
} from "./componenets/RuleFormModal/mocks";
} from "./componenets/RuleForm/components/RuleConditionValues/hooks/options/mocks";
import { DiscountRules } from "./DiscountRules";

jest.mock("react-intl", () => ({
Expand Down Expand Up @@ -76,8 +76,8 @@ const rules = [
],
},
],
rewardType: null,
rewardValue: 12,
rewardType: null,
rewardValueType: RewardValueTypeEnum.FIXED,
},
{
Expand Down Expand Up @@ -129,6 +129,7 @@ describe("DiscountRules", () => {
// Arrange & Act
render(
<DiscountRules
discountType="catalog"
channels={[]}
rules={[]}
errors={[]}
Expand All @@ -152,6 +153,7 @@ describe("DiscountRules", () => {
// Arrange & Act
render(
<DiscountRules
discountType="catalog"
channels={[]}
rules={rules}
errors={[]}
Expand Down Expand Up @@ -190,6 +192,7 @@ describe("DiscountRules", () => {
const onRuleAdd = jest.fn();
render(
<DiscountRules
discountType="catalog"
channels={channels}
rules={[]}
errors={[]}
Expand Down Expand Up @@ -276,6 +279,7 @@ describe("DiscountRules", () => {

render(
<DiscountRules
discountType="catalog"
channels={[]}
rules={rules}
errors={[]}
Expand Down Expand Up @@ -311,6 +315,7 @@ describe("DiscountRules", () => {

render(
<DiscountRules
discountType="catalog"
channels={channels}
rules={rules}
errors={[]}
Expand Down Expand Up @@ -386,6 +391,7 @@ describe("DiscountRules", () => {
// Arrange & Act
render(
<DiscountRules
discountType="catalog"
channels={[]}
rules={rules}
errors={[
Expand Down
11 changes: 7 additions & 4 deletions src/discounts/components/DiscountRules/DiscountRules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useIntl } from "react-intl";

import { AddButton } from "./componenets/AddButton";
import { RuleDeleteModal } from "./componenets/RuleDeleteModal/RuleDeleteModal";
import { RuleForm } from "./componenets/RuleForm";
import { RuleFormModal } from "./componenets/RuleFormModal";
import { RulesList } from "./componenets/RulesList";
import { DiscountRulesContextProvider } from "./context";
Expand All @@ -20,6 +21,7 @@ export type DiscountRulesErrors<ErrorCode> = Array<

interface DiscountRulesProps<ErrorCode> {
disabled: boolean;
discountType: "catalog";
channels: ChannelFragment[];
rules: Rule[];
errors: Array<CommonError<ErrorCode>>;
Expand All @@ -39,6 +41,7 @@ export const DiscountRules = <ErrorCode,>({
errors,
getRuleConfirmButtonState,
deleteButtonState,
discountType,
loading,
onRuleSubmit,
onRuleDelete,
Expand Down Expand Up @@ -86,7 +89,7 @@ export const DiscountRules = <ErrorCode,>({

return (
<DiscountRulesContextProvider
discountType="catalog"
discountType={discountType}
channels={channels}
disabled={disabled}
>
Expand Down Expand Up @@ -116,11 +119,11 @@ export const DiscountRules = <ErrorCode,>({
confimButtonState={getRuleConfirmButtonState(ruleEditIndex)}
onClose={handleRuleModalClose}
initialFormValues={ruleInitialValues}
errors={errors}
onSubmit={handleRuleModalSubmit}
/>
>
<RuleForm errors={errors} />
</RuleFormModal>
)}

<RuleDeleteModal
open={ruleDeleteIndex !== null}
onClose={() => setRuleDeleteIndex(null)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
createEmptyCodition,
Rule as RuleType,
} from "@dashboard/discounts/models";
import { createEmptyCodition, Rule } from "@dashboard/discounts/models";
import { RewardValueTypeEnum } from "@dashboard/graphql";
import { commonMessages } from "@dashboard/intl";
import { getFormErrors } from "@dashboard/utils/errors";
Expand All @@ -16,39 +13,34 @@ import React, { useEffect, useMemo } from "react";
import { useController, useFormContext } from "react-hook-form";
import { useIntl } from "react-intl";

import { ConditionType } from "../../../../types";
import { useDiscountRulesContext } from "../../context";
import { getCurencySymbol } from "../../utils";
import { FetchOptions } from "./components/RuleConditionRow";
import { RuleConditions } from "./components/RuleConditions";
import { RuleDescription } from "./components/RuleDescription";
import { RuleInputWrapper } from "./components/RuleInputWrapper/RuleInputWrapper";
import { RuleReward } from "./components/RuleReward";

interface RuleFormProps<ErrorCode> {
errors: Array<CommonError<ErrorCode>>;
typeToFetchMap: Record<ConditionType, FetchOptions>;
}

export const RuleForm = <ErrorCode,>({
errors,
typeToFetchMap,
}: RuleFormProps<ErrorCode>) => {
export const RuleForm = <ErrorCode,>({ errors }: RuleFormProps<ErrorCode>) => {
const intl = useIntl();
const { disabled, channels } = useDiscountRulesContext();
const { watch, getValues, setValue, formState } = useFormContext<RuleType>();
const { watch, getValues, setValue, formState } = useFormContext<Rule>();
const formErrors = getFormErrors(["rewardValue"], errors);

const { trigger } = useFormContext<RuleType>();
const { field: nameField } = useController<RuleType, "name">({
const { trigger } = useFormContext<Rule>();
const { field: nameField } = useController<Rule, "name">({
name: "name",
});

const { field: channelfield } = useController<RuleType, "channel">({
const { field: channelfield } = useController<Rule, "channel">({
name: "channel",
});

const selectedChannel = watch("channel");

const conditions = watch("conditions");
const hasSelectedChannel = !!selectedChannel;
const currencySymbol = getCurencySymbol(selectedChannel, channels);
Expand Down Expand Up @@ -87,49 +79,48 @@ export const RuleForm = <ErrorCode,>({

return (
<RichTextContext.Provider value={richText}>
<Box display="flex" flexDirection="column" gap={4} marginTop={4}>
<Box display="flex" gap={4}>
<RuleInputWrapper __flex={1}>
<Input
{...nameField}
disabled={disabled || nameField.disabled}
size="small"
label="Name"
error={!!formState.errors?.name?.message}
helperText={formState.errors?.name?.message}
/>
</RuleInputWrapper>

<RuleInputWrapper __flex={1}>
<Select
{...channelfield}
onChange={handleChannelChange}
size="small"
data-test-id="channel-dropdown"
label={intl.formatMessage(commonMessages.channel)}
options={channelOptions}
error={!!formState.errors?.channel?.message}
helperText={formState.errors?.channel?.message}
disabled={disabled || channelfield.disabled}
/>
</RuleInputWrapper>
<Box __width={650} __minHeight={515} __maxHeight="75vh" overflowY="auto">
<Box display="flex" flexDirection="column" gap={4} marginTop={4}>
<Box display="flex" gap={4}>
<RuleInputWrapper __flex={1}>
<Input
{...nameField}
disabled={disabled || nameField.disabled}
size="small"
label={intl.formatMessage(commonMessages.name)}
error={!!formState.errors?.name?.message}
helperText={formState.errors?.name?.message}
/>
</RuleInputWrapper>

<RuleInputWrapper __flex={1}>
<Select
{...channelfield}
onChange={handleChannelChange}
size="small"
data-test-id="channel-dropdown"
label={intl.formatMessage(commonMessages.channel)}
options={channelOptions}
error={!!formState.errors?.channel?.message}
helperText={formState.errors?.channel?.message}
disabled={disabled || channelfield.disabled}
/>
</RuleInputWrapper>
</Box>

<RuleConditions hasSelectedChannels={hasSelectedChannel} />

<RuleReward
currencySymbol={currencySymbol}
error={getCommonFormFieldErrorMessage(formErrors.rewardValue, intl)}
/>

<RuleDescription />

<button type="submit" hidden>
Submit
</button>
</Box>

<RuleConditions
hasSelectedChannels={hasSelectedChannel}
typeToFetchMap={typeToFetchMap}
/>

<RuleReward
currencySymbol={currencySymbol}
error={getCommonFormFieldErrorMessage(formErrors.rewardValue, intl)}
/>

<RuleDescription />

<button type="submit" hidden>
Submit
</button>
</Box>
</RichTextContext.Provider>
);
Expand Down

0 comments on commit 01115af

Please sign in to comment.