fix: price variant + perfoma invoice download
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
'use client'
|
||||
import { useGetCart } from "@/app/cart/hooks/useCartData"
|
||||
import { NumberFormat, toJalaliDate } from "@/config/func"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { useEffect } from "react"
|
||||
import Image from "next/image"
|
||||
|
||||
const InvoicePage = () => {
|
||||
const { data, isLoading } = useGetCart()
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoading && !data?.results?.cart?.items?.length) {
|
||||
router.push('/cart')
|
||||
}
|
||||
}, [data, isLoading, router])
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="text-lg">در حال بارگذاری...</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const cart = data?.results?.cart
|
||||
if (!cart?.items?.length) return null
|
||||
|
||||
const handlePrint = () => {
|
||||
window.print()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white p-4 sm:p-8">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="no-print mb-6 flex justify-between items-center">
|
||||
<button
|
||||
onClick={() => router.back()}
|
||||
className="px-4 py-2 bg-gray-200 rounded-lg hover:bg-gray-300"
|
||||
>
|
||||
بازگشت
|
||||
</button>
|
||||
<button
|
||||
onClick={handlePrint}
|
||||
className="px-6 py-2 bg-primary text-white rounded-lg hover:bg-primary/90"
|
||||
>
|
||||
پرینت فاکتور
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border-2 border-gray-200 rounded-lg p-6 sm:p-8 print:border-0">
|
||||
<div className="flex items-center justify-between border-b pb-4 mb-6">
|
||||
<div>
|
||||
<Image
|
||||
src="/images/logo.png"
|
||||
alt="لوگو"
|
||||
width={120}
|
||||
height={40}
|
||||
className="h-10 w-auto"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<h1 className="text-2xl font-bold mb-2">پیشفاکتور خرید</h1>
|
||||
<p className="text-sm text-gray-600">
|
||||
تاریخ: {toJalaliDate(new Date())}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-6 grid grid-cols-2 gap-4 bg-gray-50 p-4 rounded-lg">
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">نام و نام خانوادگی</p>
|
||||
<p className="font-medium">{cart.user?.fullName || '-'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">شماره تماس</p>
|
||||
<p className="font-medium">{cart.user?.phoneNumber || '-'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">شماره فاکتور</p>
|
||||
<p className="font-medium">{cart._id.slice(-8).toUpperCase()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-gray-600">تعداد کالا</p>
|
||||
<p className="font-medium">{NumberFormat(cart.items_count)} محصول</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<h2 className="text-lg font-bold mb-4">لیست محصولات</h2>
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border border-gray-300 p-3 text-right">ردیف</th>
|
||||
<th className="border border-gray-300 p-3 text-right">محصول</th>
|
||||
<th className="border border-gray-300 p-3 text-center">تعداد</th>
|
||||
<th className="border border-gray-300 p-3 text-left">قیمت واحد</th>
|
||||
<th className="border border-gray-300 p-3 text-left">تخفیف</th>
|
||||
<th className="border border-gray-300 p-3 text-left">قیمت کل</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{cart.items.map((item, index) => {
|
||||
const retailPrice = item.variant.price.retailPrice
|
||||
const sellingPrice = item.variant.price.selling_price
|
||||
const totalRetail = retailPrice * item.quantity
|
||||
const totalSelling = sellingPrice * item.quantity
|
||||
const discount = totalRetail - totalSelling
|
||||
|
||||
return (
|
||||
<tr key={`${item.product._id}-${item.variant._id}`}>
|
||||
<td className="border border-gray-300 p-3 text-center">
|
||||
{NumberFormat(index + 1)}
|
||||
</td>
|
||||
<td className="border border-gray-300 p-3">
|
||||
<div>
|
||||
<p className="font-medium">{item.product.title_fa}</p>
|
||||
<p className="text-xs text-gray-600 mt-1">
|
||||
فروشنده: {item.variant.shop.shopName}
|
||||
</p>
|
||||
{item.variant.warranty && (
|
||||
<p className="text-xs text-gray-600">
|
||||
گارانتی: {item.variant.warranty.name}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="border border-gray-300 p-3 text-center">
|
||||
{NumberFormat(item.quantity)}
|
||||
</td>
|
||||
<td className="border border-gray-300 p-3 text-left">
|
||||
{NumberFormat(retailPrice)} تومان
|
||||
</td>
|
||||
<td className="border border-gray-300 p-3 text-left">
|
||||
{discount > 0 ? `${NumberFormat(discount)} تومان` : '-'}
|
||||
</td>
|
||||
<td className="border border-gray-300 p-3 text-left font-medium">
|
||||
{NumberFormat(totalSelling)} تومان
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t pt-4">
|
||||
<div className="flex justify-end">
|
||||
<div className="w-full sm:w-80 space-y-3">
|
||||
<div className="flex justify-between text-gray-700">
|
||||
<span>قیمت کالاها:</span>
|
||||
<span>{NumberFormat(cart.retail_price)} تومان</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-gray-700">
|
||||
<span>تخفیف:</span>
|
||||
<span className="text-red-600">
|
||||
{NumberFormat(cart.total_discount)} تومان
|
||||
</span>
|
||||
</div>
|
||||
{cart.coupon_discount > 0 && (
|
||||
<div className="flex justify-between text-gray-700">
|
||||
<span>تخفیف کد تخفیف:</span>
|
||||
<span className="text-red-600">
|
||||
{NumberFormat(cart.coupon_discount)} تومان
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-between text-xl font-bold border-t pt-3">
|
||||
<span>جمع کل:</span>
|
||||
<span className="text-primary">
|
||||
{NumberFormat(cart.payable_price)} تومان
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-8 pt-6 border-t text-center text-sm text-gray-600">
|
||||
<p>
|
||||
این پیشفاکتور صرفاً جهت اطلاع شما صادر شده و فاکتور نهایی پس از تکمیل خرید ارسال خواهد شد.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default InvoicePage
|
||||
|
||||
@@ -8,9 +8,10 @@ import { NextPage } from "next"
|
||||
import { useGetCart, useRemoveAllCart } from "./hooks/useCartData"
|
||||
import { toast } from "@/components/Toast"
|
||||
import { useState } from "react"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
const Cart: NextPage = () => {
|
||||
|
||||
const router = useRouter()
|
||||
const { data, isLoading, error } = useGetCart();
|
||||
const removeAllCartMutation = useRemoveAllCart()
|
||||
const [isClearingAll, setIsClearingAll] = useState(false)
|
||||
@@ -113,6 +114,7 @@ const Cart: NextPage = () => {
|
||||
total={cart?.payable_price || 0}
|
||||
confirmHref="/cart/shipping"
|
||||
confirmLabel="ادامه به آدرس و ارسال"
|
||||
onDownloadInvoice={() => router.push('/cart/invoice')}
|
||||
className="w-full lg:w-[360px] xl:w-[400px]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -282,3 +282,26 @@ textarea.place-black::placeholder {
|
||||
.rmdp-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Print Styles */
|
||||
@media print {
|
||||
body {
|
||||
print-color-adjust: exact;
|
||||
-webkit-print-color-adjust: exact;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
|
||||
/* Hide all fixed elements (header, mobile menu, etc) */
|
||||
.fixed {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Hide no-print class */
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 1cm;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import Image from 'next/image'
|
||||
import Cart from './Cart'
|
||||
import { PRIMARY_COLOR } from '@/config/const'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useProductStore } from '../store/Store'
|
||||
|
||||
interface ShopInformationProps {
|
||||
product: Product
|
||||
@@ -15,12 +16,17 @@ interface ShopInformationProps {
|
||||
|
||||
const ShopInformation = ({ product }: ShopInformationProps) => {
|
||||
const router = useRouter()
|
||||
const { variantId } = useProductStore()
|
||||
|
||||
const defaultVariant = product.default_variant
|
||||
const shop = defaultVariant.shop
|
||||
const price = defaultVariant.price
|
||||
const warranty = defaultVariant.warranty
|
||||
const postingTime = defaultVariant.postingTime
|
||||
// پیدا کردن variant انتخابی یا استفاده از default_variant
|
||||
const selectedVariant = variantId
|
||||
? product.variants.find((variant) => variant._id === variantId) || product.default_variant
|
||||
: product.default_variant
|
||||
|
||||
const shop = selectedVariant.shop
|
||||
const price = selectedVariant.price
|
||||
const warranty = selectedVariant.warranty
|
||||
const postingTime = selectedVariant.postingTime
|
||||
|
||||
const formatPrice = (price: number) => {
|
||||
return price.toLocaleString('fa-IR')
|
||||
|
||||
@@ -53,6 +53,7 @@ const CartSummary: FC<CartSummaryProps> = (props) => {
|
||||
</div>
|
||||
|
||||
<div className="mt-6 sm:mt-8 space-y-2 sm:space-y-3">
|
||||
{onDownloadInvoice && (
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => onDownloadInvoice?.()}
|
||||
@@ -60,6 +61,7 @@ const CartSummary: FC<CartSummaryProps> = (props) => {
|
||||
>
|
||||
دانلود پیشفاکتور
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => !confirmHref && onConfirm?.()}
|
||||
|
||||
Reference in New Issue
Block a user