import DialogButtons from "@dashboard/components/ActionDialog/DialogButtons"; import CardSpacer from "@dashboard/components/CardSpacer"; import ConfirmButton from "@dashboard/components/ConfirmButton"; import PriceField from "@dashboard/components/PriceField"; import RadioGroupField from "@dashboard/components/RadioGroupField"; import { DiscountValueTypeEnum, MoneyFragment } from "@dashboard/graphql"; import { useUpdateEffect } from "@dashboard/hooks/useUpdateEffect"; import { buttonMessages } from "@dashboard/intl"; import { toFixed } from "@dashboard/utils/toFixed"; import { Card, CardContent, TextField, Typography } from "@material-ui/core"; import { ConfirmButtonTransitionState, makeStyles } from "@saleor/macaw-ui"; import React, { ChangeEvent, useEffect, useRef, useState } from "react"; import { defineMessages, useIntl } from "react-intl"; import ModalTitle from "./ModalTitle"; import { ORDER_LINE_DISCOUNT, OrderDiscountCommonInput, OrderDiscountType, } from "./types"; const numbersRegex = /([0-9]+\.?[0-9]*)$/; const useStyles = makeStyles( theme => ({ removeButton: { "&:hover": { backgroundColor: theme.palette.error.main, }, backgroundColor: theme.palette.error.main, color: theme.palette.error.contrastText, }, radioContainer: { display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center", }, reasonInput: { marginTop: theme.spacing(1), width: "100%", }, buttonWrapper: { display: "flex", flexDirection: "row", flex: 1, }, }), { name: "OrderLineDiscountModal" }, ); const messages = defineMessages({ buttonLabel: { id: "QSnh4Y", defaultMessage: "Add", description: "add button label", }, itemDiscountTitle: { id: "WTj17Z", defaultMessage: "Discount Item", description: "dialog title item discount", }, orderDiscountTitle: { id: "YFDAaX", defaultMessage: "Discount this Order by:", description: "dialog title order discount", }, percentageOption: { id: "WUf3Iu", defaultMessage: "Percentage", description: "percentage option", }, fixedAmountOption: { id: "fo7nfa", defaultMessage: "Fixed Amount", description: "fixed amount", }, invalidValue: { id: "IN5iJz", defaultMessage: "Invalid value", description: "value input helper text", }, valueBiggerThatPrice: { defaultMessage: "Cannot be higher than the price", id: "VIdXPy", description: "value input helper text", }, valueBiggerThat100: { defaultMessage: "Cannot be higher than 100%", id: "zHx85l", description: "value input helper text", }, discountValueLabel: { id: "GAmGog", defaultMessage: "Discount value", description: "value input label", }, discountReasonLabel: { id: "nvSJNR", defaultMessage: "Reason", description: "discount reason input lavel", }, }); export interface OrderDiscountCommonModalProps { maxPrice: MoneyFragment; onConfirm: (discount: OrderDiscountCommonInput) => void; onClose: () => void; onRemove: () => void; modalType: OrderDiscountType; existingDiscount: OrderDiscountCommonInput; confirmStatus: ConfirmButtonTransitionState; removeStatus: ConfirmButtonTransitionState; } const OrderDiscountCommonModal: React.FC = ({ maxPrice = { amount: null, currency: "" }, onConfirm, modalType, onClose, onRemove, existingDiscount, confirmStatus, removeStatus, }) => { const { currency, amount: maxAmount } = maxPrice; const getInitialDiscountValue = (calculationMode: DiscountValueTypeEnum) => { if (!existingDiscount?.value) { return ""; } const stringifiedValue = existingDiscount.value.toString(); if (calculationMode === DiscountValueTypeEnum.FIXED) { return parseFloat(stringifiedValue).toString(); } return stringifiedValue; }; const getInitialData = () => { const calculationMode = existingDiscount?.calculationMode || DiscountValueTypeEnum.PERCENTAGE; return { calculationMode, reason: existingDiscount?.reason || "", value: getInitialDiscountValue(calculationMode), }; }; const initialData = getInitialData(); const [valueErrorMsg, setValueErrorMsg] = useState(null); const [reason, setReason] = useState(initialData.reason); const [value, setValue] = useState(initialData.value); const [calculationMode, setCalculationMode] = useState( initialData.calculationMode, ); const previousCalculationMode = useRef(calculationMode); const classes = useStyles({}); const intl = useIntl(); const discountTypeChoices = [ { label: intl.formatMessage(messages.percentageOption), value: DiscountValueTypeEnum.PERCENTAGE, }, { label: intl.formatMessage(messages.fixedAmountOption), value: DiscountValueTypeEnum.FIXED, }, ]; const isDiscountTypePercentage = calculationMode === DiscountValueTypeEnum.PERCENTAGE; const handleSetDiscountValue = ( event: React.ChangeEvent, ) => { const value = event.target.value; setValueErrorMsg(getErrorMessage(value)); setValue(value); }; const getParsedDiscountValue = () => parseFloat(value) || 0; const isAmountTooLarge = (value?: string) => { const topAmount = isDiscountTypePercentage ? 100 : maxAmount; if (value) { return (parseFloat(value) || 0) > topAmount; } return getParsedDiscountValue() > topAmount; }; const getErrorMessage = (value: string): string | null => { if (isAmountTooLarge(value)) { if (calculationMode === DiscountValueTypeEnum.PERCENTAGE) { return intl.formatMessage(messages.valueBiggerThat100); } return intl.formatMessage(messages.valueBiggerThatPrice); } if (!numbersRegex.test(value)) { return intl.formatMessage(messages.invalidValue); } return null; }; const handleConfirm = () => { onConfirm({ calculationMode, reason, value: getParsedDiscountValue(), }); }; const setDefaultValues = () => { setReason(initialData.reason); setValue(initialData.value); setCalculationMode(initialData.calculationMode); setValueErrorMsg(null); }; useEffect(setDefaultValues, [ existingDiscount?.value, existingDiscount?.reason, ]); const handleValueConversion = () => { if (getParsedDiscountValue() === 0) { return; } const changedFromPercentageToFixed = previousCalculationMode.current === DiscountValueTypeEnum.PERCENTAGE && calculationMode === DiscountValueTypeEnum.FIXED; const recalculatedValueFromPercentageToFixed = ( (getParsedDiscountValue() * maxPrice.amount) / 100 ).toString(); const recalculatedValueFromFixedToPercentage = ( (getParsedDiscountValue() / maxPrice.amount) * 100 ).toString(); const recalculatedValue = changedFromPercentageToFixed ? recalculatedValueFromPercentageToFixed : recalculatedValueFromFixedToPercentage; setValueErrorMsg(getErrorMessage(recalculatedValue)); setValue(recalculatedValue); previousCalculationMode.current = calculationMode; }; useUpdateEffect(handleValueConversion, [calculationMode]); const dialogTitle = modalType === ORDER_LINE_DISCOUNT ? messages.itemDiscountTitle : messages.orderDiscountTitle; const valueFieldSymbol = calculationMode === DiscountValueTypeEnum.FIXED ? currency : "%"; const isSubmitDisabled = !getParsedDiscountValue() || !!valueErrorMsg || isAmountTooLarge(); return ( setCalculationMode(event.target.value)} /> {intl.formatMessage(messages.discountReasonLabel)} ) => setReason(event.target.value) } /> {existingDiscount && (
{intl.formatMessage(buttonMessages.remove)}
)}
); }; export default OrderDiscountCommonModal;