Skip to content

Commit

Permalink
fix: begin fixed_price in order process modal
Browse files Browse the repository at this point in the history
  • Loading branch information
HoreKk committed Nov 6, 2024
1 parent be7b954 commit 9e7c3ac
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 54 deletions.
123 changes: 80 additions & 43 deletions webapp/src/components/modals/ObizOrderProcessModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import {
Box,
Button,
Center,
Flex,
Heading,
Icon,
Modal,
ModalBody,
Expand All @@ -12,7 +9,6 @@ import {
Text,
} from "@chakra-ui/react";
import { Dispatch, SetStateAction, useState } from "react";
import LoadingLoader from "~/components/LoadingLoader";
import DiscountAmountBlock from "~/components/obiz/DiscountAmountBlock";
import RecapOrder from "~/components/obiz/RecapOrder";
import BackButton from "~/components/ui/BackButton";
Expand All @@ -28,56 +24,91 @@ const ObizOfferVariableContent = ({
amount,
setAmount,
offer,
article,
articles,
createOrder,
selectedArticles,
setSelectedArticles,
}: {
step: "amount" | "summary" | "payment";
setStep: Dispatch<SetStateAction<"amount" | "summary" | "payment">>;
step: Steps;
setStep: Dispatch<SetStateAction<Steps>>;
amount: number;
setAmount: Dispatch<SetStateAction<number>>;
article: OfferArticle;
articles: OfferArticle[];
selectedArticles?: { reference: string; quantity: number }[];
setSelectedArticles?: Dispatch<
SetStateAction<{ reference: string; quantity: number }[]>
>;
offer: OfferIncluded;
createOrder: () => void;
}) => {
switch (step) {
case "amount":
const minimumPrice = article.minimumPrice ?? 0;
const maximumPrice = article.maximumPrice ?? 1000;
const isDisabled =
amount === 0 ||
amount < minimumPrice ||
amount > maximumPrice ||
amount % 1 !== 0;
if (articles.length === 1 && articles[0].kind === "variable_price") {
const article = articles[0];
const minimumPrice = article.minimumPrice ?? 0;
const maximumPrice = article.maximumPrice ?? 1000;
const isDisabled =
amount === 0 ||
amount < minimumPrice ||
amount > maximumPrice ||
amount % 1 !== 0;

return (
<>
<Box mt={10}>
<DiscountAmountBlock
discount={article.reductionPercentage}
amount={amount}
setAmount={setAmount}
minAmount={minimumPrice}
maxAmount={maximumPrice}
/>
</Box>
<Button
mt="auto"
mb={24}
onClick={() => setStep("summary")}
w="full"
isDisabled={isDisabled}
>
Acheter mon bon
</Button>
</>
);
return (
<>
<Box mt={10}>
<DiscountAmountBlock
kind="variable_price"
discount={article.reductionPercentage}
amount={amount}
setAmount={setAmount}
minAmount={minimumPrice}
maxAmount={maximumPrice}
/>
</Box>
<Button
mt="auto"
mb={24}
onClick={() => setStep("summary")}
w="full"
isDisabled={isDisabled}
>
Acheter mon bon
</Button>
</>
);
} else {
if (!selectedArticles || !setSelectedArticles) return null;
return (
<>
<Box mt={10}>
<DiscountAmountBlock
kind="fixed_price"
amount={amount}
setAmount={setAmount}
articles={articles}
selectedArticles={selectedArticles}
setSelectedArticles={setSelectedArticles}
/>
</Box>
<Button
mt="auto"
mb={24}
onClick={() => setStep("summary")}
isDisabled={amount === 0}
w="full"
>
Acheter ces bons
</Button>
</>
);
}
case "summary":
if (!offer) return null;
return (
<>
<Box mt={10}>
<RecapOrder
discount={article.reductionPercentage}
discount={articles[0].reductionPercentage}
amount={amount}
offer={offer}
/>
Expand Down Expand Up @@ -114,13 +145,18 @@ type ObizOrderProcessModalProps = {
offerId: number;
};

type Steps = "amount" | "summary" | "payment";

export default function ObizOrderProcessModal(
props: ObizOrderProcessModalProps
) {
const { isOpen, onClose, offerId } = props;

const [amount, setAmount] = useState(0);
const [step, setStep] = useState<"amount" | "summary" | "payment">("amount");
const [step, setStep] = useState<Steps>("amount");
const [selectedArticles, setSelectedArticles] = useState<
{ reference: string; quantity: number }[]
>([]);

const { mutate: createTestOrder } = api.order.createOrder.useMutation({
onMutate: () => setStep("payment"),
Expand All @@ -137,9 +173,8 @@ export default function ObizOrderProcessModal(
if (!offer || !offer.articles) return;

const availableArticles = offer.articles.filter((a) => !!a.available);
const article = availableArticles.find((a) => a.kind === "variable_price");

if (!article) return;
if (availableArticles.length === 0) return;

return (
<Modal isOpen={isOpen} onClose={onClose} size="full">
Expand All @@ -161,14 +196,16 @@ export default function ObizOrderProcessModal(
amount={amount}
setAmount={setAmount}
offer={offer}
article={article}
articles={availableArticles}
createOrder={() => {
createTestOrder({
offer_id: offer.id,
article_reference: article.reference,
article_reference: availableArticles[0].reference,
input_value: amount,
});
}}
selectedArticles={selectedArticles}
setSelectedArticles={setSelectedArticles}
/>
</ModalBody>
</ModalContent>
Expand Down
135 changes: 124 additions & 11 deletions webapp/src/components/obiz/DiscountAmountBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,56 @@
import {
Box,
Center,
Divider,
Flex,
FormControl,
FormLabel,
Icon,
IconButton,
Input,
Text,
} from "@chakra-ui/react";
import { Dispatch, SetStateAction } from "react";
import { HiMiniMinus, HiMiniPlus } from "react-icons/hi2";
import { OfferArticle } from "~/server/types";

const DiscountAmountBlock = ({
amount,
setAmount,
minAmount,
maxAmount,
discount,
}: {
type DefaultProps = {
amount: number;
setAmount: Dispatch<SetStateAction<number>>;
};

interface DiscountAmountBlockVariable extends DefaultProps {
kind: "variable_price";
minAmount: number;
maxAmount: number;
discount: number;
}) => {
}

interface DiscountAmountBlockFixed extends DefaultProps {
kind: "fixed_price";
articles: OfferArticle[];
selectedArticles: { reference: string; quantity: number }[];
setSelectedArticles: Dispatch<
SetStateAction<{ reference: string; quantity: number }[]>
>;
}

type DiscountAmountBlockProps =
| DiscountAmountBlockVariable
| DiscountAmountBlockFixed;

const DiscountAmountBlock = (props: DiscountAmountBlockProps) => {
const { kind, amount, setAmount } = props;

const discount =
kind === "variable_price"
? props.discount
: props.articles[0].reductionPercentage;
const isDisabled = amount === 0;
const isInvalid =
kind === "variable_price" &&
!isDisabled &&
(amount < minAmount || amount > maxAmount || amount % 1 !== 0);
(amount < props.minAmount || amount > props.maxAmount || amount % 1 !== 0);

return (
<Center flexDir="column">
Expand All @@ -52,12 +77,16 @@ const DiscountAmountBlock = ({
py={6}
autoComplete="off"
step={1}
autoFocus={kind === "variable_price"}
value={kind === "fixed_price" ? amount : undefined}
onChange={(e) =>
setAmount(e.target.value ? Number(e.target.value) : 0)
}
placeholder="0€"
min={minAmount}
max={maxAmount}
min={kind === "variable_price" ? props.minAmount : 0}
max={kind === "variable_price" ? props.maxAmount : 0}
isDisabled={kind === "fixed_price"}
_disabled={{ opacity: 1 }}
/>
</FormControl>
<Flex alignItems="center" mt={6}>
Expand Down Expand Up @@ -110,6 +139,90 @@ const DiscountAmountBlock = ({
</Text>
</Center>
</Flex>
{kind === "fixed_price" && (
<Box mt={8} w="full">
{props.articles.map((article, index) => {
const selectedArticle = props.selectedArticles.find(
(a) => a.reference === article.reference
);
const quantity = selectedArticle?.quantity || 0;
return (
<Flex key={article.reference} flexDir="column" w="full">
{index === 0 && <Divider borderColor="cje-gray.100" />}
<Flex alignItems="center" mt={2}>
<Flex flexDir="column">
<Text fontWeight={500}>Bon de {article.publicPrice}</Text>
<Text fontSize={14} color="disabled">
Valable jusqu'au{" "}
{new Date(article.validityTo).toLocaleDateString(
"fr-FR",
{
day: "2-digit",
month: "2-digit",
year: "numeric",
}
)}
</Text>
<Text fontSize={14} fontWeight={700}>
Voir les infos
</Text>
</Flex>
<Flex alignItems="center" ml="auto" gap={2}>
<IconButton
icon={<Icon as={HiMiniMinus} />}
borderRadius="full"
size="xs"
aria-label={`Minus the quantity of ${article.reference}`}
isDisabled={quantity === 0}
onClick={() => {
if (quantity === 0) return;
props.setSelectedArticles((prev) =>
prev.map((a) =>
a.reference === article.reference
? { ...a, quantity: a.quantity - 1 }
: a
)
);
setAmount(
(prev) => prev - (article.publicPrice as number)
);
}}
/>
<Box bgColor="bgGray" borderRadius="xl" py={2} px={6}>
<Text fontSize={18} fontWeight={800}>
{quantity}
</Text>
</Box>
<IconButton
size="xs"
aria-label={`Plus the quantity of ${article.reference}`}
icon={<Icon as={HiMiniPlus} />}
borderRadius="full"
isDisabled={quantity === 5}
onClick={() => {
if (quantity === 5) return;
props.setSelectedArticles((prev) => [
...prev.filter(
(a) => a.reference !== article.reference
),
{
reference: article.reference,
quantity: quantity + 1,
},
]);
setAmount(
(prev) => prev + (article.publicPrice as number)
);
}}
/>
</Flex>
</Flex>
<Divider borderColor="cje-gray.100" mt={2} />
</Flex>
);
})}
</Box>
)}
</Center>
);
};
Expand Down

0 comments on commit 9e7c3ac

Please sign in to comment.