From 99a530d672000a92060eba0e08b93661e315057b Mon Sep 17 00:00:00 2001 From: Karli Date: Tue, 30 Sep 2025 16:21:08 +0300 Subject: [PATCH 1/6] feat(MED-98): use single
in cart, add toggle for company benefits --- .../_components/cart/analysis-location.tsx | 108 ++++----- .../_components/cart/cart-form-content.tsx | 215 ++++++++++++++++++ .../(user)/_components/cart/cart-form.tsx | 47 ++++ .../(user)/_components/cart/discount-code.tsx | 90 ++++---- app/home/(user)/_components/cart/index.tsx | 202 +++++----------- app/home/(user)/_components/cart/types.ts | 8 + app/home/(user)/_lib/server/cart-actions.ts | 7 +- public/locales/en/cart.json | 3 + public/locales/et/cart.json | 3 + public/locales/ru/cart.json | 3 + 10 files changed, 420 insertions(+), 266 deletions(-) create mode 100644 app/home/(user)/_components/cart/cart-form-content.tsx create mode 100644 app/home/(user)/_components/cart/cart-form.tsx diff --git a/app/home/(user)/_components/cart/analysis-location.tsx b/app/home/(user)/_components/cart/analysis-location.tsx index 38189a5..7189fea 100644 --- a/app/home/(user)/_components/cart/analysis-location.tsx +++ b/app/home/(user)/_components/cart/analysis-location.tsx @@ -1,13 +1,10 @@ 'use client'; -import { zodResolver } from '@hookform/resolvers/zod'; import { StoreCart, StoreCartLineItem } from '@medusajs/types'; -import { useForm } from 'react-hook-form'; +import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { toast } from 'sonner'; -import { z } from 'zod'; -import { Form } from '@kit/ui/form'; import { Select, SelectContent, @@ -22,10 +19,6 @@ import { Trans } from '@kit/ui/trans'; import { updateCartPartnerLocation } from '../../_lib/server/update-cart-partner-location'; import partnerLocations from './partner-locations.json'; -const AnalysisLocationSchema = z.object({ - locationId: z.string().min(1), -}); - export default function AnalysisLocation({ cart, synlabAnalyses, @@ -35,21 +28,15 @@ export default function AnalysisLocation({ }) { const { t } = useTranslation('cart'); - const form = useForm>({ - defaultValues: { - locationId: (cart.metadata?.partner_location_id as string) ?? '', - }, - resolver: zodResolver(AnalysisLocationSchema), - }); + const { watch, setValue } = useFormContext(); + const currentValue = watch('locationId'); const getLocation = (locationId: string) => partnerLocations.find(({ name }) => name === locationId); - const selectedLocation = getLocation(form.watch('locationId')); + const selectedLocation = getLocation(currentValue); - const onSubmit = async ({ - locationId, - }: z.infer) => { + const handleUpdateCartPartnerLocation = async (locationId: string) => { const promise = updateCartPartnerLocation({ cartId: cart.id, lineIds: synlabAnalyses.map(({ id }) => id), @@ -70,53 +57,48 @@ export default function AnalysisLocation({

- - onSubmit(data))} - className="mb-2 flex w-full flex-1 gap-x-2" +
+ { - form.setValue('locationId', value, { - shouldValidate: true, - shouldDirty: true, - shouldTouch: true, - }); + + + - return onSubmit(form.getValues()); - }} - > - - - - - - {Object.entries( - partnerLocations.reduce( - (acc, curr) => ({ - ...acc, - [curr.city]: [ - ...((acc[curr.city] as typeof partnerLocations) ?? []), - curr, - ], - }), - {} as Record, - ), - ).map(([city, locations]) => ( - - {city} - {locations.map((location) => ( - - {location.name} - - ))} - - ))} - - - - + + {Object.entries( + partnerLocations.reduce( + (acc, curr) => ({ + ...acc, + [curr.city]: [ + ...((acc[curr.city] as typeof partnerLocations) ?? []), + curr, + ], + }), + {} as Record, + ), + ).map(([city, locations]) => ( + + {city} + {locations.map((location) => ( + + {location.name} + + ))} + + ))} + + +
{selectedLocation && (
diff --git a/app/home/(user)/_components/cart/cart-form-content.tsx b/app/home/(user)/_components/cart/cart-form-content.tsx new file mode 100644 index 0000000..0a8cd2f --- /dev/null +++ b/app/home/(user)/_components/cart/cart-form-content.tsx @@ -0,0 +1,215 @@ +'use client'; + +import { formatCurrency } from '@/packages/shared/src/utils'; +import { StoreCart, StoreCartLineItem } from '@medusajs/types'; +import { Loader2 } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; + +import { Button } from '@kit/ui/button'; +import { Card, CardContent, CardHeader } from '@kit/ui/card'; +import { Trans } from '@kit/ui/trans'; + +import AnalysisLocation from './analysis-location'; +import CartItems from './cart-items'; +import CartServiceItems from './cart-service-items'; +import DiscountCode from './discount-code'; +import { EnrichedCartItem, GetBalanceSummarySelection } from './types'; +import { + FormControl, + FormField, + FormItem, + FormLabel, +} from '@kit/ui/form'; +import { Checkbox } from '@kit/ui/checkbox'; +import { useFormContext } from 'react-hook-form'; +import { cn } from '~/lib/utils'; + +const IS_DISCOUNT_SHOWN = true as boolean; + +export default function CartFormContent({ + cart, + synlabAnalyses, + ttoServiceItems, + unavailableLineItemIds, + isInitiatingSession, + getBalanceSummarySelection, +}: { + cart: StoreCart; + synlabAnalyses: StoreCartLineItem[]; + ttoServiceItems: EnrichedCartItem[]; + unavailableLineItemIds?: string[]; + isInitiatingSession: boolean; + getBalanceSummarySelection: GetBalanceSummarySelection; +}) { + const { + i18n: { language }, + } = useTranslation(); + const { watch } = useFormContext(); + + const items = cart?.items ?? []; + const hasCartItems = cart && Array.isArray(items) && items.length > 0; + + const isLocationsShown = synlabAnalyses.length > 0; + + const useCompanyBenefits = watch('useCompanyBenefits'); + const balanceSummary = getBalanceSummarySelection({ useCompanyBenefits }); + + const { benefitsAmount, benefitsAmountTotal, montonioAmount } = balanceSummary; + + const hasBenefitsApplied = benefitsAmountTotal > 0 && !!useCompanyBenefits; + + return ( + <> +
+ + +
+ {hasCartItems && ( + <> +
+
+

+ +

+
+
+

+ {formatCurrency({ + value: cart.subtotal, + currencyCode: cart.currency_code, + locale: language, + })} +

+
+
+
+
+

+ +

+
+
+

+ {formatCurrency({ + value: cart.discount_total, + currencyCode: cart.currency_code, + locale: language, + })} +

+
+
+ {hasBenefitsApplied && ( +
+
+

+ +

+
+
+

+ {formatCurrency({ + value: benefitsAmount, + currencyCode: cart.currency_code, + locale: language, + })} +

+
+
+ )} +
+
+

+ +

+
+
+

+ {formatCurrency({ + value: montonioAmount, + currencyCode: cart.currency_code, + locale: language, + })} +

+
+
+ + {benefitsAmountTotal > 0 && ( + ( + +
+ + + + + + +
+
+ )} + /> + )} + + )} + +
+ {IS_DISCOUNT_SHOWN && ( + + +
+ +
+
+ + + +
+ )} + + {isLocationsShown && ( + + +
+ +
+
+ + + +
+ )} +
+ +
+ +
+ + ); +} diff --git a/app/home/(user)/_components/cart/cart-form.tsx b/app/home/(user)/_components/cart/cart-form.tsx new file mode 100644 index 0000000..6c60d83 --- /dev/null +++ b/app/home/(user)/_components/cart/cart-form.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { z } from 'zod'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import type { StoreCart } from '@medusajs/types'; + +import { Form } from '@kit/ui/form'; + +const CartFormSchema = z.object({ + code: z.string().optional(), + locationId: z.string().optional(), + useCompanyBenefits: z.boolean(), +}); + +export type CartFormOnSubmit = (data: z.infer) => Promise; + +export default function CartForm({ + children, + cart, + onSubmit, +}: { + children: React.ReactNode; + cart: StoreCart; + onSubmit: CartFormOnSubmit; +}) { + const form = useForm>({ + defaultValues: { + code: '', + locationId: (cart.metadata?.partner_location_id as string) ?? '', + useCompanyBenefits: true, + }, + resolver: zodResolver(CartFormSchema), + }); + + const handleSubmit: CartFormOnSubmit = async (data) => { + await onSubmit(data); + }; + + return ( +
+ handleSubmit(data))}> + {children} +
+ + ); +}; diff --git a/app/home/(user)/_components/cart/discount-code.tsx b/app/home/(user)/_components/cart/discount-code.tsx index 84ef51d..90250b7 100644 --- a/app/home/(user)/_components/cart/discount-code.tsx +++ b/app/home/(user)/_components/cart/discount-code.tsx @@ -1,30 +1,21 @@ 'use client'; import React from 'react'; +import { useFormContext } from 'react-hook-form'; -import { zodResolver } from '@hookform/resolvers/zod'; import { convertToLocale } from '@lib/util/money'; import { StoreCart, StorePromotion } from '@medusajs/types'; import { Badge, Text } from '@medusajs/ui'; import Trash from '@modules/common/icons/trash'; -import { useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import { z } from 'zod'; import { Button } from '@kit/ui/button'; -import { Form, FormControl, FormField, FormItem } from '@kit/ui/form'; +import { FormControl, FormField, FormItem } from '@kit/ui/form'; import { Input } from '@kit/ui/input'; import { toast } from '@kit/ui/sonner'; import { Trans } from '@kit/ui/trans'; -import { - addPromotionCodeAction, - removePromotionCodeAction, -} from './discount-code-actions'; - -const DiscountCodeSchema = z.object({ - code: z.string().min(1), -}); +import { addPromotionCodeAction, removePromotionCodeAction } from './discount-code-actions'; export default function DiscountCode({ cart, @@ -35,6 +26,9 @@ export default function DiscountCode({ }) { const { t } = useTranslation('cart'); + const { setValue, watch } = useFormContext(); + const currentValue = watch('code'); + const { promotions = [] } = cart; const removePromotionCode = async (code: string) => { @@ -55,57 +49,49 @@ export default function DiscountCode({ }; const addPromotionCode = async (code: string) => { + if (!code || code.length === 0) { + return; + } + 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(); + setValue('code', ''); } else { toast.error(t('cart:discountCode.addError')); } }; - const form = useForm>({ - defaultValues: { - code: '', - }, - resolver: zodResolver(DiscountCodeSchema), - }); - return (

-
- addPromotionCode(data.code))} - className="mb-2 flex w-full flex-1 flex-col gap-x-2 gap-y-2 sm:flex-row" - > - ( - - - - - - )} - /> +
+ ( + + + + + + )} + /> - - - + +
{promotions.length > 0 && (
@@ -133,17 +119,17 @@ export default function DiscountCode({ ( {promotion.application_method?.value !== undefined && promotion.application_method.currency_code !== - undefined && ( + undefined && ( <> {promotion.application_method.type === 'percentage' ? `${promotion.application_method.value}%` : convertToLocale({ - amount: Number( - promotion.application_method.value, - ), - currency_code: - promotion.application_method.currency_code, - })} + amount: Number( + promotion.application_method.value, + ), + currency_code: + promotion.application_method.currency_code, + })} )} ) diff --git a/app/home/(user)/_components/cart/index.tsx b/app/home/(user)/_components/cart/index.tsx index 5f884a5..d76f8be 100644 --- a/app/home/(user)/_components/cart/index.tsx +++ b/app/home/(user)/_components/cart/index.tsx @@ -1,26 +1,17 @@ 'use client'; -import { useState } from 'react'; - -import { formatCurrency } from '@/packages/shared/src/utils'; +import { useCallback, useState } from 'react'; +import { useRouter } from 'next/navigation'; import { StoreCart, StoreCartLineItem } from '@medusajs/types'; -import { Loader2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { Button } from '@kit/ui/button'; -import { Card, CardContent, CardHeader } from '@kit/ui/card'; import { Trans } from '@kit/ui/trans'; - -import AnalysisLocation from './analysis-location'; -import CartItems from './cart-items'; -import CartServiceItems from './cart-service-items'; -import DiscountCode from './discount-code'; -import { initiatePayment } from '../../_lib/server/cart-actions'; -import { useRouter } from 'next/navigation'; import { AccountBalanceSummary } from '@kit/accounts/services/account-balance.service'; -import { EnrichedCartItem } from './types'; -const IS_DISCOUNT_SHOWN = true as boolean; +import { initiatePayment } from '../../_lib/server/cart-actions'; +import { EnrichedCartItem } from './types'; +import CartForm, { CartFormOnSubmit } from './cart-form'; +import CartFormContent from './cart-form-content'; export default function Cart({ accountId, @@ -44,6 +35,44 @@ export default function Cart({ const [unavailableLineItemIds, setUnavailableLineItemIds] = useState(); + const getBalanceSummarySelection = useCallback(({ useCompanyBenefits }: { + useCompanyBenefits: boolean; + }): { + benefitsAmount: number; + benefitsAmountTotal: number; + montonioAmount: number; + } => { + if (!cart) { + return { + benefitsAmount: 0, + benefitsAmountTotal: 0, + montonioAmount: 0, + }; + } + + const benefitsAmountTotal = balanceSummary?.totalBalance ?? 0; + const cartTotal = cart.total; + if (!useCompanyBenefits) { + return { + benefitsAmount: 0, + benefitsAmountTotal, + montonioAmount: cartTotal, + }; + } + + const benefitsAmount = benefitsAmountTotal > cartTotal + ? cartTotal + : benefitsAmountTotal; + const montonioAmount = benefitsAmount > 0 + ? cartTotal - benefitsAmount + : cartTotal; + return { + benefitsAmount, + benefitsAmountTotal, + montonioAmount, + }; + }, [balanceSummary, cart]); + const items = cart?.items ?? []; const hasCartItems = cart && Array.isArray(items) && items.length > 0; @@ -67,13 +96,14 @@ export default function Cart({ ); } - async function initiateSession() { + const initiateSession: CartFormOnSubmit = async ({ useCompanyBenefits }) => { setIsInitiatingSession(true); try { + const { benefitsAmount } = getBalanceSummarySelection({ useCompanyBenefits }); const { url, isFullyPaidByBenefits, orderId, unavailableLineItemIds } = await initiatePayment({ accountId, - balanceSummary: balanceSummary!, + benefitsAmount, cart: cart!, language, }); @@ -92,142 +122,20 @@ export default function Cart({ console.error('Failed to initiate payment', error); setIsInitiatingSession(false); } - } - - const isLocationsShown = synlabAnalyses.length > 0; - - const companyBenefitsTotal = balanceSummary?.totalBalance ?? 0; - const montonioTotal = cart && companyBenefitsTotal > 0 ? cart.total - companyBenefitsTotal : cart.total; + }; return (
-
- + - -
- {hasCartItems && ( - <> -
-
-

- -

-
-
-

- {formatCurrency({ - value: cart.subtotal, - currencyCode: cart.currency_code, - locale: language, - })} -

-
-
-
-
-

- -

-
-
-

- {formatCurrency({ - value: cart.discount_total, - currencyCode: cart.currency_code, - locale: language, - })} -

-
-
- {companyBenefitsTotal > 0 && ( -
-
-

- -

-
-
-

- {formatCurrency({ - value: (companyBenefitsTotal > cart.total ? cart.total : companyBenefitsTotal), - currencyCode: cart.currency_code, - locale: language, - })} -

-
-
- )} -
-
-

- -

-
-
-

- {formatCurrency({ - value: montonioTotal < 0 ? 0 : montonioTotal, - currencyCode: cart.currency_code, - locale: language, - })} -

-
-
- - )} - -
- {IS_DISCOUNT_SHOWN && ( - - -
- -
-
- - - -
- )} - - {isLocationsShown && ( - - -
- -
-
- - - -
- )} -
- -
- -
+
); } diff --git a/app/home/(user)/_components/cart/types.ts b/app/home/(user)/_components/cart/types.ts index aa5cc6d..dcbf184 100644 --- a/app/home/(user)/_components/cart/types.ts +++ b/app/home/(user)/_components/cart/types.ts @@ -36,3 +36,11 @@ export enum CartItemType { } export type EnrichedCartItem = StoreCartLineItem & { reservation: Reservation }; + +export type GetBalanceSummarySelection = ({ useCompanyBenefits }: { + useCompanyBenefits: boolean; +}) => { + benefitsAmount: number; + benefitsAmountTotal: number; + montonioAmount: number; +}; diff --git a/app/home/(user)/_lib/server/cart-actions.ts b/app/home/(user)/_lib/server/cart-actions.ts index b6c95f8..4d1021b 100644 --- a/app/home/(user)/_lib/server/cart-actions.ts +++ b/app/home/(user)/_lib/server/cart-actions.ts @@ -6,7 +6,6 @@ import jwt from 'jsonwebtoken'; import type { StoreCart, StoreOrder } from "@medusajs/types"; import { initiateMultiPaymentSession, placeOrder } from "@lib/data/cart"; -import type { AccountBalanceSummary } from "@kit/accounts/services/account-balance.service"; import { handleNavigateToPayment } from "~/lib/services/medusaCart.service"; import { loadCurrentUserAccount } from "./load-user-account"; import { getOrderedAnalysisIds } from "~/lib/services/medusaOrder.service"; @@ -58,12 +57,12 @@ const env = () => export const initiatePayment = async ({ accountId, - balanceSummary, + benefitsAmount, cart, language, }: { accountId: string; - balanceSummary: AccountBalanceSummary; + benefitsAmount: number; cart: StoreCart; language: string; }) => { @@ -74,7 +73,7 @@ export const initiatePayment = async ({ totalByMontonio, totalByBenefits, isFullyPaidByBenefits, - } = await initiateMultiPaymentSession(cart, balanceSummary.totalBalance); + } = await initiateMultiPaymentSession(cart, benefitsAmount); if (!isFullyPaidByBenefits) { if (!montonioPaymentSessionId) { diff --git a/public/locales/en/cart.json b/public/locales/en/cart.json index 8e471b5..ad800d3 100644 --- a/public/locales/en/cart.json +++ b/public/locales/en/cart.json @@ -94,5 +94,8 @@ "editServiceItem": { "title": "Edit booking", "description": "Edit booking details" + }, + "companyBenefits": { + "label": "Use company benefits" } } diff --git a/public/locales/et/cart.json b/public/locales/et/cart.json index 8154d57..6f58d89 100644 --- a/public/locales/et/cart.json +++ b/public/locales/et/cart.json @@ -94,5 +94,8 @@ "editServiceItem": { "title": "Muuda broneeringut", "description": "Muuda broneeringu andmeid" + }, + "companyBenefits": { + "label": "Kasuta ettevõtte toetust" } } diff --git a/public/locales/ru/cart.json b/public/locales/ru/cart.json index d11ba44..e900175 100644 --- a/public/locales/ru/cart.json +++ b/public/locales/ru/cart.json @@ -94,5 +94,8 @@ "editServiceItem": { "title": "Изменить бронирование", "description": "Изменить данные бронирования" + }, + "companyBenefits": { + "label": "Использовать выгоды компании" } } From 2af0ad4d15c81eb410cc2b5c6cfacb27d3e86221 Mon Sep 17 00:00:00 2001 From: Karli Date: Tue, 30 Sep 2025 16:21:49 +0300 Subject: [PATCH 2/6] feat(MED-98): fix merge issue from 7817ae0 --- app/home/(user)/_components/cart/types.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/home/(user)/_components/cart/types.ts b/app/home/(user)/_components/cart/types.ts index dcbf184..5c535a2 100644 --- a/app/home/(user)/_components/cart/types.ts +++ b/app/home/(user)/_components/cart/types.ts @@ -13,12 +13,6 @@ export interface MontonioOrderToken { | 'PENDING' | 'EXPIRED' | 'REFUNDED'; - | 'PAID' - | 'FAILED' - | 'CANCELLED' - | 'PENDING' - | 'EXPIRED' - | 'REFUNDED'; paymentMethod: string; grandTotal: number; currency: string; From 176e1e2a3c2d3f4dd98066033d2432646f31c162 Mon Sep 17 00:00:00 2001 From: Karli Date: Tue, 30 Sep 2025 16:22:10 +0300 Subject: [PATCH 3/6] feat(MED-98): load packages page slightly faster --- .../_lib/server/load-analysis-packages.ts | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/app/home/(user)/_lib/server/load-analysis-packages.ts b/app/home/(user)/_lib/server/load-analysis-packages.ts index f564e08..19f6043 100644 --- a/app/home/(user)/_lib/server/load-analysis-packages.ts +++ b/app/home/(user)/_lib/server/load-analysis-packages.ts @@ -3,7 +3,7 @@ import { cache } from 'react'; import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product'; import { listProductTypes, listProducts } from '@lib/data/products'; import { listRegions } from '@lib/data/regions'; -import type { StoreProduct } from '@medusajs/types'; +import type { StoreProduct, StoreProductType } from '@medusajs/types'; import type { AccountWithParams } from '@kit/accounts/types/accounts'; import type { AnalysisPackageWithVariant } from '@kit/shared/components/select-analysis-package'; @@ -118,17 +118,12 @@ async function analysisPackageElementsLoader({ async function analysisPackagesWithVariantLoader({ account, countryCode, + productType, }: { account: AccountWithParams; countryCode: string; + productType: StoreProductType; }) { - const productTypes = await loadProductTypes(); - const productType = productTypes.find( - ({ metadata }) => metadata?.handle === 'analysis-packages', - ); - if (!productType) { - return null; - } const analysisPackagesResponse = await listProducts({ countryCode, queryParams: { limit: 100, 'type_id[0]': productType.id }, @@ -171,12 +166,23 @@ async function analysisPackagesLoader() { throw new Error('Account not found'); } - const countryCodes = await loadCountryCodes(); + const [countryCodes, productTypes] = await Promise.all([ + loadCountryCodes(), + loadProductTypes(), + ]); const countryCode = countryCodes[0]!; + const productType = productTypes.find( + ({ metadata }) => metadata?.handle === 'analysis-packages', + ); + + if (!productType) { + return { analysisPackageElements: [], analysisPackages: [], countryCode }; + } const analysisPackagesWithVariant = await analysisPackagesWithVariantLoader({ account, countryCode, + productType, }); if (!analysisPackagesWithVariant) { return { analysisPackageElements: [], analysisPackages: [], countryCode }; From 2b63d7c529e7a0dd8cc3e106d3f9c7e79919765e Mon Sep 17 00:00:00 2001 From: Karli Date: Tue, 30 Sep 2025 16:41:27 +0300 Subject: [PATCH 4/6] feat(MED-98): update translations, fix --- app/home/(user)/_components/cart/discount-code.tsx | 1 - public/locales/en/cart.json | 2 +- public/locales/et/cart.json | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/home/(user)/_components/cart/discount-code.tsx b/app/home/(user)/_components/cart/discount-code.tsx index 90250b7..0a11af0 100644 --- a/app/home/(user)/_components/cart/discount-code.tsx +++ b/app/home/(user)/_components/cart/discount-code.tsx @@ -78,7 +78,6 @@ export default function DiscountCode({ Date: Tue, 30 Sep 2025 16:44:08 +0300 Subject: [PATCH 5/6] feat(MED-98): disable discount button while loading --- app/home/(user)/_components/cart/discount-code.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/app/home/(user)/_components/cart/discount-code.tsx b/app/home/(user)/_components/cart/discount-code.tsx index 0a11af0..1c5332c 100644 --- a/app/home/(user)/_components/cart/discount-code.tsx +++ b/app/home/(user)/_components/cart/discount-code.tsx @@ -1,6 +1,6 @@ 'use client'; -import React from 'react'; +import React, { useState } from 'react'; import { useFormContext } from 'react-hook-form'; import { convertToLocale } from '@lib/util/money'; @@ -31,6 +31,8 @@ export default function DiscountCode({ const { promotions = [] } = cart; + const [isAddingPromotionCode, setIsAddingPromotionCode] = useState(false); + const removePromotionCode = async (code: string) => { const appliedCodes = promotions .filter((p) => p.code !== undefined) @@ -53,6 +55,7 @@ export default function DiscountCode({ return; } + setIsAddingPromotionCode(true); const loading = toast.loading(t('cart:discountCode.addLoading')); const result = await addPromotionCodeAction(code); @@ -63,6 +66,7 @@ export default function DiscountCode({ } else { toast.error(t('cart:discountCode.addError')); } + setIsAddingPromotionCode(false); }; return ( @@ -87,7 +91,13 @@ export default function DiscountCode({ )} /> -
From 04d266dacc29510aa1259c85810be146f11cc0f0 Mon Sep 17 00:00:00 2001 From: Karli Date: Tue, 30 Sep 2025 21:49:55 +0300 Subject: [PATCH 6/6] feat(MED-98): prettier fix --- .prettierignore | 4 +- .../_components/cart/cart-form-content.tsx | 36 ++++---- .../(user)/_components/cart/cart-form.tsx | 10 ++- .../(user)/_components/cart/discount-code.tsx | 21 +++-- app/home/(user)/_components/cart/index.tsx | 90 ++++++++++--------- app/home/(user)/_components/cart/types.ts | 4 +- app/home/(user)/_lib/server/cart-actions.ts | 10 +-- .../_components/account-preferences-form.tsx | 2 +- .../_components/account-settings-form.tsx | 2 +- lib/services/medusaCart.service.ts | 6 +- 10 files changed, 101 insertions(+), 84 deletions(-) diff --git a/.prettierignore b/.prettierignore index dca02d0..e10846e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,5 @@ database.types.ts playwright-report -*.hbs \ No newline at end of file +*.hbs +.history +node_modules diff --git a/app/home/(user)/_components/cart/cart-form-content.tsx b/app/home/(user)/_components/cart/cart-form-content.tsx index 0a8cd2f..7082b74 100644 --- a/app/home/(user)/_components/cart/cart-form-content.tsx +++ b/app/home/(user)/_components/cart/cart-form-content.tsx @@ -3,26 +3,22 @@ import { formatCurrency } from '@/packages/shared/src/utils'; import { StoreCart, StoreCartLineItem } from '@medusajs/types'; import { Loader2 } from 'lucide-react'; +import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { Button } from '@kit/ui/button'; import { Card, CardContent, CardHeader } from '@kit/ui/card'; +import { Checkbox } from '@kit/ui/checkbox'; +import { FormControl, FormField, FormItem, FormLabel } from '@kit/ui/form'; import { Trans } from '@kit/ui/trans'; +import { cn } from '~/lib/utils'; + import AnalysisLocation from './analysis-location'; import CartItems from './cart-items'; import CartServiceItems from './cart-service-items'; import DiscountCode from './discount-code'; import { EnrichedCartItem, GetBalanceSummarySelection } from './types'; -import { - FormControl, - FormField, - FormItem, - FormLabel, -} from '@kit/ui/form'; -import { Checkbox } from '@kit/ui/checkbox'; -import { useFormContext } from 'react-hook-form'; -import { cn } from '~/lib/utils'; const IS_DISCOUNT_SHOWN = true as boolean; @@ -54,7 +50,8 @@ export default function CartFormContent({ const useCompanyBenefits = watch('useCompanyBenefits'); const balanceSummary = getBalanceSummarySelection({ useCompanyBenefits }); - const { benefitsAmount, benefitsAmountTotal, montonioAmount } = balanceSummary; + const { benefitsAmount, benefitsAmountTotal, montonioAmount } = + balanceSummary; const hasBenefitsApplied = benefitsAmountTotal > 0 && !!useCompanyBenefits; @@ -91,9 +88,14 @@ export default function CartFormContent({

-
+

@@ -148,7 +150,7 @@ export default function CartFormContent({ ( - +

-