bulk action + payment
This commit is contained in:
@@ -12,13 +12,18 @@ import { extractErrorMessage } from '@/helpers/errorUtils'
|
|||||||
import Error from '@/components/Error'
|
import Error from '@/components/Error'
|
||||||
import { setRefreshToken, setToken } from '@/config/func'
|
import { setRefreshToken, setToken } from '@/config/func'
|
||||||
import { useCountDown } from '@/hooks/useCountDown'
|
import { useCountDown } from '@/hooks/useCountDown'
|
||||||
|
import { useBulkAddCart } from '@/app/cart/hooks/useCartData'
|
||||||
|
import { useLocalCart } from '@/app/product/hooks/useLocalCart'
|
||||||
|
import { useSharedStore } from '@/share/store/sharedStore'
|
||||||
|
|
||||||
const LoginStep2: FC = () => {
|
const LoginStep2: FC = () => {
|
||||||
|
|
||||||
const { phone } = useAuthStore()
|
const { phone } = useAuthStore()
|
||||||
const { isPending, mutate: verifyOtp } = useVerifyOtp()
|
const { isPending, mutate: verifyOtp } = useVerifyOtp()
|
||||||
|
|
||||||
const { mutate: authentication, isPending: isAuthenticationPending } = useAuthentication();
|
const { mutate: authentication, isPending: isAuthenticationPending } = useAuthentication();
|
||||||
|
const { mutate: bulkAddCart } = useBulkAddCart()
|
||||||
|
const { getLocalCartItems, clearLocalCart } = useLocalCart()
|
||||||
|
const { setIsLogin } = useSharedStore()
|
||||||
|
|
||||||
const { value: countdownValue, reset: resetCountdown } = useCountDown(2, true, () => {
|
const { value: countdownValue, reset: resetCountdown } = useCountDown(2, true, () => {
|
||||||
// When countdown ends, enable resend button
|
// When countdown ends, enable resend button
|
||||||
@@ -49,6 +54,28 @@ const LoginStep2: FC = () => {
|
|||||||
toast('ورود با موفقیت انجام شد', 'success')
|
toast('ورود با موفقیت انجام شد', 'success')
|
||||||
setToken(data?.results?.data?.accessToken?.token)
|
setToken(data?.results?.data?.accessToken?.token)
|
||||||
setRefreshToken(data?.results?.data?.refreshToken?.token)
|
setRefreshToken(data?.results?.data?.refreshToken?.token)
|
||||||
|
setIsLogin(true)
|
||||||
|
|
||||||
|
// همگامسازی سبد خرید آفلاین
|
||||||
|
const localCartItems = getLocalCartItems()
|
||||||
|
if (localCartItems.length > 0) {
|
||||||
|
const bulkItems = localCartItems.map(item => ({
|
||||||
|
productId: item.productId,
|
||||||
|
variantId: item.variantId,
|
||||||
|
quantity: item.quantity
|
||||||
|
}))
|
||||||
|
|
||||||
|
bulkAddCart({ items: bulkItems }, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast('سبد خرید آفلاین با موفقیت همگامسازی شد', 'success')
|
||||||
|
clearLocalCart()
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast(extractErrorMessage(error), 'error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
window.location.href = '/'
|
window.location.href = '/'
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -54,3 +54,42 @@ export const usePaymentMethods = () => {
|
|||||||
queryFn: api.paymentMethods,
|
queryFn: api.paymentMethods,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useCheckoutCart = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.checkoutCart,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useApplyDiscountCode = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.applyDiscountCode,
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["cart"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCheckPaymentStatus = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.checkPaymentStatus,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRemoveAllCart = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.removeAllCart,
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["cart"] });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useBulkAddCart = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: api.bulkAddCart,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
+3
-13
@@ -5,14 +5,14 @@ import CartSummary from "@/components/CartSummary"
|
|||||||
import Layout from "@/hoc/Layout"
|
import Layout from "@/hoc/Layout"
|
||||||
import { Trash } from "iconsax-react"
|
import { Trash } from "iconsax-react"
|
||||||
import { NextPage } from "next"
|
import { NextPage } from "next"
|
||||||
import { useGetCart, useRemoveFromCart } from "./hooks/useCartData"
|
import { useGetCart, useRemoveAllCart } from "./hooks/useCartData"
|
||||||
import { toast } from "@/components/Toast"
|
import { toast } from "@/components/Toast"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
|
||||||
const Cart: NextPage = () => {
|
const Cart: NextPage = () => {
|
||||||
|
|
||||||
const { data, isLoading, error } = useGetCart();
|
const { data, isLoading, error } = useGetCart();
|
||||||
const removeFromCartMutation = useRemoveFromCart()
|
const removeAllCartMutation = useRemoveAllCart()
|
||||||
const [isClearingAll, setIsClearingAll] = useState(false)
|
const [isClearingAll, setIsClearingAll] = useState(false)
|
||||||
|
|
||||||
const handleClearAll = async () => {
|
const handleClearAll = async () => {
|
||||||
@@ -20,17 +20,7 @@ const Cart: NextPage = () => {
|
|||||||
|
|
||||||
setIsClearingAll(true)
|
setIsClearingAll(true)
|
||||||
try {
|
try {
|
||||||
// حذف همه آیتمها یکی یکی
|
await removeAllCartMutation.mutateAsync()
|
||||||
const removePromises = data.results.cart.items
|
|
||||||
.filter(item => item && item.product && item.variant)
|
|
||||||
.map(item =>
|
|
||||||
removeFromCartMutation.mutateAsync({
|
|
||||||
productId: item.product._id,
|
|
||||||
variantId: item.variant._id
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
await Promise.all(removePromises)
|
|
||||||
toast('همه محصولات از سبد خرید حذف شدند', 'success')
|
toast('همه محصولات از سبد خرید حذف شدند', 'success')
|
||||||
} catch {
|
} catch {
|
||||||
toast('خطا در حذف محصولات', 'error')
|
toast('خطا در حذف محصولات', 'error')
|
||||||
|
|||||||
@@ -0,0 +1,156 @@
|
|||||||
|
'use client'
|
||||||
|
import Layout from '@/hoc/Layout'
|
||||||
|
import { NextPage } from 'next'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useRouter, useSearchParams } from 'next/navigation'
|
||||||
|
import { useCheckPaymentStatus } from '../../hooks/useCartData'
|
||||||
|
import { toast } from '@/components/Toast'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
const PaymentCallback: NextPage = () => {
|
||||||
|
const router = useRouter()
|
||||||
|
const searchParams = useSearchParams()
|
||||||
|
const checkPaymentMutation = useCheckPaymentStatus()
|
||||||
|
|
||||||
|
const [paymentStatus, setPaymentStatus] = useState<'loading' | 'success' | 'failed' | 'pending'>('loading')
|
||||||
|
const [orderData, setOrderData] = useState<any>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const authority = searchParams.get('Authority')
|
||||||
|
const status = searchParams.get('Status')
|
||||||
|
|
||||||
|
if (!authority) {
|
||||||
|
toast('خطا در دریافت اطلاعات پرداخت', 'error')
|
||||||
|
setPaymentStatus('failed')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// بررسی وضعیت پرداخت - اطلاعات سفارش از سرور دریافت میشود
|
||||||
|
checkPaymentStatus(authority)
|
||||||
|
}, [searchParams])
|
||||||
|
|
||||||
|
const checkPaymentStatus = async (authority: string) => {
|
||||||
|
try {
|
||||||
|
const response = await checkPaymentMutation.mutateAsync({ authority })
|
||||||
|
|
||||||
|
// ذخیره اطلاعات سفارش از response
|
||||||
|
if (response?.results?.orderData) {
|
||||||
|
setOrderData(response.results.orderData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response?.results?.paymentStatus === 'success') {
|
||||||
|
setPaymentStatus('success')
|
||||||
|
toast('پرداخت با موفقیت انجام شد', 'success')
|
||||||
|
} else if (response?.results?.paymentStatus === 'failed') {
|
||||||
|
setPaymentStatus('failed')
|
||||||
|
toast('پرداخت ناموفق بود', 'error')
|
||||||
|
} else {
|
||||||
|
setPaymentStatus('pending')
|
||||||
|
toast('وضعیت پرداخت در حال بررسی است', 'warning')
|
||||||
|
}
|
||||||
|
} catch (error: unknown) {
|
||||||
|
setPaymentStatus('failed')
|
||||||
|
const errorMessage = (error as { response?: { data?: { message?: string } } })?.response?.data?.message || 'خطا در بررسی وضعیت پرداخت'
|
||||||
|
toast(errorMessage, 'error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusIcon = () => {
|
||||||
|
switch (paymentStatus) {
|
||||||
|
case 'success':
|
||||||
|
return '✅'
|
||||||
|
case 'failed':
|
||||||
|
return '❌'
|
||||||
|
case 'pending':
|
||||||
|
return '⏳'
|
||||||
|
default:
|
||||||
|
return '🔄'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusMessage = () => {
|
||||||
|
switch (paymentStatus) {
|
||||||
|
case 'success':
|
||||||
|
return 'پرداخت با موفقیت انجام شد'
|
||||||
|
case 'failed':
|
||||||
|
return 'پرداخت ناموفق بود'
|
||||||
|
case 'pending':
|
||||||
|
return 'وضعیت پرداخت در حال بررسی است'
|
||||||
|
default:
|
||||||
|
return 'در حال بررسی وضعیت پرداخت...'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusColor = () => {
|
||||||
|
switch (paymentStatus) {
|
||||||
|
case 'success':
|
||||||
|
return 'text-green-600'
|
||||||
|
case 'failed':
|
||||||
|
return 'text-red-600'
|
||||||
|
case 'pending':
|
||||||
|
return 'text-yellow-600'
|
||||||
|
default:
|
||||||
|
return 'text-blue-600'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-14 px-4 sm:px-8 lg:px-20">
|
||||||
|
<div className="flex items-center justify-center min-h-[60vh]">
|
||||||
|
<div className="text-center max-w-md w-full">
|
||||||
|
<div className="text-6xl mb-6">
|
||||||
|
{getStatusIcon()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className={`text-2xl font-bold mb-4 ${getStatusColor()}`}>
|
||||||
|
{getStatusMessage()}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
{orderData && (
|
||||||
|
<div className="bg-gray-50 rounded-lg p-4 mb-6 text-right">
|
||||||
|
<div className="text-sm text-gray-600 mb-2">اطلاعات سفارش:</div>
|
||||||
|
<div className="text-sm">
|
||||||
|
<div>شماره سفارش: {orderData.orderId}</div>
|
||||||
|
<div>مبلغ پرداخت: {orderData.totalPaymentPrice?.toLocaleString()} تومان</div>
|
||||||
|
<div>تاریخ: {new Date(orderData.createdAt).toLocaleDateString('fa-IR')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="space-y-3">
|
||||||
|
{paymentStatus === 'success' && (
|
||||||
|
<Button asChild className="w-full">
|
||||||
|
<Link href="/profile/orders">
|
||||||
|
مشاهده سفارشات
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Button asChild variant="outline" className="w-full">
|
||||||
|
<Link href="/">
|
||||||
|
بازگشت به صفحه اصلی
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
{paymentStatus === 'failed' && (
|
||||||
|
<Button asChild variant="outline" className="w-full">
|
||||||
|
<Link href="/cart/payment">
|
||||||
|
تلاش مجدد برای پرداخت
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PaymentCallbackWithLayout() {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<PaymentCallback />
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import { NextPage } from 'next'
|
|||||||
import TitleBack from '../components/TitleBack'
|
import TitleBack from '../components/TitleBack'
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
||||||
import DiscountCard from '../components/DiscountCard'
|
import DiscountCard from '../components/DiscountCard'
|
||||||
import { usePaymentMethods, useGetCart, useShippingCost } from '../hooks/useCartData'
|
import { usePaymentMethods, useGetCart, useShippingCost, useApplyDiscountCode, useCheckoutCart } from '../hooks/useCartData'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { toast } from '@/components/Toast'
|
import { toast } from '@/components/Toast'
|
||||||
import { useGetProfile } from '@/app/profile/hooks/useProfileData'
|
import { useGetProfile } from '@/app/profile/hooks/useProfileData'
|
||||||
@@ -16,9 +16,11 @@ const CartPayment: NextPage = () => {
|
|||||||
const { data: shippingData, isLoading: shippingLoading } = useShippingCost()
|
const { data: shippingData, isLoading: shippingLoading } = useShippingCost()
|
||||||
const { data: profileData, isLoading: profileLoading } = useGetProfile()
|
const { data: profileData, isLoading: profileLoading } = useGetProfile()
|
||||||
|
|
||||||
|
const applyDiscountMutation = useApplyDiscountCode()
|
||||||
|
const checkoutMutation = useCheckoutCart()
|
||||||
|
|
||||||
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState<string>('')
|
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState<string>('')
|
||||||
const [discountCode, setDiscountCode] = useState<string>('')
|
const [discountCode, setDiscountCode] = useState<string>('')
|
||||||
const [isApplyingDiscount, setIsApplyingDiscount] = useState(false)
|
|
||||||
|
|
||||||
const isLoading = paymentMethodsLoading || cartLoading || shippingLoading || profileLoading
|
const isLoading = paymentMethodsLoading || cartLoading || shippingLoading || profileLoading
|
||||||
|
|
||||||
@@ -64,15 +66,13 @@ const CartPayment: NextPage = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsApplyingDiscount(true)
|
|
||||||
try {
|
try {
|
||||||
// TODO: پیادهسازی API اعمال کد تخفیف
|
await applyDiscountMutation.mutateAsync({ discount_code: discountCode })
|
||||||
// await applyDiscountCode(discountCode)
|
|
||||||
toast('کد تخفیف با موفقیت اعمال شد', 'success')
|
toast('کد تخفیف با موفقیت اعمال شد', 'success')
|
||||||
} catch {
|
setDiscountCode('')
|
||||||
toast('کد تخفیف نامعتبر است', 'error')
|
} catch (error: unknown) {
|
||||||
} finally {
|
const errorMessage = (error as { response?: { data?: { message?: string } } })?.response?.data?.message || 'کد تخفیف نامعتبر است'
|
||||||
setIsApplyingDiscount(false)
|
toast(errorMessage, 'error')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,16 +87,14 @@ const CartPayment: NextPage = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
const response = await checkoutMutation.mutateAsync({
|
||||||
// TODO: پیادهسازی API پرداخت نهایی
|
payment_method_id: selectedPaymentMethod
|
||||||
// await processPayment({
|
})
|
||||||
// paymentMethodId: selectedPaymentMethod,
|
|
||||||
// discountCode: discountCode || null,
|
if (response?.results?.paymentData?.redirectUrl) {
|
||||||
// shippingAddress: profile.userAddress
|
window.location.href = response.results.paymentData.redirectUrl
|
||||||
// })
|
} else {
|
||||||
toast('پرداخت با موفقیت انجام شد', 'success')
|
toast('خطا در دریافت لینک پرداخت', 'error')
|
||||||
} catch {
|
|
||||||
toast('خطا در پردازش پرداخت', 'error')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +107,7 @@ const CartPayment: NextPage = () => {
|
|||||||
discountCode={discountCode}
|
discountCode={discountCode}
|
||||||
setDiscountCode={setDiscountCode}
|
setDiscountCode={setDiscountCode}
|
||||||
onSubmit={handleDiscountCodeSubmit}
|
onSubmit={handleDiscountCodeSubmit}
|
||||||
isLoading={isApplyingDiscount}
|
isLoading={applyDiscountMutation.isPending}
|
||||||
/>
|
/>
|
||||||
<div className='mt-5 border border-border rounded-2xl p-4 sm:p-6 font-light'>
|
<div className='mt-5 border border-border rounded-2xl p-4 sm:p-6 font-light'>
|
||||||
<div>انتخاب روش پرداخت</div>
|
<div>انتخاب روش پرداخت</div>
|
||||||
@@ -153,6 +151,7 @@ const CartPayment: NextPage = () => {
|
|||||||
onConfirm={handlePayment}
|
onConfirm={handlePayment}
|
||||||
confirmLabel="پرداخت"
|
confirmLabel="پرداخت"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
isLoading={checkoutMutation.isPending}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ import {
|
|||||||
CartResponseType,
|
CartResponseType,
|
||||||
ShippingCostResponseType,
|
ShippingCostResponseType,
|
||||||
PaymentMethodsResponseType,
|
PaymentMethodsResponseType,
|
||||||
|
CheckoutCartType,
|
||||||
|
CheckoutResponseType,
|
||||||
|
ApplyDiscountType,
|
||||||
|
ApplyDiscountResponseType,
|
||||||
|
PaymentStatusType,
|
||||||
|
PaymentStatusResponseType,
|
||||||
|
BulkAddCartType,
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
export const getCart = async (): Promise<CartResponseType> => {
|
export const getCart = async (): Promise<CartResponseType> => {
|
||||||
@@ -37,3 +44,34 @@ export const paymentMethods = async (): Promise<PaymentMethodsResponseType> => {
|
|||||||
const { data } = await axios.get("/payment/methods");
|
const { data } = await axios.get("/payment/methods");
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkoutCart = async (
|
||||||
|
params: CheckoutCartType
|
||||||
|
): Promise<CheckoutResponseType> => {
|
||||||
|
const { data } = await axios.post("/payment/checkout/cart", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const applyDiscountCode = async (
|
||||||
|
params: ApplyDiscountType
|
||||||
|
): Promise<ApplyDiscountResponseType> => {
|
||||||
|
const { data } = await axios.post("/cart/apply-discount", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const checkPaymentStatus = async (
|
||||||
|
params: PaymentStatusType
|
||||||
|
): Promise<PaymentStatusResponseType> => {
|
||||||
|
const { data } = await axios.post("/payment/verify", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeAllCart = async () => {
|
||||||
|
const { data } = await axios.post("/cart/clear");
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const bulkAddCart = async (params: BulkAddCartType) => {
|
||||||
|
const { data } = await axios.post("/cart/bulk-add", params);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -167,6 +167,16 @@ export type RemoveCartType = {
|
|||||||
variantId: string;
|
variantId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BulkAddCartItemType = {
|
||||||
|
productId: number;
|
||||||
|
variantId: string;
|
||||||
|
quantity: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BulkAddCartType = {
|
||||||
|
items: BulkAddCartItemType[];
|
||||||
|
};
|
||||||
|
|
||||||
// Shipping Cost Types
|
// Shipping Cost Types
|
||||||
export type ShippingItemType = {
|
export type ShippingItemType = {
|
||||||
product: number;
|
product: number;
|
||||||
@@ -302,3 +312,104 @@ export type PaymentMethodsResponseType = {
|
|||||||
paymentMethods: PaymentMethodType[];
|
paymentMethods: PaymentMethodType[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type CheckoutCartType = {
|
||||||
|
payment_method_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CheckoutResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
paymentData: {
|
||||||
|
redirectUrl: string;
|
||||||
|
message: string;
|
||||||
|
authority: string;
|
||||||
|
};
|
||||||
|
order: {
|
||||||
|
user: string;
|
||||||
|
payment: string;
|
||||||
|
shipmentAddress: {
|
||||||
|
address: string;
|
||||||
|
city: string;
|
||||||
|
province: string;
|
||||||
|
phone: string;
|
||||||
|
plaque: string;
|
||||||
|
postalCode: string;
|
||||||
|
_id: string;
|
||||||
|
};
|
||||||
|
orderStatus: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
_id: number;
|
||||||
|
};
|
||||||
|
orderItems: Array<{
|
||||||
|
order: number;
|
||||||
|
shop: string;
|
||||||
|
shipmentItems: Array<{
|
||||||
|
product: number;
|
||||||
|
variant: string;
|
||||||
|
quantity: number;
|
||||||
|
cancelled_quantity: number;
|
||||||
|
returned_quantity: number;
|
||||||
|
selling_price: number;
|
||||||
|
retail_price: number;
|
||||||
|
discount_percent: number;
|
||||||
|
shipmentCost: number;
|
||||||
|
isFreeShip: boolean;
|
||||||
|
_id: string;
|
||||||
|
}>;
|
||||||
|
shipper: number;
|
||||||
|
totalSellingPrice: number;
|
||||||
|
totalRetailPrice: number;
|
||||||
|
totalShipmentCost: number;
|
||||||
|
totalCouponDiscount: number;
|
||||||
|
totalPaymentPrice: number;
|
||||||
|
itemsCount: number;
|
||||||
|
trackCode: string | null;
|
||||||
|
postingDate: string | null;
|
||||||
|
postingReceipt: string | null;
|
||||||
|
status: string;
|
||||||
|
_id: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ApplyDiscountType = {
|
||||||
|
discount_code: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ApplyDiscountResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
discount: {
|
||||||
|
code: string;
|
||||||
|
amount: number;
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PaymentStatusType = {
|
||||||
|
authority: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PaymentStatusResponseType = {
|
||||||
|
status: number;
|
||||||
|
success: boolean;
|
||||||
|
results: {
|
||||||
|
paymentStatus: "success" | "failed" | "pending";
|
||||||
|
orderStatus: string;
|
||||||
|
message: string;
|
||||||
|
orderId?: number;
|
||||||
|
orderData?: {
|
||||||
|
orderId: number;
|
||||||
|
totalPaymentPrice: number;
|
||||||
|
createdAt: string;
|
||||||
|
orderStatus: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ type CartSummaryProps = {
|
|||||||
confirmLabel?: string;
|
confirmLabel?: string;
|
||||||
onDownloadInvoice?: () => void;
|
onDownloadInvoice?: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
isLoading?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Row: FC<{ label: string; value: string | number; emphasize?: boolean }> = (
|
const Row: FC<{ label: string; value: string | number; emphasize?: boolean }> = (
|
||||||
@@ -32,7 +33,7 @@ const Row: FC<{ label: string; value: string | number; emphasize?: boolean }> =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CartSummary: FC<CartSummaryProps> = (props) => {
|
const CartSummary: FC<CartSummaryProps> = (props) => {
|
||||||
const { itemsCount, itemsPrice, discount, shippingCost, total, onConfirm, onDownloadInvoice, className, confirmHref, confirmLabel } = props;
|
const { itemsCount, itemsPrice, discount, shippingCost, total, onConfirm, onDownloadInvoice, className, confirmHref, confirmLabel, isLoading } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"rounded-xl sm:rounded-2xl border border-border p-4 sm:p-6 h-fit bg-[#FAFAFA] " + (className ?? "")}>
|
<div className={"rounded-xl sm:rounded-2xl border border-border p-4 sm:p-6 h-fit bg-[#FAFAFA] " + (className ?? "")}>
|
||||||
@@ -61,14 +62,15 @@ const CartSummary: FC<CartSummaryProps> = (props) => {
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => !confirmHref && onConfirm?.()}
|
onClick={() => !confirmHref && onConfirm?.()}
|
||||||
className="w-full h-10 sm:h-12 rounded-lg sm:rounded-xl text-white text-sm sm:text-base"
|
disabled={isLoading}
|
||||||
|
className="w-full h-10 sm:h-12 rounded-lg sm:rounded-xl text-white text-sm sm:text-base disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
>
|
>
|
||||||
{confirmHref ? (
|
{confirmHref ? (
|
||||||
<Link href={confirmHref} className="w-full h-full flex items-center justify-center">
|
<Link href={confirmHref} className="w-full h-full flex items-center justify-center">
|
||||||
{confirmLabel ?? "تایید و تکمیل سفارش"}
|
{confirmLabel ?? "تایید و تکمیل سفارش"}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
confirmLabel ?? "تایید و تکمیل سفارش"
|
isLoading ? "در حال پردازش..." : (confirmLabel ?? "تایید و تکمیل سفارش")
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
export const TOKEN_NAME = "sh_token";
|
export const TOKEN_NAME = "sh_token";
|
||||||
export const REFRESH_TOKEN_NAME = "sh_refresh_token";
|
export const REFRESH_TOKEN_NAME = "sh_refresh_token";
|
||||||
export const BASE_URL = "https://api.shinan.ir";
|
export const BASE_URL = "https://shop-api.dev.danakcorp.com";
|
||||||
// export const BASE_URL = "https://api-sondos.run.danakcorp.com";
|
// export const BASE_URL = "https://api-sondos.run.danakcorp.com";
|
||||||
|
|
||||||
export const PRIMARY_COLOR = "#015699";
|
export const PRIMARY_COLOR = "#015699";
|
||||||
|
|||||||
Reference in New Issue
Block a user