Skip to content

Commit

Permalink
Promotion rule gifts reward (#4655)
Browse files Browse the repository at this point in the history
* Update schema

* Add checkout option to add button submenu

* Update rules

* Refactor Condition

* Split model to order and catalog

* Prepare context

* Store condtion type

* Support multiple inputs depend on condition type

* handleOpenModal

* Use rule union

* Fix create object from static methods

* Fix add new rule

* Refactor model

* Use BaseRule type in form

* Update schema and support field with new names

* Filter AddButton submenu by discount type

* Filter add button options by discount type

* Fix showing conditions

* Show saved conditions

* Fix catalog conditions

* Show base rule summary for order rules

* Bump macaw to fix select onChange prop

* Use Rule interface, add OrderRule tests

* Refactor types

* Refactor model

* Update scheme, add type to promotion query

* Handle discount type field

* Bump macaw

* Handle range input

* Fix order rule label on list

* Improve rule summary

* Show option label in summary instead of value

* Rename models

* Refactor rule summary

* Refactor rule summary

* Comment useEnrichConditions, fix validation schema

* Rename hooks, fix tests

* Model refactor

* Fix ts issues

* Fix tests

* Refactor to condition value

* Fix tests

* Remove hooks from context

* Keep hooks close to components

* Pass RuleForm as child

* Last improvments

* 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

* Refactor RuleList

* Refactor rule summary to support order conditions

* Update test

* Add changeset

* Update schema

* Changeset add

* Add test to order rule, update catalog rule test, add test ids

* Skeleton

* Generate types

* Enable discount type at create page

* Fix disable type field

* Move RewardPrice

* Handle gifts

* Allow to change discount type at create page

* Update validation schema

* Show gift errors

* Fix reward type slect on change

* Improve data transfrmation

* Improve validation and messages

* Show gift on summary

* Fetch gifts labels

* Clear gifts and reward value when switch reward type

* Some improvemnts, ts fixes,  fix validation schema, format gift labels

* Update storybook, add mocks, update tests

* Add changeset

* Extract messages

* Format variant optipns label

* Add validation when procentage more than 100

* Add empty provider for create page

* Range inputs in one row

* Fix tests

* Redirect ti discount list after submit

* Extract messages

* Add product name to variant labels

* Clear gifts when channel change

* Stop send empty conditions, fix validation

* Add discount type to datagrid

* Fix typo

* Send gifts in separate fields

* Update types

* Refactor useConditionNames

* Handle complex condition in promotion rule (#4667)

* Update playground query

* Update mocks

* Update schema

* Fix caluclate nested conditions

* Prevent predicate send when hasPredicateNestedConditions

* Refactor rule reward

* Stop navigate on details discount form submit

* Improve reward wrapper

* Remove semicolon

* Use undefined instead of null when no gifts

* Show is gift boolean at order datagrid (#4661)

* Add is gift to query

* Add isGift column to order datagrids

* Update fixtures

* Add changeset
  • Loading branch information
poulch authored Feb 12, 2024
1 parent a3b365b commit bb2232b
Show file tree
Hide file tree
Showing 62 changed files with 1,572 additions and 329 deletions.
5 changes: 5 additions & 0 deletions .changeset/angry-pumpkins-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": minor
---

Introduce gift reward to order discounts
5 changes: 5 additions & 0 deletions .changeset/smart-dingos-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": minor
---

Introduce is gift column in order and draft order details datagrid
44 changes: 35 additions & 9 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,9 @@
"context": "gift card export type label",
"string": "gift cards"
},
"3mvL2Q": {
"string": "and"
},
"3oQzWR": {
"context": "product availability",
"string": "Set publication date"
Expand Down Expand Up @@ -1584,6 +1587,10 @@
"context": "modal button images upload",
"string": "Upload Images"
},
"9CW3TD": {
"context": "label",
"string": "Reward type"
},
"9FGTOt": {
"string": "Allow access to orders of all channels"
},
Expand Down Expand Up @@ -1923,6 +1930,9 @@
"BUKMzM": {
"string": "Variant removed"
},
"BVDaKx": {
"string": "Subtotal discount"
},
"BWpuKl": {
"string": "Update"
},
Expand Down Expand Up @@ -2044,9 +2054,6 @@
"context": "card header title",
"string": "Country list"
},
"CFlmRP": {
"string": "Rule reword value is required"
},
"CG+awx": {
"context": "dialog content",
"string": "Which address would you like to use as shipping address for selected customer:"
Expand Down Expand Up @@ -2187,6 +2194,9 @@
"context": "section title",
"string": "Checkout Configuration"
},
"DDYrvn": {
"string": "Rule reward value must be less than 100"
},
"DEa1T1": {
"context": "button",
"string": "Save Search"
Expand Down Expand Up @@ -2757,6 +2767,9 @@
"context": "navigator notification title",
"string": "Navigator is here to help"
},
"GxsQuO": {
"string": "You must select at least one gift"
},
"Gz+4CI": {
"context": "info text",
"string": "Preordered products will be available in all warehouses. You can set a threshold for sold quantity. Leaving input blank will be interpreted as no limit to sale. Sold items will be allocated at the warehouse assigned to chosen shipping zone."
Expand Down Expand Up @@ -3080,6 +3093,10 @@
"context": "column label",
"string": "Warehouse"
},
"J3W5LI": {
"context": "order line is gift",
"string": "Is gift"
},
"J3uE0t": {
"context": "section header",
"string": "Attribute Values"
Expand Down Expand Up @@ -3242,9 +3259,6 @@
"context": "delete attribute value",
"string": "Are you sure you want to delete \"{name}\" value?"
},
"JyaQcP": {
"string": "Rule reword value must be less than 100"
},
"K+vjtE": {
"string": "Search Variants"
},
Expand Down Expand Up @@ -5456,6 +5470,9 @@
"context": "Taxes section title",
"string": "Countries"
},
"ZBs2Pb": {
"string": "Gift"
},
"ZCSOaS": {
"string": "Limit to voucher code use once"
},
Expand Down Expand Up @@ -7008,9 +7025,6 @@
"kN6SLs": {
"string": "Min Value"
},
"kNK4es": {
"string": "Discount value"
},
"kPIZ65": {
"context": "page header",
"string": "Order #{orderNumber}"
Expand Down Expand Up @@ -7609,6 +7623,9 @@
"context": "tab name",
"string": "All Page Types"
},
"oX2TAb": {
"string": "Select gifts"
},
"oYGfnY": {
"string": "ZIP / Postal code"
},
Expand Down Expand Up @@ -7670,6 +7687,9 @@
"context": "alert",
"string": "Staff Member limit reached"
},
"pAwBtz": {
"string": "Reward value"
},
"pBTTtU": {
"context": "product kind",
"string": "Product Kind"
Expand Down Expand Up @@ -8421,6 +8441,9 @@
"context": "Authorize {app name}",
"string": "Authorize"
},
"uf1ttM": {
"string": "Rule reward value is required"
},
"ufD5Jr": {
"string": "Content type"
},
Expand Down Expand Up @@ -8511,6 +8534,9 @@
"v3WWK+": {
"string": "Status is invalid"
},
"vAxm7u": {
"string": "You must select a channel first and select at least one gift"
},
"vC8vyb": {
"context": "enabled status option label",
"string": "Enabled"
Expand Down
6 changes: 5 additions & 1 deletion src/components/Datagrid/customCells/cells.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,13 @@ export function tagsCell(
};
}

