Skip to content

Commit

Permalink
Improvments for discount catalog (#4565)
Browse files Browse the repository at this point in the history
* Add empty column to datagrid

* Fix loading of rules

* Update rule validation

* Show rule summary when no conditions

* Handle labels on rule update

* Improve loading rules

* Handle show selected labels

* Fix rules tests

* Update labels on rule add

* Improve adding condtions

* Move reward value to left

* Remove optional from description

* Fix show channel error

* Add changeset

* Update test

* Bump macaw

* Sort rule by name

* Improve details form submission

* Prevent refetch, write data into cache

* Improve rule sorting and update mutations

* Fix loading issue

* Fix ts issues

* Refactor to separate hooks

* Fix richtext

* Refactor useRulesHandlers to get rid of rules state and get data from api

* Show only initial loading

* Refactor and improve loading conditions options

* Fix jumpy condition multiselect

* Fix input heigh equal

* Change discount type switch height

* After CR improvments

* Fix ts issues
  • Loading branch information
poulch committed Jan 4, 2024
1 parent a2bac68 commit dc64404
Show file tree
Hide file tree
Showing 56 changed files with 875 additions and 236 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-mangos-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Improvments for discount rules
9 changes: 9 additions & 0 deletions locale/defaultMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,9 @@
"context": "Payment card title",
"string": "Payment balance"
},
"7MUx0T": {
"string": "Discount of {value} through the {channel}"
},
"7NFfmz": {
"string": "Products"
},
Expand Down Expand Up @@ -5205,6 +5208,9 @@
"XtlUj6": {
"string": "Add your first rule to set up a promotion"
},
"Xu4ST7": {
"string": "No conditions added, click button bellow to create one"
},
"Xu4ech": {
"context": "deactivate app",
"string": "Are you sure you want to disable this app? Your data will be kept until you reactivate the app."
Expand Down Expand Up @@ -8812,6 +8818,9 @@
"y/UWBR": {
"string": "There is no address to show for this customer"
},
"y08GTW": {
"string": "Channel is required"
},
"y7mfbl": {
"string": "Currently, there are no countries assigned to this shipping zone"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Rule } from "@dashboard/discounts/models";
import { sortRules } from "@dashboard/discounts/utils";
import { useState } from "react";

export const useRulesHandlers = () => {
Expand All @@ -17,7 +18,7 @@ export const useRulesHandlers = () => {
return rules;
});
} else {
setRules([...rules, ruleObj]);
setRules(sortRules([...rules, ruleObj]));
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import { DashboardCard } from "@dashboard/components/Card";
import RichTextEditor from "@dashboard/components/RichTextEditor";
import { RichTextEditorLoading } from "@dashboard/components/RichTextEditor/RichTextEditorLoading";
import { DiscoutFormData } from "@dashboard/discounts/types";
import { commonMessages } from "@dashboard/intl";
import { useRichTextContext } from "@dashboard/utils/richText/context";
import React from "react";
import { useController } from "react-hook-form";
import { FormattedMessage, useIntl } from "react-intl";
import { FormattedMessage } from "react-intl";

interface DiscountDescriptionProps {
disabled?: boolean;
Expand All @@ -17,7 +16,6 @@ export const DiscountDescription = ({
disabled = false,
error = false,
}: DiscountDescriptionProps) => {
const intl = useIntl();
const { defaultValue, editorRef, isReadyForMount, handleChange } =
useRichTextContext();

Expand All @@ -43,7 +41,7 @@ export const DiscountDescription = ({
disabled={disabled}
error={error}
helperText=""
label={intl.formatMessage(commonMessages.optionalField)}
label=" "
name="description"
/>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { RichTextContext } from "@dashboard/utils/richText/context";
import useRichText from "@dashboard/utils/richText/useRichText";
import { zodResolver } from "@hookform/resolvers/zod";
import React, { ReactNode } from "react";
import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import { FormProvider, useForm } from "react-hook-form";
import { useIntl } from "react-intl";

import { getValidationSchema } from "../DiscountCreateForm/validationSchema";
Expand Down Expand Up @@ -75,13 +75,7 @@ export const DiscountDetailsForm = ({
triggerChange: methods.trigger,
});

const handleSubmit: SubmitHandler<DiscoutFormData> = formData => {
if (!methods.formState.isDirty) {
return;
}

return onSubmit(formData);
};
const handleSubmit = methods.handleSubmit(onSubmit);

const { onDeleteRule, onRuleSubmit, rules, rulesErrors } = useRulesHandlers({
data,
Expand All @@ -94,11 +88,11 @@ export const DiscountDetailsForm = ({
return (
<RichTextContext.Provider value={richText}>
<FormProvider {...methods}>
<form onSubmit={methods.handleSubmit(handleSubmit)}>
<form onSubmit={handleSubmit}>
{children({
rulesErrors,
rules,
onSubmit: methods.handleSubmit(handleSubmit),
onSubmit: handleSubmit,
onRuleSubmit,
onDeleteRule,
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
import { CommonError } from "@dashboard/utils/errors/common";
import { useEffect, useState } from "react";

import { getCurrentConditionsValuesLabels } from "../utils";

interface UseRulesHandlersProps {
data: PromotionDetailsFragment | undefined | null;
ruleConditionsOptionsDetailsMap: Record<string, string>;
Expand All @@ -26,18 +28,26 @@ export const useRulesHandlers = ({
onRuleCreateSubmit,
onRuleDeleteSubmit,
}: UseRulesHandlersProps) => {
const [rules, setRules] = useState<Rule[]>([]);
const [rulesErrors, setRulesErrors] = useState<Array<CommonError<any>>>([]);
const [labelsMap, setLabelMap] = useState<Record<string, string>>({});

const rules = data?.rules?.map(rule => Rule.fromAPI(rule, labelsMap)) ?? [];

useEffect(() => {
if (data?.rules) {
setRules(
data.rules.map(rule =>
Rule.fromAPI(rule, ruleConditionsOptionsDetailsMap),
) ?? [],
);
}
}, [data?.rules, ruleConditionsOptionsDetailsMap]);
setLabelMap(labels => {
return {
...ruleConditionsOptionsDetailsMap,
...labels,
};
});
}, [ruleConditionsOptionsDetailsMap]);

const updateLabels = (rule: Rule) => {
setLabelMap(labels => ({
...labels,
...getCurrentConditionsValuesLabels([rule]),
}));
};

const onRuleSubmit = async (rule: Rule, ruleEditIndex: number | null) => {
let errors: Array<
Expand All @@ -46,9 +56,10 @@ export const useRulesHandlers = ({
>
> = [];
const ruleObj = Rule.fromFormValues(rule);

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

if (errors.length > 0) {
setRulesErrors(errors);
}
Expand Down
34 changes: 34 additions & 0 deletions src/discounts/components/DiscountDetailsForm/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Rule } from "@dashboard/discounts/models";

import { getCurrentConditionsValuesLabels } from "./utils";

describe("getCurrentConditionsValuesLabels", () => {
it("should return empty object if no rules", () => {
expect(getCurrentConditionsValuesLabels([])).toEqual({});
});

it("should return empty object if no conditions", () => {
expect(
getCurrentConditionsValuesLabels([
{ conditions: [] },
] as unknown as Rule[]),
).toEqual({});
});

it("should return empty object if no values", () => {
expect(
getCurrentConditionsValuesLabels([
{ conditions: [{ values: [] }] },
] as unknown as Rule[]),
).toEqual({});
});

it("should return object with value as key and label as value", () => {
expect(
getCurrentConditionsValuesLabels([
{ conditions: [{ values: [{ value: "test", label: "test2" }] }] },
{ conditions: [{ values: [{ value: "test3", label: "test4" }] }] },
] as unknown as Rule[]),
).toEqual({ test: "test2", test3: "test4" });
});
});
14 changes: 14 additions & 0 deletions src/discounts/components/DiscountDetailsForm/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Rule } from "@dashboard/discounts/models";

export const getCurrentConditionsValuesLabels = (rules: Rule[]) => {
return rules
.flatMap(rule => rule.conditions)
.flatMap(condition => condition.values)
.reduce((acc, value) => {
// Initali value and label might contain id
if (value.value !== value.label) {
acc[value.value] = value.label;
}
return acc;
}, {} as Record<string, string>);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { TopNav } from "@dashboard/components/AppLayout";
import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton";
import { DetailPageLayout } from "@dashboard/components/Layouts";
import Savebar from "@dashboard/components/Savebar";
import { discountListUrl } from "@dashboard/discounts/discountsUrls";
import { Rule } from "@dashboard/discounts/models";
import { DiscoutFormData } from "@dashboard/discounts/types";
Expand All @@ -25,6 +24,7 @@ import { DiscountDescription } from "../DiscountDescription";
import { DiscountDetailsForm } from "../DiscountDetailsForm";
import { DiscountName } from "../DiscountName";
import { DiscountRules } from "../DiscountRules";
import { DiscountSavebar } from "../DiscountSavebar";

export interface DiscountDetailsPageProps {
channels: ChannelFragment[];
Expand Down Expand Up @@ -114,12 +114,12 @@ export const DiscountDetailsPage = ({
disabled={disabled}
/>

<Savebar
<DiscountSavebar
disabled={disabled}
onCancel={onBack}
onSubmit={onSubmit}
onDelete={onDelete}
state={submitButtonState}
submitButtonState={submitButtonState}
/>
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DatagridChangeStateContext,
useDatagridChangeState,
} from "@dashboard/components/Datagrid/hooks/useDatagridChange";
import { useEmptyColumn } from "@dashboard/components/Datagrid/hooks/useEmptyColumn";
import { TablePaginationWithContext } from "@dashboard/components/TablePagination";
import {
DiscountListUrlSortField,
Expand Down Expand Up @@ -45,9 +46,11 @@ export const DiscountListDatagrid = ({
const intl = useIntl();
const datagrid = useDatagridChangeState();

const emptyColumn = useEmptyColumn();

const discountListStaticColumns = useMemo(
() => dicountListStaticColumnsAdapter(intl, sort),
[intl, sort],
() => dicountListStaticColumnsAdapter(intl, sort, emptyColumn),
[intl, sort, emptyColumn],
);

const onColumnChange = useCallback(
Expand Down Expand Up @@ -116,7 +119,7 @@ export const DiscountListDatagrid = ({
hasRowHover={hasRowHover}
onColumnMoved={handlers.onMove}
onColumnResize={handlers.onResize}
verticalBorder={col => col > 0}
verticalBorder={col => col > 1}
rows={promotions?.length ?? 0}
availableColumns={visibleColumns}
emptyText={intl.formatMessage(messages.empty)}
Expand Down
2 changes: 2 additions & 0 deletions src/discounts/components/DiscountListDatagrid/datagrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import { columnsMessages } from "./messages";
export const dicountListStaticColumnsAdapter = (
intl: IntlShape,
sort: Sort<DiscountListUrlSortField>,
emptyColumn: AvailableColumn,
) =>
[
emptyColumn,
{
id: "name",
title: intl.formatMessage(columnsMessages.name),
Expand Down
Loading

0 comments on commit dc64404

Please sign in to comment.