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 { useGetCart, useRemoveAllCart } from "./hooks/useCartData"
|
||||||
import { toast } from "@/components/Toast"
|
import { toast } from "@/components/Toast"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
|
import { useRouter } from "next/navigation"
|
||||||
|
|
||||||
const Cart: NextPage = () => {
|
const Cart: NextPage = () => {
|
||||||
|
const router = useRouter()
|
||||||
const { data, isLoading, error } = useGetCart();
|
const { data, isLoading, error } = useGetCart();
|
||||||
const removeAllCartMutation = useRemoveAllCart()
|
const removeAllCartMutation = useRemoveAllCart()
|
||||||
const [isClearingAll, setIsClearingAll] = useState(false)
|
const [isClearingAll, setIsClearingAll] = useState(false)
|
||||||
@@ -113,6 +114,7 @@ const Cart: NextPage = () => {
|
|||||||
total={cart?.payable_price || 0}
|
total={cart?.payable_price || 0}
|
||||||
confirmHref="/cart/shipping"
|
confirmHref="/cart/shipping"
|
||||||
confirmLabel="ادامه به آدرس و ارسال"
|
confirmLabel="ادامه به آدرس و ارسال"
|
||||||
|
onDownloadInvoice={() => router.push('/cart/invoice')}
|
||||||
className="w-full lg:w-[360px] xl:w-[400px]"
|
className="w-full lg:w-[360px] xl:w-[400px]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -282,3 +282,26 @@ textarea.place-black::placeholder {
|
|||||||
.rmdp-container {
|
.rmdp-container {
|
||||||
width: 100%;
|
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 Cart from './Cart'
|
||||||
import { PRIMARY_COLOR } from '@/config/const'
|
import { PRIMARY_COLOR } from '@/config/const'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
|
import { useProductStore } from '../store/Store'
|
||||||
|
|
||||||
interface ShopInformationProps {
|
interface ShopInformationProps {
|
||||||
product: Product
|
product: Product
|
||||||
@@ -15,12 +16,17 @@ interface ShopInformationProps {
|
|||||||
|
|
||||||
const ShopInformation = ({ product }: ShopInformationProps) => {
|
const ShopInformation = ({ product }: ShopInformationProps) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { variantId } = useProductStore()
|
||||||
|
|
||||||
const defaultVariant = product.default_variant
|
// پیدا کردن variant انتخابی یا استفاده از default_variant
|
||||||
const shop = defaultVariant.shop
|
const selectedVariant = variantId
|
||||||
const price = defaultVariant.price
|
? product.variants.find((variant) => variant._id === variantId) || product.default_variant
|
||||||
const warranty = defaultVariant.warranty
|
: product.default_variant
|
||||||
const postingTime = defaultVariant.postingTime
|
|
||||||
|
const shop = selectedVariant.shop
|
||||||
|
const price = selectedVariant.price
|
||||||
|
const warranty = selectedVariant.warranty
|
||||||
|
const postingTime = selectedVariant.postingTime
|
||||||
|
|
||||||
const formatPrice = (price: number) => {
|
const formatPrice = (price: number) => {
|
||||||
return price.toLocaleString('fa-IR')
|
return price.toLocaleString('fa-IR')
|
||||||
|
|||||||
@@ -53,13 +53,15 @@ const CartSummary: FC<CartSummaryProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 sm:mt-8 space-y-2 sm:space-y-3">
|
<div className="mt-6 sm:mt-8 space-y-2 sm:space-y-3">
|
||||||
<Button
|
{onDownloadInvoice && (
|
||||||
type="button"
|
<Button
|
||||||
onClick={() => onDownloadInvoice?.()}
|
type="button"
|
||||||
className="w-full h-10 sm:h-12 rounded-lg sm:rounded-xl bg-[#303030] text-white shadow hover:bg-[#303030]/90 text-sm sm:text-base"
|
onClick={() => onDownloadInvoice?.()}
|
||||||
>
|
className="w-full h-10 sm:h-12 rounded-lg sm:rounded-xl bg-[#303030] text-white shadow hover:bg-[#303030]/90 text-sm sm:text-base"
|
||||||
دانلود پیشفاکتور
|
>
|
||||||
</Button>
|
دانلود پیشفاکتور
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => !confirmHref && onConfirm?.()}
|
onClick={() => !confirmHref && onConfirm?.()}
|
||||||
|
|||||||
Reference in New Issue
Block a user