This commit is contained in:
@@ -9,7 +9,7 @@ import { extractErrorMessage } from "@/lib/func";
|
||||
import { Card, Icon, Wallet2 } from "iconsax-react";
|
||||
import Image from "next/image";
|
||||
import { glassSurfaceCard } from "@/lib/styles/glassSurface";
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { PaymentMethodEnum } from "../../enum/Enum";
|
||||
import { useGetPaymentMethod } from "../../hooks/useOrderData";
|
||||
@@ -20,6 +20,11 @@ type PaymentSectionProps = {
|
||||
onPaymentTypeChange: (id: string) => void;
|
||||
};
|
||||
|
||||
type CreditCardOption = {
|
||||
cardNumber: string;
|
||||
cardOwner: string;
|
||||
};
|
||||
|
||||
const getIconByMethod = (method: PaymentMethodEnum): Icon => {
|
||||
if (method === PaymentMethodEnum.Online || method === PaymentMethodEnum.CreditCard) {
|
||||
return Card;
|
||||
@@ -40,6 +45,7 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect
|
||||
const { data: cartData } = useGetCartItems(isSuccess);
|
||||
const { mutateAsync: singleUpload, isPending: isUploading } = useSingleUpload();
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [selectedCardNumber, setSelectedCardNumber] = useState<string>("");
|
||||
|
||||
const walletAmount = userWallet?.data?.balance ?? 0;
|
||||
const totalAmount = cartData?.data?.total ?? 0;
|
||||
@@ -69,6 +75,11 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect
|
||||
method: item.method,
|
||||
cardNumber: item.cardNumber,
|
||||
cardOwner: item.cardOwner,
|
||||
cards:
|
||||
item.cards?.map((card) => ({
|
||||
cardNumber: card.cardNumber,
|
||||
cardOwner: card.owner,
|
||||
})) ?? [],
|
||||
description: item.description,
|
||||
isWallet: item.method === PaymentMethodEnum.Wallet,
|
||||
}));
|
||||
@@ -85,11 +96,45 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect
|
||||
if (selected?.method !== PaymentMethodEnum.CreditCard) {
|
||||
setPaymentDesc("");
|
||||
setPaymentAttachments([]);
|
||||
setSelectedCardNumber("");
|
||||
}
|
||||
onPaymentTypeChange(value);
|
||||
setIsSelectedPayment(true);
|
||||
};
|
||||
|
||||
const creditCardOptions = useMemo<CreditCardOption[]>(() => {
|
||||
if (!selectedCreditCard) return [];
|
||||
|
||||
const normalizedCards = selectedCreditCard.cards.filter(
|
||||
(card): card is CreditCardOption => !!card.cardNumber && !!card.cardOwner,
|
||||
);
|
||||
|
||||
if (normalizedCards.length > 0) return normalizedCards;
|
||||
|
||||
if (selectedCreditCard.cardNumber && selectedCreditCard.cardOwner) {
|
||||
return [{ cardNumber: selectedCreditCard.cardNumber, cardOwner: selectedCreditCard.cardOwner }];
|
||||
}
|
||||
|
||||
return [];
|
||||
}, [selectedCreditCard]);
|
||||
|
||||
useEffect(() => {
|
||||
if (creditCardOptions.length === 0) {
|
||||
setSelectedCardNumber("");
|
||||
return;
|
||||
}
|
||||
|
||||
const hasSelectedCard = creditCardOptions.some((item) => item.cardNumber === selectedCardNumber);
|
||||
if (!hasSelectedCard) {
|
||||
setSelectedCardNumber(creditCardOptions[0].cardNumber);
|
||||
}
|
||||
}, [creditCardOptions, selectedCardNumber]);
|
||||
|
||||
const selectedCard = useMemo(
|
||||
() => creditCardOptions.find((item) => item.cardNumber === selectedCardNumber) ?? null,
|
||||
[creditCardOptions, selectedCardNumber],
|
||||
);
|
||||
|
||||
const handleCopyCardNumber = useCallback(
|
||||
async (cardNumber: string) => {
|
||||
try {
|
||||
@@ -147,24 +192,49 @@ export const PaymentSection = ({ paymentType, onPaymentTypeChange }: PaymentSect
|
||||
|
||||
{selectedCreditCard && (
|
||||
<div className="mt-6 pt-4 border-t border-border flex flex-col gap-4">
|
||||
{(selectedCreditCard.cardOwner || selectedCreditCard.cardNumber) && (
|
||||
{creditCardOptions.length > 0 && (
|
||||
<div className="space-y-3">
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||
{`تعداد کارت های مقصد: ${creditCardOptions.length}`}
|
||||
</p>
|
||||
{creditCardOptions.map((card) => {
|
||||
const isActiveCard = selectedCardNumber === card.cardNumber;
|
||||
return (
|
||||
<button
|
||||
key={card.cardNumber}
|
||||
type="button"
|
||||
onClick={() => setSelectedCardNumber(card.cardNumber)}
|
||||
className={`w-full rounded-normal border px-3 py-2 text-right transition-colors ${
|
||||
isActiveCard ? "border-primary bg-primary/5" : "border-border hover:border-primary/50"
|
||||
}`}
|
||||
>
|
||||
<span className="block text-xs text-gray-500 dark:text-gray-400">{card.cardOwner}</span>
|
||||
<span className="block text-sm font-medium mt-1" dir="ltr">
|
||||
{card.cardNumber}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{selectedCard && (
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
{selectedCreditCard.cardOwner && (
|
||||
{selectedCard.cardOwner && (
|
||||
<div>
|
||||
<span className="text-xs text-gray-500 dark:text-gray-400">{tOrderDetail("SectionPayment.CreditCard.CardOwnerLabel")}</span>
|
||||
<p className="text-sm font-medium mt-1">{selectedCreditCard.cardOwner}</p>
|
||||
<p className="text-sm font-medium mt-1">{selectedCard.cardOwner}</p>
|
||||
</div>
|
||||
)}
|
||||
{selectedCreditCard.cardNumber && (
|
||||
{selectedCard.cardNumber && (
|
||||
<div className="text-left">
|
||||
<span className="text-xs text-gray-500 dark:text-gray-400">{tOrderDetail("SectionPayment.CreditCard.CardNumberLabel")}</span>
|
||||
<button
|
||||
type="button"
|
||||
className="block text-sm font-medium mt-1 cursor-pointer hover:text-primary transition-colors"
|
||||
dir="ltr"
|
||||
onClick={() => handleCopyCardNumber(selectedCreditCard.cardNumber!)}
|
||||
onClick={() => handleCopyCardNumber(selectedCard.cardNumber)}
|
||||
>
|
||||
{selectedCreditCard.cardNumber}
|
||||
{selectedCard.cardNumber}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -116,10 +116,21 @@ export interface PaymentMethodResponse {
|
||||
enabled: boolean;
|
||||
order: number;
|
||||
merchantId: string | null;
|
||||
cards?: PaymentMethodCard[];
|
||||
}
|
||||
|
||||
export type PaymentMethodsResponse = BaseResponse<PaymentMethodResponse[]>;
|
||||
|
||||
export interface PaymentMethodCard {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: string | null;
|
||||
paymentMethod: string;
|
||||
cardNumber: string;
|
||||
owner: string;
|
||||
}
|
||||
|
||||
export type CheckoutStoreType = {
|
||||
isSelectedAddress: boolean;
|
||||
setIsSelectedAddress: (value: boolean) => void;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
// export const API_BASE_URL = "https://dmenuplus-api-production.dev.danakcorp.com";
|
||||
// export const API_BASE_URL = "https://dmenu-api.danakcorp.com";
|
||||
export const API_BASE_URL = "http://192.168.99.131:2000";
|
||||
export const API_BASE_URL = "https://dmenu-api.danakcorp.com";
|
||||
// export const API_BASE_URL = "http://192.168.99.131:2000";
|
||||
export const TOKEN_NAME = "dmenu-t";
|
||||
export const REFRESH_TOKEN_NAME = "dmenu-rt";
|
||||
|
||||
Reference in New Issue
Block a user