commit
47dc872eeb
21 changed files with 2259 additions and 1237 deletions
|
@ -36,3 +36,4 @@ All notable, unreleased changes to this project will be documented in this file.
|
|||
- Add git hooks - #209 by @dominik-zeglen
|
||||
- Do not send customer invitation email - #211 by @dominik-zeglen
|
||||
- Send address update mutation only once - #210 by @dominik-zeglen
|
||||
- Update sale details design - #207 by @dominik-zeglen
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2019-10-09T15:30:47.333Z\n"
|
||||
"POT-Creation-Date: 2019-10-15T15:56:00.137Z\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -99,6 +99,14 @@ msgctxt "staff member status"
|
|||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/DiscountDates/DiscountDates.json
|
||||
#. [src.discounts.components.DiscountDates.1662220323] - time during discount is active, header
|
||||
#. defaultMessage is:
|
||||
#. Active Dates
|
||||
msgctxt "time during discount is active, header"
|
||||
msgid "Active Dates"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherDates/VoucherDates.json
|
||||
#. [src.discounts.components.VoucherDates.1662220323] - time during voucher is active, header
|
||||
#. defaultMessage is:
|
||||
|
@ -3235,12 +3243,12 @@ msgctxt "description"
|
|||
msgid "Discount Code"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherValue/VoucherValue.json
|
||||
#. [src.discounts.components.VoucherValue.1971417066]
|
||||
#: build/locale/src/discounts/components/SaleType/SaleType.json
|
||||
#. [src.discounts.components.SaleType.3216816841] - percentage or fixed, header
|
||||
#. defaultMessage is:
|
||||
#. Discount Specific Information
|
||||
msgctxt "description"
|
||||
msgid "Discount Specific Information"
|
||||
#. Discount Type
|
||||
msgctxt "percentage or fixed, header"
|
||||
msgid "Discount Type"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherTypes/VoucherTypes.json
|
||||
|
@ -3251,10 +3259,14 @@ msgctxt "header"
|
|||
msgid "Discount Type"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/SalePricing/SalePricing.json
|
||||
#. [src.discounts.components.SalePricing.1205967018]
|
||||
#: build/locale/src/discounts/components/SaleValue/SaleValue.json
|
||||
#. [src.discounts.components.SaleValue.1205967018] - sale discount
|
||||
#. defaultMessage is:
|
||||
#. Discount Value
|
||||
msgctxt "sale discount"
|
||||
msgid "Discount Value"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherValue/VoucherValue.json
|
||||
#. [src.discounts.components.VoucherValue.1205967018]
|
||||
#. defaultMessage is:
|
||||
|
@ -3659,6 +3671,14 @@ msgctxt "description"
|
|||
msgid "First Name"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/SaleType/SaleType.json
|
||||
#. [src.discounts.components.SaleType.46415128] - discount type
|
||||
#. defaultMessage is:
|
||||
#. Fixed Amount
|
||||
msgctxt "discount type"
|
||||
msgid "Fixed Amount"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherTypes/VoucherTypes.json
|
||||
#. [src.discounts.components.VoucherTypes.46415128] - voucher discount type
|
||||
#. defaultMessage is:
|
||||
|
@ -5607,6 +5627,14 @@ msgctxt "order history message"
|
|||
msgid "Payment was voided"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/SaleType/SaleType.json
|
||||
#. [src.discounts.components.SaleType.3688224049] - discount type
|
||||
#. defaultMessage is:
|
||||
#. Percentage
|
||||
msgctxt "discount type"
|
||||
msgid "Percentage"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherTypes/VoucherTypes.json
|
||||
#. [src.discounts.components.VoucherTypes.3688224049] - voucher discount type
|
||||
#. defaultMessage is:
|
||||
|
@ -5875,14 +5903,6 @@ msgctxt "variant creation step"
|
|||
msgid "Prices and SKU"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/SalePricing/SalePricing.json
|
||||
#. [src.discounts.components.SalePricing.1099355007] - sale pricing, header
|
||||
#. defaultMessage is:
|
||||
#. Pricing
|
||||
msgctxt "sale pricing, header"
|
||||
msgid "Pricing"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/products/components/ProductPricing/ProductPricing.json
|
||||
#. [src.products.components.ProductPricing.1099355007] - product pricing
|
||||
#. defaultMessage is:
|
||||
|
@ -7091,6 +7111,10 @@ msgctxt "button"
|
|||
msgid "Set as default shipping address"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/DiscountDates/DiscountDates.json
|
||||
#. [src.discounts.components.DiscountDates.1596226028] - voucher end date, switch button
|
||||
#. defaultMessage is:
|
||||
#. Set end date
|
||||
#: build/locale/src/discounts/components/VoucherDates/VoucherDates.json
|
||||
#. [src.discounts.components.VoucherDates.1596226028] - voucher end date, switch button
|
||||
#. defaultMessage is:
|
||||
|
@ -7879,14 +7903,6 @@ msgctxt "description"
|
|||
msgid "This will be shown to customers at checkout"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/SalePricing/SalePricing.json
|
||||
#. [src.discounts.components.SalePricing.2503204759] - time during which sale is active
|
||||
#. defaultMessage is:
|
||||
#. Time Frame
|
||||
msgctxt "time during which sale is active"
|
||||
msgid "Time Frame"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/pages/components/PageInfo/PageInfo.json
|
||||
#. [src.pages.components.PageInfo.1124600214] - page title
|
||||
#. defaultMessage is:
|
||||
|
@ -8555,6 +8571,14 @@ msgctxt "sale value"
|
|||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/SaleValue/SaleValue.json
|
||||
#. [src.discounts.components.SaleValue.1148029984] - sale value, header
|
||||
#. defaultMessage is:
|
||||
#. Value
|
||||
msgctxt "sale value, header"
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherList/VoucherList.json
|
||||
#. [src.discounts.components.VoucherList.1148029984] - voucher value
|
||||
#. defaultMessage is:
|
||||
|
@ -8787,6 +8811,14 @@ msgctxt "description"
|
|||
msgid "Voucher Name"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherValue/VoucherValue.json
|
||||
#. [src.discounts.components.VoucherValue.1960678372]
|
||||
#. defaultMessage is:
|
||||
#. Voucher Specific Information
|
||||
msgctxt "description"
|
||||
msgid "Voucher Specific Information"
|
||||
msgstr ""
|
||||
|
||||
#: build/locale/src/discounts/components/VoucherDetailsPage/VoucherDetailsPage.json
|
||||
#. [src.discounts.components.VoucherDetailsPage.2071139683]
|
||||
#. defaultMessage is:
|
||||
|
|
|
@ -5,28 +5,39 @@ import FormLabel from "@material-ui/core/FormLabel";
|
|||
import MenuItem from "@material-ui/core/MenuItem";
|
||||
import Radio from "@material-ui/core/Radio";
|
||||
import RadioGroup from "@material-ui/core/RadioGroup";
|
||||
import { createStyles, withStyles, WithStyles } from "@material-ui/core/styles";
|
||||
import { Theme } from "@material-ui/core/styles";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import classNames from "classnames";
|
||||
import React from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
const styles = createStyles({
|
||||
formControl: {
|
||||
const useStyles = makeStyles(
|
||||
(theme: Theme) => ({
|
||||
formLabel: {
|
||||
marginBottom: theme.spacing.unit
|
||||
},
|
||||
radioLabel: {
|
||||
marginBottom: -theme.spacing.unit * 1.5
|
||||
},
|
||||
root: {
|
||||
"& $radioLabel": {
|
||||
"&:last-of-type": {
|
||||
marginBottom: 0
|
||||
}
|
||||
},
|
||||
padding: 0,
|
||||
width: "100%"
|
||||
},
|
||||
formLabel: {
|
||||
marginLeft: "-5px",
|
||||
paddingBottom: "10px"
|
||||
},
|
||||
radioLabel: {
|
||||
"& > span": {
|
||||
padding: "6px"
|
||||
rootNoLabel: {
|
||||
marginTop: -theme.spacing.unit * 1.5
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "RadioGroupField"
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
interface RadioGroupFieldChoice {
|
||||
export interface RadioGroupFieldChoice {
|
||||
value: string;
|
||||
label: React.ReactNode;
|
||||
}
|
||||
|
@ -39,16 +50,13 @@ interface RadioGroupFieldProps {
|
|||
hint?: string;
|
||||
label?: string;
|
||||
name?: string;
|
||||
value?: string;
|
||||
value: string;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
export const RadioGroupField = withStyles(styles, {
|
||||
name: "RadioGroupField"
|
||||
})(
|
||||
({
|
||||
export const RadioGroupField: React.FC<RadioGroupFieldProps> = props => {
|
||||
const {
|
||||
className,
|
||||
classes,
|
||||
disabled,
|
||||
error,
|
||||
label,
|
||||
|
@ -57,10 +65,14 @@ export const RadioGroupField = withStyles(styles, {
|
|||
onChange,
|
||||
name,
|
||||
hint
|
||||
}: RadioGroupFieldProps & WithStyles<typeof styles>) => {
|
||||
} = props;
|
||||
const classes = useStyles(props);
|
||||
|
||||
return (
|
||||
<FormControl
|
||||
className={classNames(classes.formControl, className)}
|
||||
className={classNames(classes.root, className, {
|
||||
[classes.rootNoLabel]: !label
|
||||
})}
|
||||
error={error}
|
||||
disabled={disabled}
|
||||
>
|
||||
|
@ -92,7 +104,6 @@ export const RadioGroupField = withStyles(styles, {
|
|||
{hint && <FormHelperText>{hint}</FormHelperText>}
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
RadioGroupField.displayName = "RadioGroupField";
|
||||
export default RadioGroupField;
|
||||
|
|
119
src/discounts/components/DiscountDates/DiscountDates.tsx
Normal file
119
src/discounts/components/DiscountDates/DiscountDates.tsx
Normal file
|
@ -0,0 +1,119 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "../../../types";
|
||||
|
||||
interface DiscountDatesProps {
|
||||
data: {
|
||||
endDate: string;
|
||||
endTime: string;
|
||||
hasEndDate: boolean;
|
||||
startDate: string;
|
||||
startTime: string;
|
||||
};
|
||||
defaultCurrency: string;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"endDate" | "startDate">;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
const DiscountDates = ({
|
||||
data,
|
||||
disabled,
|
||||
errors,
|
||||
onChange
|
||||
}: DiscountDatesProps) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Active Dates",
|
||||
description: "time during discount is active, header"
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
name={"startDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startDate)}
|
||||
value={data.startDate}
|
||||
type="date"
|
||||
InputLabelProps={{
|
||||
shrink: true
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
name={"startTime" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startHour)}
|
||||
value={data.startTime}
|
||||
type="time"
|
||||
InputLabelProps={{
|
||||
shrink: true
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
<ControlledCheckbox
|
||||
checked={data.hasEndDate}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Set end date",
|
||||
description: "voucher end date, switch button"
|
||||
})}
|
||||
name={"hasEndDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
/>
|
||||
{data.hasEndDate && (
|
||||
<Grid variant="uniform">
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
name={"endDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endDate)}
|
||||
value={data.endDate}
|
||||
type="date"
|
||||
InputLabelProps={{
|
||||
shrink: true
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
name={"endTime" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endHour)}
|
||||
value={data.endTime}
|
||||
type="time"
|
||||
InputLabelProps={{
|
||||
shrink: true
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
export default DiscountDates;
|
2
src/discounts/components/DiscountDates/index.ts
Normal file
2
src/discounts/components/DiscountDates/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./DiscountDates";
|
||||
export * from "./DiscountDates";
|
|
@ -11,16 +11,20 @@ import PageHeader from "@saleor/components/PageHeader";
|
|||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { UserError } from "../../../types";
|
||||
import { SaleType } from "../../../types/globalTypes";
|
||||
import { SaleType as SaleTypeEnum } from "../../../types/globalTypes";
|
||||
import DiscountDates from "../DiscountDates";
|
||||
import SaleInfo from "../SaleInfo";
|
||||
import SalePricing from "../SalePricing";
|
||||
import SaleType from "../SaleType";
|
||||
|
||||
export interface FormData {
|
||||
endDate: string;
|
||||
endTime: string;
|
||||
hasEndDate: boolean;
|
||||
name: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
startTime: string;
|
||||
type: SaleTypeEnum;
|
||||
value: string;
|
||||
type: SaleType;
|
||||
}
|
||||
|
||||
export interface SaleCreatePageProps {
|
||||
|
@ -44,9 +48,12 @@ const SaleCreatePage: React.StatelessComponent<SaleCreatePageProps> = ({
|
|||
|
||||
const initialForm: FormData = {
|
||||
endDate: "",
|
||||
endTime: "",
|
||||
hasEndDate: false,
|
||||
name: "",
|
||||
startDate: "",
|
||||
type: SaleType.FIXED,
|
||||
startTime: "",
|
||||
type: SaleTypeEnum.FIXED,
|
||||
value: ""
|
||||
};
|
||||
return (
|
||||
|
@ -71,10 +78,12 @@ const SaleCreatePage: React.StatelessComponent<SaleCreatePageProps> = ({
|
|||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<SalePricing
|
||||
<SaleType data={data} disabled={disabled} onChange={change} />
|
||||
<CardSpacer />
|
||||
<DiscountDates
|
||||
data={data}
|
||||
defaultCurrency={defaultCurrency}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
onChange={change}
|
||||
/>
|
||||
|
|
|
@ -11,23 +11,28 @@ import PageHeader from "@saleor/components/PageHeader";
|
|||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||
import { Tab, TabContainer } from "@saleor/components/Tab";
|
||||
import { sectionNames } from "@saleor/intl";
|
||||
import { maybe } from "../../../misc";
|
||||
import { maybe, splitDateTime } from "../../../misc";
|
||||
import { ListProps, TabListActions, UserError } from "../../../types";
|
||||
import { SaleType } from "../../../types/globalTypes";
|
||||
import { SaleType as SaleTypeEnum } from "../../../types/globalTypes";
|
||||
import { SaleDetails_sale } from "../../types/SaleDetails";
|
||||
import DiscountCategories from "../DiscountCategories";
|
||||
import DiscountCollections from "../DiscountCollections";
|
||||
import DiscountDates from "../DiscountDates";
|
||||
import DiscountProducts from "../DiscountProducts";
|
||||
import SaleInfo from "../SaleInfo";
|
||||
import SalePricing from "../SalePricing";
|
||||
import SaleSummary from "../SaleSummary";
|
||||
import SaleType from "../SaleType";
|
||||
import SaleValue from "../SaleValue";
|
||||
|
||||
export interface FormData {
|
||||
endDate: string;
|
||||
endTime: string;
|
||||
hasEndDate: boolean;
|
||||
name: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
startTime: string;
|
||||
type: SaleTypeEnum;
|
||||
value: string;
|
||||
type: SaleType;
|
||||
}
|
||||
|
||||
export enum SaleDetailsPageTab {
|
||||
|
@ -106,10 +111,13 @@ const SaleDetailsPage: React.StatelessComponent<SaleDetailsPageProps> = ({
|
|||
const intl = useIntl();
|
||||
|
||||
const initialForm: FormData = {
|
||||
endDate: maybe(() => (sale.endDate ? sale.endDate : ""), ""),
|
||||
endDate: splitDateTime(maybe(() => sale.endDate, "")).date,
|
||||
endTime: splitDateTime(maybe(() => sale.endDate, "")).time,
|
||||
hasEndDate: maybe(() => !!sale.endDate),
|
||||
name: maybe(() => sale.name, ""),
|
||||
startDate: maybe(() => sale.startDate, ""),
|
||||
type: maybe(() => sale.type, SaleType.FIXED),
|
||||
startDate: splitDateTime(maybe(() => sale.startDate, "")).date,
|
||||
startTime: splitDateTime(maybe(() => sale.startDate, "")).time,
|
||||
type: maybe(() => sale.type, SaleTypeEnum.FIXED),
|
||||
value: maybe(() => sale.value.toString(), "")
|
||||
};
|
||||
return (
|
||||
|
@ -129,9 +137,11 @@ const SaleDetailsPage: React.StatelessComponent<SaleDetailsPageProps> = ({
|
|||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<SalePricing
|
||||
<SaleType data={data} disabled={disabled} onChange={change} />
|
||||
<CardSpacer />
|
||||
<SaleValue
|
||||
currencySymbol={defaultCurrency}
|
||||
data={data}
|
||||
defaultCurrency={defaultCurrency}
|
||||
disabled={disabled}
|
||||
errors={formErrors}
|
||||
onChange={change}
|
||||
|
@ -243,6 +253,14 @@ const SaleDetailsPage: React.StatelessComponent<SaleDetailsPageProps> = ({
|
|||
toolbar={productListToolbar}
|
||||
/>
|
||||
)}
|
||||
<CardSpacer />
|
||||
<DiscountDates
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
errors={formErrors}
|
||||
onChange={change}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<SaleSummary defaultCurrency={defaultCurrency} sale={sale} />
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import {
|
||||
createStyles,
|
||||
Theme,
|
||||
WithStyles,
|
||||
withStyles
|
||||
} from "@material-ui/core/styles";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import Hr from "@saleor/components/Hr";
|
||||
import TextFieldWithChoice from "@saleor/components/TextFieldWithChoice";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { FormErrors } from "../../../types";
|
||||
import { SaleType } from "../../../types/globalTypes";
|
||||
import { FormData } from "../SaleDetailsPage";
|
||||
|
||||
export interface SalePricingProps {
|
||||
data: FormData;
|
||||
defaultCurrency: string;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"startDate" | "endDate" | "value">;
|
||||
onChange: (event: React.ChangeEvent<any>) => void;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
display: "grid",
|
||||
gridColumnGap: theme.spacing.unit * 2 + "px",
|
||||
gridTemplateColumns: "1fr 1fr"
|
||||
},
|
||||
subheading: {
|
||||
gridColumnEnd: "span 2",
|
||||
marginBottom: theme.spacing.unit * 2
|
||||
}
|
||||
});
|
||||
|
||||
const SalePricing = withStyles(styles, {
|
||||
name: "SalePricing"
|
||||
})(
|
||||
({
|
||||
classes,
|
||||
data,
|
||||
defaultCurrency,
|
||||
disabled,
|
||||
errors,
|
||||
onChange
|
||||
}: SalePricingProps & WithStyles<typeof styles>) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Pricing",
|
||||
description: "sale pricing, header"
|
||||
})}
|
||||
/>
|
||||
<CardContent className={classes.root}>
|
||||
<TextFieldWithChoice
|
||||
disabled={disabled}
|
||||
ChoiceProps={{
|
||||
label: data.type === SaleType.FIXED ? defaultCurrency : "%",
|
||||
name: "type",
|
||||
values: [
|
||||
{
|
||||
label: defaultCurrency,
|
||||
value: SaleType.FIXED
|
||||
},
|
||||
{
|
||||
label: "%",
|
||||
value: SaleType.PERCENTAGE
|
||||
}
|
||||
]
|
||||
}}
|
||||
error={!!errors.value}
|
||||
helperText={errors.value}
|
||||
name={"value" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Discount Value"
|
||||
})}
|
||||
value={data.value}
|
||||
type="number"
|
||||
fullWidth
|
||||
inputProps={{
|
||||
min: 0
|
||||
}}
|
||||
/>
|
||||
</CardContent>
|
||||
<Hr />
|
||||
<CardContent className={classes.root}>
|
||||
<Typography className={classes.subheading} variant="subtitle1">
|
||||
<FormattedMessage
|
||||
defaultMessage="Time Frame"
|
||||
description="time during which sale is active"
|
||||
/>
|
||||
</Typography>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.startDate}
|
||||
helperText={errors.startDate}
|
||||
name={"startDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.startDate)}
|
||||
value={data.startDate}
|
||||
type="date"
|
||||
InputLabelProps={{
|
||||
shrink: true
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
error={!!errors.endDate}
|
||||
helperText={errors.endDate}
|
||||
name={"endDate" as keyof FormData}
|
||||
onChange={onChange}
|
||||
label={intl.formatMessage(commonMessages.endDate)}
|
||||
value={data.endDate}
|
||||
type="date"
|
||||
InputLabelProps={{
|
||||
shrink: true
|
||||
}}
|
||||
fullWidth
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
);
|
||||
SalePricing.displayName = "SalePricing";
|
||||
export default SalePricing;
|
|
@ -1,2 +0,0 @@
|
|||
export { default } from "./SalePricing";
|
||||
export * from "./SalePricing";
|
84
src/discounts/components/SaleType/SaleType.tsx
Normal file
84
src/discounts/components/SaleType/SaleType.tsx
Normal file
|
@ -0,0 +1,84 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import { Theme } from "@material-ui/core/styles";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import React from "react";
|
||||
import { IntlShape, useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import RadioGroupField, {
|
||||
RadioGroupFieldChoice
|
||||
} from "@saleor/components/RadioGroupField";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import { SaleType as SaleTypeEnum } from "@saleor/types/globalTypes";
|
||||
import { FormData } from "../SaleDetailsPage";
|
||||
|
||||
export interface SaleTypeProps {
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
onChange: FormChange;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles(
|
||||
(theme: Theme) => ({
|
||||
root: {
|
||||
"&&": {
|
||||
paddingBottom: theme.spacing.unit * 1.5
|
||||
}
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "SaleType"
|
||||
}
|
||||
);
|
||||
|
||||
function createChoices(intl: IntlShape): RadioGroupFieldChoice[] {
|
||||
return [
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Percentage",
|
||||
description: "discount type"
|
||||
}),
|
||||
value: SaleTypeEnum.PERCENTAGE
|
||||
},
|
||||
{
|
||||
label: intl.formatMessage({
|
||||
defaultMessage: "Fixed Amount",
|
||||
description: "discount type"
|
||||
}),
|
||||
value: SaleTypeEnum.FIXED
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
const SaleType: React.FC<SaleTypeProps> = props => {
|
||||
const { data, disabled, onChange } = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
const intl = useIntl();
|
||||
|
||||
const choices = createChoices(intl);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Discount Type",
|
||||
description: "percentage or fixed, header"
|
||||
})}
|
||||
/>
|
||||
<CardContent className={classes.root}>
|
||||
<RadioGroupField
|
||||
choices={choices}
|
||||
disabled={disabled}
|
||||
name={"type" as keyof FormData}
|
||||
value={data.type}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
SaleType.displayName = "SaleType";
|
||||
export default SaleType;
|
2
src/discounts/components/SaleType/index.ts
Normal file
2
src/discounts/components/SaleType/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./SaleType";
|
||||
export * from "./SaleType";
|
61
src/discounts/components/SaleValue/SaleValue.tsx
Normal file
61
src/discounts/components/SaleValue/SaleValue.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import { FormErrors } from "@saleor/types";
|
||||
import { SaleType } from "@saleor/types/globalTypes";
|
||||
import { FormData } from "../SaleDetailsPage";
|
||||
|
||||
export interface SaleValueProps {
|
||||
currencySymbol: string;
|
||||
data: FormData;
|
||||
disabled: boolean;
|
||||
errors: FormErrors<"value">;
|
||||
onChange: FormChange;
|
||||
}
|
||||
|
||||
const SaleValue: React.FC<SaleValueProps> = ({
|
||||
currencySymbol,
|
||||
data,
|
||||
disabled,
|
||||
errors,
|
||||
onChange
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Value",
|
||||
description: "sale value, header"
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
fullWidth
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Discount Value",
|
||||
description: "sale discount"
|
||||
})}
|
||||
error={!!errors.value}
|
||||
name="value"
|
||||
InputProps={{
|
||||
endAdornment: data.type === SaleType.FIXED ? currencySymbol : "%"
|
||||
}}
|
||||
helperText={errors.value}
|
||||
value={data.value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
SaleValue.displayName = "SaleValue";
|
||||
export default SaleValue;
|
2
src/discounts/components/SaleValue/index.ts
Normal file
2
src/discounts/components/SaleValue/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./SaleValue";
|
||||
export * from "./SaleValue";
|
|
@ -23,8 +23,8 @@ import {
|
|||
import { VoucherDetails_voucher } from "../../types/VoucherDetails";
|
||||
import DiscountCategories from "../DiscountCategories";
|
||||
import DiscountCollections from "../DiscountCollections";
|
||||
import DiscountDates from "../DiscountDates";
|
||||
import DiscountProducts from "../DiscountProducts";
|
||||
import VoucherDates from "../VoucherDates";
|
||||
import VoucherInfo from "../VoucherInfo";
|
||||
import VoucherLimits from "../VoucherLimits";
|
||||
import VoucherRequirements from "../VoucherRequirements";
|
||||
|
@ -349,7 +349,7 @@ const VoucherDetailsPage: React.StatelessComponent<VoucherDetailsPageProps> = ({
|
|||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<VoucherDates
|
||||
<DiscountDates
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
defaultCurrency={defaultCurrency}
|
||||
|
|
|
@ -70,7 +70,9 @@ const VoucherRequirements = ({
|
|||
value={data.requirementsPicker}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<FormSpacer />
|
||||
{[RequirementsPicker.ORDER, RequirementsPicker.ITEM].includes(
|
||||
data.requirementsPicker
|
||||
) && <FormSpacer />}
|
||||
{data.requirementsPicker === RequirementsPicker.ORDER ? (
|
||||
<TextField
|
||||
disabled={disabled}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import { Theme } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import { makeStyles } from "@material-ui/styles";
|
||||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
|
@ -29,14 +31,21 @@ export enum VoucherType {
|
|||
SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT"
|
||||
}
|
||||
|
||||
const VoucherValue = ({
|
||||
data,
|
||||
defaultCurrency,
|
||||
disabled,
|
||||
errors,
|
||||
variant,
|
||||
onChange
|
||||
}: VoucherValueProps) => {
|
||||
const useStyles = makeStyles(
|
||||
(theme: Theme) => ({
|
||||
hr: {
|
||||
margin: `${theme.spacing.unit * 2}px 0`
|
||||
}
|
||||
}),
|
||||
{
|
||||
name: "VoucherValue"
|
||||
}
|
||||
);
|
||||
|
||||
const VoucherValue: React.FC<VoucherValueProps> = props => {
|
||||
const { data, defaultCurrency, disabled, errors, variant, onChange } = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
const intl = useIntl();
|
||||
|
||||
const translatedVoucherTypes = translateVoucherTypes(intl);
|
||||
|
@ -81,22 +90,22 @@ const VoucherValue = ({
|
|||
<FormSpacer />
|
||||
{variant === "update" && (
|
||||
<>
|
||||
<Hr className={classes.hr} />
|
||||
<RadioGroupField
|
||||
choices={voucherTypeChoices}
|
||||
disabled={disabled}
|
||||
error={!!errors.type}
|
||||
hint={errors.type}
|
||||
label={intl.formatMessage({
|
||||
defaultMessage: "Discount Specific Information"
|
||||
defaultMessage: "Voucher Specific Information"
|
||||
})}
|
||||
name={"type" as keyof FormData}
|
||||
value={data.type}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<FormSpacer />
|
||||
</>
|
||||
)}
|
||||
<Hr />
|
||||
<Hr className={classes.hr} />
|
||||
<FormSpacer />
|
||||
<ControlledCheckbox
|
||||
name={"applyOncePerOrder" as keyof FormData}
|
||||
|
|
|
@ -22,7 +22,7 @@ import { DEFAULT_INITIAL_SEARCH_DATA, PAGINATE_BY } from "../../config";
|
|||
import SearchCategories from "../../containers/SearchCategories";
|
||||
import SearchCollections from "../../containers/SearchCollections";
|
||||
import SearchProducts from "../../containers/SearchProducts";
|
||||
import { decimal, getMutationState, maybe } from "../../misc";
|
||||
import { decimal, getMutationState, joinDateTime, maybe } from "../../misc";
|
||||
import { productUrl } from "../../products/urls";
|
||||
import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes";
|
||||
import SaleDetailsPage, {
|
||||
|
@ -273,15 +273,17 @@ export const SaleDetails: React.StatelessComponent<SaleDetailsProps> = ({
|
|||
variables: {
|
||||
id,
|
||||
input: {
|
||||
endDate:
|
||||
formData.endDate === ""
|
||||
? null
|
||||
: formData.endDate,
|
||||
endDate: formData.hasEndDate
|
||||
? joinDateTime(
|
||||
formData.endDate,
|
||||
formData.endTime
|
||||
)
|
||||
: null,
|
||||
name: formData.name,
|
||||
startDate:
|
||||
formData.startDate === ""
|
||||
? null
|
||||
: formData.startDate,
|
||||
startDate: joinDateTime(
|
||||
formData.startDate,
|
||||
formData.startTime
|
||||
),
|
||||
type: discountValueTypeEnum(
|
||||
formData.type
|
||||
),
|
||||
|
|
|
@ -162,7 +162,7 @@ const ProductVariantCreatePrices: React.FC<
|
|||
<Hr className={classes.hrAttribute} />
|
||||
{priceAttributeValues &&
|
||||
priceAttributeValues.map(attributeValue => (
|
||||
<>
|
||||
<React.Fragment key={attributeValue.id}>
|
||||
<FormSpacer />
|
||||
<Grid variant="uniform">
|
||||
<div className={classes.label}>
|
||||
|
@ -198,7 +198,7 @@ const ProductVariantCreatePrices: React.FC<
|
|||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
@ -272,7 +272,7 @@ const ProductVariantCreatePrices: React.FC<
|
|||
<Hr className={classes.hrAttribute} />
|
||||
{stockAttributeValues &&
|
||||
stockAttributeValues.map(attributeValue => (
|
||||
<>
|
||||
<React.Fragment key={attributeValue.id}>
|
||||
<FormSpacer />
|
||||
<Grid variant="uniform">
|
||||
<div className={classes.label}>
|
||||
|
@ -301,7 +301,7 @@ const ProductVariantCreatePrices: React.FC<
|
|||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -200,6 +200,7 @@ const ProductVariantCreateSummary: React.FC<
|
|||
style={{
|
||||
color: colors[valueIndex % colors.length]
|
||||
}}
|
||||
key={value}
|
||||
>
|
||||
{value}
|
||||
</span>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -106,7 +106,7 @@ export default (colors: IThemeColors): Theme =>
|
|||
MuiFormControlLabel: {
|
||||
root: {
|
||||
display: "grid",
|
||||
gridTemplateColumns: "50px 6fr"
|
||||
gridTemplateColumns: "48px 1fr"
|
||||
}
|
||||
},
|
||||
MuiFormLabel: {
|
||||
|
@ -453,7 +453,8 @@ export default (colors: IThemeColors): Theme =>
|
|||
ripple: {
|
||||
"&$rippleVisible": {
|
||||
backgroundColor: fade(colors.primary, 0.2)
|
||||
}
|
||||
},
|
||||
borderRadius: "100%"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue