Files
medreport_mrb2b/app/home/(user)/_components/cart/discount-code.tsx
2025-09-10 06:34:34 +03:00

177 lines
5.9 KiB
TypeScript

"use client"
import { Badge, Text } from "@medusajs/ui"
import { toast } from '@kit/ui/sonner';
import React from "react";
import { convertToLocale } from "@lib/util/money"
import { StoreCart, StorePromotion } from "@medusajs/types"
import Trash from "@modules/common/icons/trash"
import { Button } from '@kit/ui/button';
import { Form, FormControl, FormField, FormItem } from "@kit/ui/form";
import { Trans } from '@kit/ui/trans';
import { Input } from "@kit/ui/input";
import { useTranslation } from "react-i18next";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { addPromotionCodeAction, removePromotionCodeAction } from "./discount-code-actions";
const DiscountCodeSchema = z.object({
code: z.string().min(1),
})
export default function DiscountCode({ cart }: {
cart: StoreCart & {
promotions: StorePromotion[]
}
}) {
const { t } = useTranslation('cart');
const { promotions = [] } = cart;
const removePromotionCode = async (code: string) => {
const appliedCodes = promotions
.filter((p) => p.code !== undefined)
.map((p) => p.code!)
const loading = toast.loading(t('cart:discountCode.removeLoading'));
const result = await removePromotionCodeAction(code, appliedCodes)
toast.dismiss(loading);
if (result.success) {
toast.success(t('cart:discountCode.removeSuccess'));
} else {
toast.error(t('cart:discountCode.removeError'));
}
}
const addPromotionCode = async (code: string) => {
const loading = toast.loading(t('cart:discountCode.addLoading'));
const result = await addPromotionCodeAction(code)
toast.dismiss(loading);
if (result.success) {
toast.success(t('cart:discountCode.addSuccess'));
form.reset()
} else {
toast.error(t('cart:discountCode.addError'));
}
}
const form = useForm<z.infer<typeof DiscountCodeSchema>>({
defaultValues: {
code: '',
},
resolver: zodResolver(DiscountCodeSchema),
});
return (
<div className="w-full h-full bg-white flex flex-col txt-medium gap-y-4">
<p className="text-sm text-muted-foreground">
<Trans i18nKey={'cart:discountCode.subtitle'} />
</p>
<Form {...form}>
<form
onSubmit={form.handleSubmit((data) => addPromotionCode(data.code))}
className="w-full mb-2 flex gap-x-2 sm:flex-row flex-col gap-y-2 flex-1"
>
<FormField
name={'code'}
render={({ field }) => (
<FormItem className="flex-1">
<FormControl>
<Input required type="text" {...field} placeholder={t('cart:discountCode.placeholder')} />
</FormControl>
</FormItem>
)}
/>
<Button
type="submit"
variant="secondary"
className="h-min"
>
<Trans i18nKey={'cart:discountCode.apply'} />
</Button>
</form>
</Form>
{promotions.length > 0 && (
<div className="w-full flex items-center mt-4">
<div className="flex flex-col w-full gap-y-2">
<p>
<Trans i18nKey={'cart:discountCode.appliedCodes'} />
</p>
{promotions.map((promotion) => {
return (
<div
key={promotion.id}
className="flex items-center justify-between w-full max-w-full mb-2"
data-testid="discount-row"
>
<Text className="flex gap-x-1 items-baseline text-sm w-4/5 pr-1">
<span className="truncate" data-testid="discount-code">
<Badge
color={promotion.is_automatic ? "green" : "grey"}
size="small"
className="px-4 text-sm"
>
{promotion.code}
</Badge>{" "}
(
{promotion.application_method?.value !== undefined &&
promotion.application_method.currency_code !==
undefined && (
<>
{promotion.application_method.type ===
"percentage"
? `${promotion.application_method.value}%`
: convertToLocale({
amount: Number(promotion.application_method.value),
currency_code:
promotion.application_method
.currency_code,
})}
</>
)}
)
{/* {promotion.is_automatic && (
<Tooltip content="This promotion is automatically applied">
<InformationCircleSolid className="inline text-zinc-400" />
</Tooltip>
)} */}
</span>
</Text>
{!promotion.is_automatic && (
<button
className="flex items-center"
onClick={() => {
if (!promotion.code) {
return
}
removePromotionCode(promotion.code)
}}
data-testid="remove-discount-button"
>
<Trash size={14} />
<span className="sr-only">
<Trans i18nKey={'cart:discountCode.remove'} />
</span>
</button>
)}
</div>
)
})}
</div>
</div>
)}
</div>
)
}