export function booleanCell(value: boolean): GridCell {
export function booleanCell(
value: boolean,
options: Partial<GridCell> = {},
): GridCell {
return {
...common,
...options,
allowOverlay: false,
kind: GridCellKind.Boolean,
data: value,
Expand Down
4 changes: 3 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export const defaultListSettings: AppListViewSettings = {
},
[ListViews.DISCOUNTS_LIST]: {
rowNumber: PAGINATE_BY,
columns: ["name", "startDate", "endDate"],
columns: ["name", "type", "startDate", "endDate"],
},
[ListViews.SHIPPING_METHODS_LIST]: {
columns: ["name", "countries"],
Expand Down Expand Up @@ -169,6 +169,7 @@ export const defaultListSettings: AppListViewSettings = {
"quantity",
"price",
"total",
"isGift",
"metadata",
],
},
Expand All @@ -182,6 +183,7 @@ export const defaultListSettings: AppListViewSettings = {
"quantity",
"price",
"total",
"isGift",
"metadata",
],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Rule } from "@dashboard/discounts/models";
import { DiscoutFormData } from "@dashboard/discounts/types";
import { useLabelMapsContext } from "@dashboard/discounts/views/DiscountDetails/context/context";
import {
PromotionDetailsFragment,
PromotionRuleCreateErrorFragment,
Expand Down Expand Up @@ -32,7 +33,6 @@ interface DiscountDetailsFormProps {
disabled: boolean;
data: PromotionDetailsFragment | undefined | null;
onSubmit: (data: DiscoutFormData) => void;
ruleConditionsOptionsDetailsMap: Record<string, string>;
onRuleUpdateSubmit: (
data: Rule,
) => Promise<Array<CommonError<PromotionRuleUpdateErrorFragment>>>;
Expand All @@ -50,7 +50,6 @@ export const DiscountDetailsForm = ({
onRuleCreateSubmit,
onRuleDeleteSubmit,
onRuleUpdateSubmit,
ruleConditionsOptionsDetailsMap,
}: DiscountDetailsFormProps) => {
const intl = useIntl();

Expand Down Expand Up @@ -82,12 +81,14 @@ export const DiscountDetailsForm = ({

const handleSubmit = methods.handleSubmit(onSubmit);

const { ruleConditionsValues, gifts } = useLabelMapsContext();
const { onDeleteRule, onRuleSubmit, rules, rulesErrors } = useRulesHandlers({
data,
onRuleCreateSubmit,
onRuleDeleteSubmit,
onRuleUpdateSubmit,
ruleConditionsOptionsDetailsMap,
ruleConditionsOptionsDetailsMap: ruleConditionsValues.labels,
giftsOptionsDetailsMap: gifts.labels,
});

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { getCurrentConditionsValuesLabels } from "../utils";
interface UseRulesHandlersProps {
data: PromotionDetailsFragment | undefined | null;
ruleConditionsOptionsDetailsMap: Record<string, string>;
giftsOptionsDetailsMap: Record<string, string>;
onRuleUpdateSubmit: (
data: Rule,
) => Promise<Array<CommonError<PromotionRuleUpdateErrorFragment>>>;
Expand All @@ -25,20 +26,27 @@ interface UseRulesHandlersProps {
export const useRulesHandlers = ({
data,
ruleConditionsOptionsDetailsMap,
giftsOptionsDetailsMap,
onRuleUpdateSubmit,
onRuleCreateSubmit,
onRuleDeleteSubmit,
}: UseRulesHandlersProps) => {
const [rulesErrors, setRulesErrors] = useState<Array<CommonError<any>>>([]);
const [labelsMap, setLabelMap] = useState<Record<string, string>>({});
const [conditionValuesLabelMap, setConditionValuesLabelMap] = useState<
Record<string, string>
>({});

const rules = sortRules(
data?.rules?.map(rule => mapAPIRuleToForm(data?.type, rule, labelsMap)) ??
[],
data?.rules?.map(rule =>
mapAPIRuleToForm(data?.type, rule, {
conditionsValues: conditionValuesLabelMap,
gifts: giftsOptionsDetailsMap,
}),
) ?? [],
);

useEffect(() => {
setLabelMap(labels => {
setConditionValuesLabelMap(labels => {
return {
...ruleConditionsOptionsDetailsMap,
...labels,
Expand All @@ -47,7 +55,7 @@ export const useRulesHandlers = ({
}, [ruleConditionsOptionsDetailsMap]);

const updateLabels = (rule: Rule) => {
setLabelMap(labels => ({
setConditionValuesLabelMap(labels => ({
...labels,
...getCurrentConditionsValuesLabels([rule]),
}));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { MockedProvider } from "@apollo/client/testing";
import { channelsList } from "@dashboard/channels/fixtures";
import { discount } from "@dashboard/discounts/fixtures";
import { discount, orderDiscount } from "@dashboard/discounts/fixtures";
import { LabelsMapsProvider } from "@dashboard/discounts/views/DiscountDetails/context/provider";
import {
conditionsValuesLabelsMock,
emptyGiftsLabelsMock,
giftsLabelsMock,
} from "@dashboard/discounts/views/DiscountDetails/hooks/mocks";
import React from "react";

import {
Expand All @@ -9,6 +15,7 @@ import {
searchProductsMock,
searchVariantsMock,
} from "../DiscountRules/componenets/RuleForm/components/RuleConditionValues/hooks/options/mocks";
import { variantsWithProductDataMock } from "../DiscountRules/componenets/RuleForm/components/RuleRewardGifts/mock";
import {
DiscountDetailsPage,
DiscountDetailsPageProps,
Expand All @@ -20,17 +27,10 @@ const props: DiscountDetailsPageProps = {
onBack: () => undefined,
onSubmit: () => undefined,
onDelete: () => undefined,
ruleConditionsOptionsDetailsMap: {
"UHJvZHVjdDo3OQ==": "Bean Juice",
"UHJvZHVjdDoxMTU=": "Black Hoodie",
UHJvZHVjdFZhcmlhbnQ6OTg3: "45cm x 45cm",
UHJvZHVjdFZhcmlhbnQ6MjE1: "1l",
},
errors: [],
onRuleCreateSubmit: () => Promise.resolve([]),
onRuleDeleteSubmit: () => Promise.resolve([]),
onRuleUpdateSubmit: () => Promise.resolve([]),
ruleConditionsOptionsDetailsLoading: false,
ruleCreateButtonState: "default",
ruleDeleteButtonState: "default",
ruleUpdateButtonState: "default",
Expand All @@ -51,8 +51,42 @@ export const Default = () => (
searchProductsMock,
searchCollectionsMock,
searchVariantsMock,
emptyGiftsLabelsMock,
conditionsValuesLabelsMock,
]}
>
<LabelsMapsProvider
promotionData={{
__typename: "Query",
promotion: discount,
}}
>
<DiscountDetailsPage {...props} />
</LabelsMapsProvider>
</MockedProvider>
);

export const OrderDiscounts = () => (
<MockedProvider
mocks={[
searchCategoriesMock,
searchProductsMock,
searchProductsMock,
searchProductsMock,
searchCollectionsMock,
searchVariantsMock,
giftsLabelsMock,
conditionsValuesLabelsMock,
variantsWithProductDataMock,
]}
>
<DiscountDetailsPage {...props} />
<LabelsMapsProvider
promotionData={{
__typename: "Query",
promotion: orderDiscount,
}}
>
<DiscountDetailsPage {...props} data={orderDiscount} />
</LabelsMapsProvider>
</MockedProvider>
);
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ import { DiscountSavebar } from "../DiscountSavebar";

export interface DiscountDetailsPageProps {
channels: ChannelFragment[];
ruleConditionsOptionsDetailsMap: Record<string, string>;
ruleConditionsOptionsDetailsLoading: boolean;
data: PromotionDetailsFragment | undefined | null;
disabled: boolean;
errors: PromotionUpdateErrorFragment[];
Expand All @@ -51,8 +49,6 @@ export interface DiscountDetailsPageProps {

export const DiscountDetailsPage = ({
channels,
ruleConditionsOptionsDetailsMap,
ruleConditionsOptionsDetailsLoading,
disabled,
data,
errors,
Expand All @@ -79,7 +75,6 @@ export const DiscountDetailsPage = ({
data={data}
disabled={disabled}
onSubmit={onSubmit}
ruleConditionsOptionsDetailsMap={ruleConditionsOptionsDetailsMap}
onRuleCreateSubmit={onRuleCreateSubmit}
onRuleDeleteSubmit={onRuleDeleteSubmit}
onRuleUpdateSubmit={onRuleUpdateSubmit}
Expand Down Expand Up @@ -111,7 +106,6 @@ export const DiscountDetailsPage = ({
discountType={discountType}
errors={rulesErrors}
rules={rules}
loading={ruleConditionsOptionsDetailsLoading}
getRuleConfirmButtonState={ruleEditIndex =>
ruleEditIndex !== null
? ruleUpdateButtonState
Expand Down
Loading

0 comments on commit bb2232b

Please sign in to comment.