diff --git a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx index ecd477b..7b5b8d9 100644 --- a/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx +++ b/src/app/[name]/(Dialogs)/order/checkout/[id]/components/PaymentSection.tsx @@ -1,44 +1,51 @@ 'use client'; import { Card, Icon, Wallet2 } from 'iconsax-react'; -import { useCallback, useMemo } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { useGetPaymentMethod } from '../../hooks/useOrderData'; import { useCheckoutStore } from '../../store/Store'; import { useGetUserWallet } from '@/app/[name]/(Main)/transactions/hooks/useTransactionData'; import { useGetCartItems } from '@/app/[name]/(Main)/cart/hooks/useCartData'; -import { useGetProfile } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; +import { useGetProfile, useSingleUpload } from '@/app/[name]/(Profile)/profile/hooks/userProfileData'; +import { PaymentMethodEnum } from '../../enum/Enum'; +import { toast } from '@/components/Toast'; +import { extractErrorMessage } from '@/lib/func'; +import Image from 'next/image'; type PaymentSectionProps = { paymentType: string; onPaymentTypeChange: (id: string) => void; }; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const getIconByMethod = (method: "CardOnDelivery" | "Cash" | "Online", _gateway: string | null): Icon => { - if (method === "Online" || method === "CardOnDelivery") { +const getIconByMethod = (method: PaymentMethodEnum): Icon => { + if (method === PaymentMethodEnum.Online || method === PaymentMethodEnum.CreditCard) { return Card; } - if (method === "Cash") { + if (method === PaymentMethodEnum.Cash || method === PaymentMethodEnum.Wallet) { return Wallet2; } return Card; }; -const isWalletPayment = (method: string, gateway: string | null): boolean => { - return gateway?.toLowerCase() === 'wallet' || method.toLowerCase() === 'wallet'; -}; - export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSectionProps) => { const { t: tOrderDetail } = useTranslation('parallels', { keyPrefix: 'OrderDetail' }); const { t: tOrders } = useTranslation('orders'); const { data: paymentMethod } = useGetPaymentMethod(); - const { setIsSelectedPayment } = useCheckoutStore(); + const { + setIsSelectedPayment, + paymentDesc, + setPaymentDesc, + paymentAttachments, + setPaymentAttachments, + } = useCheckoutStore(); const { data: userWallet } = useGetUserWallet(); const { isSuccess } = useGetProfile(); const { data: cartData } = useGetCartItems(isSuccess); + const { mutateAsync: singleUpload, isPending: isUploading } = useSingleUpload(); + const fileInputRef = useRef(null); const walletAmount = userWallet?.data?.balance ?? 0; const totalAmount = cartData?.data?.total ?? 0; @@ -63,14 +70,50 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect .sort((a, b) => a.order - b.order) .map(item => ({ id: item.id, - label: getPaymentMethodTranslation(item.method, item.title), - icon: getIconByMethod(item.method, item.gateway), + label: getPaymentMethodTranslation(item.method, item.description), + icon: getIconByMethod(item.method), method: item.method, - gateway: item.gateway, - isWallet: isWalletPayment(item.method, item.gateway), + cardNumber: item.cardNumber, + description: item.description, + isWallet: item.method === PaymentMethodEnum.Wallet, })); }, [paymentMethod, getPaymentMethodTranslation]); + const selectedCreditCard = useMemo(() => { + const selected = paymentOptions.find(opt => opt.id === paymentType); + if (selected?.method === PaymentMethodEnum.CreditCard) return selected; + return null; + }, [paymentOptions, paymentType]); + + const handlePaymentTypeChange = (value: string) => { + const selected = paymentOptions.find(opt => opt.id === value); + if (selected?.method !== PaymentMethodEnum.CreditCard) { + setPaymentDesc(''); + setPaymentAttachments([]); + } + onPaymentTypeChange(value); + setIsSelectedPayment(true); + }; + + const handleReceiptUpload = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + try { + const response = await singleUpload(file); + if (response?.data?.url) { + setPaymentAttachments([response.data.url]); + toast(tOrderDetail('SectionPayment.CreditCard.UploadSuccess'), 'success'); + } + } catch (error) { + toast(extractErrorMessage(error), 'error'); + } finally { + if (fileInputRef.current) { + fileInputRef.current.value = ''; + } + } + }; + return (
@@ -78,15 +121,11 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect { - onPaymentTypeChange(value); - setIsSelectedPayment(true); - }} + onValueChange={handlePaymentTypeChange} className='flex flex-col gap-6 mt-6' > {paymentOptions.map(({ id, label, icon: Icon, isWallet }) => { const isDisabled = isWallet && isWalletInsufficient; - const walletOption = paymentOptions.find(opt => opt.id === id && opt.isWallet); return (
@@ -100,12 +139,11 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect htmlFor={`paymentMethod${id}`} >
- {walletOption && ( + {isWallet && ( ({formatPrice(walletAmount)} T) )} - {label}
+ + {selectedCreditCard && ( +
+ {selectedCreditCard.cardNumber && ( +
+ + {tOrderDetail('SectionPayment.CreditCard.CardNumberLabel')} + +

+ {selectedCreditCard.cardNumber} +

+
+ )} + {selectedCreditCard.description && ( +

+ {selectedCreditCard.description} +

+ )} +
+ +