Files
danak-console/src/components/Invoice.tsx
T
hamid zarghami 31fd405773 latefee
2025-06-01 11:38:20 +03:30

280 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useEffect } from 'react';
import './Invoice.css';
import { useParams } from 'react-router-dom';
import { useGetInvoiceDetail } from '../pages/receipts/hooks/useReceiptData';
import { useGetProfile } from '../pages/profile/hooks/useProfileData';
import moment from 'moment-jalaali';
import { NumberFormat } from '../config/func';
import { ReceiptDetailItemType } from '../pages/receipts/types/ReceiptTypes';
import SignImage from '../assets/images/sign.png'
import { useTranslation } from 'react-i18next';
import Button from './Button';
import { Printer } from 'iconsax-react';
const Invoice = () => {
const { t } = useTranslation('global')
const { id } = useParams();
const getInvoice = useGetInvoiceDetail(id ? id : '');
const getProfile = useGetProfile();
useEffect(() => {
const handleResize = () => {
try {
const mvp = document.getElementById('vp');
if (!mvp) return;
if (screen.width >= 300 && screen.width < 500) {
mvp.setAttribute('content', 'initial-scale=0.35,width=device-width');
} else if (screen.width > 500 && screen.width < 600) {
mvp.setAttribute('content', 'initial-scale=0.6,width=device-width');
} else if (screen.width > 600 && screen.width < 700) {
mvp.setAttribute('content', 'initial-scale=0.7,width=device-width');
}
} catch (e) {
console.error('Error setting viewport:', e);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
const handlePrint = () => {
// Add print-specific styles before printing
const style = document.createElement('style');
style.innerHTML = `
@media print {
@page {
margin: 0;
}
body * {
visibility: hidden;
}
.invoice-container, .invoice-container * {
visibility: visible;
}
}
`;
document.head.appendChild(style);
window.print();
document.head.removeChild(style);
};
if (getInvoice.isPending || getProfile.isPending) {
return <div></div>;
}
const invoice = getInvoice.data?.data?.invoice;
const profile = getProfile.data?.data?.user;
return (
<div className="invoice-container">
<meta
id="vp"
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<Button
className='w-fit px-7 print-button mb-4'
onClick={handlePrint}
>
<div className='flex gap-2'>
<Printer size={20} color='white' />
<div>چاپ</div>
</div>
</Button>
<div className="mobile-scroll-wrapper">
<div className="page">
<h1 className='font-bold text-lg pb-4' style={{ textAlign: 'center' }}>
{invoice?.status === 'PAID' ? 'فاکتور (پرداخت شده)' : 'پیش فاکتور (پرداخت نشده)'}
</h1>
<table className="header-table" style={{ width: '100%' }}>
<tr>
<td style={{ width: '1.8cm', height: '2.5cm', verticalAlign: 'middle', paddingBottom: '4px' }}>
<div className="header-item-wrapper">
<div className="portait" style={{ margin: '5px' }}>فروشندده</div>
</div>
</td>
<td style={{ padding: '0 4px 4px', height: '2cm' }}>
<div className="bordered grow header-item-data">
<table className="grow centered">
<tr>
<td style={{ width: '7cm' }}>
<span className="label">فروشنده:</span> رسا نگاره داناک
</td>
<td style={{ width: '5cm' }}>
<span className="label">شناسه ملی:</span> ۱۴۰۰۵۴۵۳۱۹۰
</td>
<td>
<span className="label">شماره ثبت:</span> ۴۸۳۵۱۶
</td>
<td>
<span className="label">شماره اقتصادی:</span> ۱۴۰۰۵۴۵۳۱۹۰
</td>
</tr>
<tr>
<td colSpan={2}>
<span className="label">نشانی شرکت:</span>تهران - یوسف آباد - خیابان فتحی شقاقی - پلاک ۵ - واحد ۱۳
</td>
<td>
<span className="label">کدپستی:</span> ۱۴۳۳۶۳۴۴۴۶
</td>
<td>
<span className="label">تلفن و فکس:</span> ۰۲۱۹۱۶۹۳۵۳۳
</td>
</tr>
</table>
</div>
</td>
<td style={{ width: '7cm', height: '2cm', padding: '0 4px 4px 0' }}>
<div className="bordered" style={{ textAlign: 'center', height: '100%', padding: '0.4cm 0.2cm' }}>
<div className="flex">
<div className="font-small">شماره فاکتور:</div>
<div className="flex-grow" style={{ textAlign: 'left' }}>{moment(invoice?.createdAt).format('jYYYY') + invoice?.numericId}</div>
</div>
<div className="flex">
<div>تاریخ:</div>
<div className="flex-grow" style={{ textAlign: 'left' }}>{moment(invoice?.createdAt).format('jYYYY/jMM/jDD')}</div>
</div>
<div className="flex" style={{ marginBottom: '4px' }}>
<div>پیگیری:</div>
<div className="flex-grow font-medium" style={{ textAlign: 'left' }}>{invoice?.numericId}</div>
</div>
</div>
</td>
</tr>
<tr>
<td style={{ width: '1.8cm', height: '2.5cm', verticalAlign: 'middle', paddingBottom: '4px' }}>
<div className="header-item-wrapper">
<div className="portait" style={{ margin: '5px' }}>خریدار</div>
</div>
</td>
<td style={{ padding: '0 4px 4px', height: '2cm' }}>
<div className="bordered grow header-item-data">
<table className="grow centered">
<tr>
<td style={{ width: '7cm' }}>
<span className="label">خریدار:</span> {profile?.financialType === 'LEGAL' ? profile?.legalUser?.registrationName : `${profile?.firstName} ${profile?.lastName}`}
</td>
<td style={{ width: '5cm' }}>
<span className="label">شناسه ملی:</span> {profile?.nationalCode || '-'}
</td>
<td>
<span className="label">شماره ثبت:</span> {profile?.financialType === 'LEGAL' ? profile?.legalUser?.registrationCode : '-'}
</td>
<td>
<span className="label">شماره اقتصادی:</span> {profile?.financialType === 'LEGAL' ? profile?.legalUser?.economicCode : '-'}
</td>
</tr>
<tr>
<td colSpan={2}>
<span className="label">نشانی:</span> {profile?.financialType === 'LEGAL' ? profile?.legalUser?.address?.fullAddress : profile?.address?.fullAddress || '-'}
</td>
<td>
<span className="label">کدپستی:</span> {profile?.financialType === 'LEGAL' ? profile?.legalUser?.address?.postalCode : profile?.address?.postalCode || '-'}
</td>
<td>
<span className="label">تلفن:</span> {profile?.phone || '-'}
</td>
</tr>
</table>
</div>
</td>
<td style={{ width: '7cm', height: '2cm', padding: '0 4px 4px 0' }}>
<div className="bordered" style={{ textAlign: 'center', height: '100%', padding: '0.4cm 0.2cm' }}>
<div className="flex">
<div className="font-small">نوع شخص:</div>
<div className="flex-grow" style={{ textAlign: 'left' }}>{profile?.financialType === 'LEGAL' ? 'حقوقی' : 'حقیقی'}</div>
</div>
<div className="flex">
<div>وضعیت:</div>
<div className="flex-grow" style={{ textAlign: 'left' }}>{t(`receip.${invoice?.status}`)}</div>
</div>
<div className="flex" style={{ marginBottom: '4px' }}>
<div>تاریخ پرداخت:</div>
<div className="flex-grow font-medium" style={{ textAlign: 'left' }}>{invoice?.paidAt ? moment(invoice?.paidAt).format('jYYYY/jMM/jDD') : '-'}</div>
</div>
</div>
</td>
</tr>
</table>
<table className="content-table">
<thead>
<tr>
<th style={{ width: "1cm" }} >ردیف</th>
<th style={{ width: '2.5cm' }}>شناسه کالا یا خدمت</th>
<th style={{ width: '5cm' }}>شرح کالا یا خدمت</th>
<th style={{ width: "1.5cm" }}>تعداد</th>
<th style={{ width: '2.3cm' }}>مبلغ واحد (ریال)</th>
<th style={{ width: '2.3cm' }}>مبلغ کل (ریال)</th>
<th style={{ width: '2.0cm' }}>تخفیف (درصد)</th>
<th style={{ width: "1.8cm" }}>جریمه دیرکرد</th>
<th style={{ width: '2.3cm' }}>مبلغ کل پس از تخفیف (ریال)</th>
<th style={{ width: '2.3cm' }}>جمع مالیات و عوارض ارزش افزوده (ریال)</th>
<th style={{ width: '2.5cm' }}>جمع کل پس از تخفیف و مالیات و عوارض (ریال)</th>
</tr>
</thead>
<tbody>
{invoice?.items?.map((item: ReceiptDetailItemType, index: number) => (
<tr key={item.id}>
<td>{index + 1}</td>
<td>2720000114542</td>
<td>{item.name}</td>
<td>{item.count}</td>
<td>{NumberFormat(Number(item.unitPrice) * 10)}</td>
<td>{NumberFormat(Number(item.unitPrice) * Number(item.count) * 10)}</td>
<td>{NumberFormat(Number(item.discount))}</td>
<td>{NumberFormat(Number(invoice?.lateFee) * 10)}</td>
<td>{NumberFormat(Number(item.totalPrice) * 10)}</td>
<td>{NumberFormat(Number(item.totalPrice) * 0.1 * 10)}</td>
<td>{NumberFormat(Number(item.totalPrice) * 0.1 * 10 + Number(item.totalPrice) * 10)}</td>
</tr>
))}
</tbody>
<tfoot>
<tr>
<td colSpan={6}></td>
<td colSpan={4} className="font-small">
جمع کل پس از کسر تخفیف با احتساب مالیات و عوارض (ریال):
</td>
<td><span className="ltr">{NumberFormat(Number(invoice?.totalPrice) * 10)}</span></td>
</tr>
<tr>
<td colSpan={4}>
اعتبار مالیاتی قابل استفاده توسط خریدار
</td>
<td colSpan={7} className="font-small">
</td>
</tr>
<tr style={{ background: '#fff' }}>
<td colSpan={11} style={{ height: '2.5cm', verticalAlign: 'top', padding: '10px' }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
<div style={{ width: '40%', textAlign: 'right' }}>مهر و امضای فروشنده:</div>
<div style={{ width: '40%', textAlign: 'right' }}>تاریخ خرید:</div>
</div>
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
<div style={{ width: '40%', display: 'flex', justifyContent: 'center' }}>
<img className="footer-img" width="170px" src={SignImage} />
</div>
<div style={{ width: '40%', textAlign: 'right', paddingTop: '10px' }}>
{invoice?.paidAt ? moment(invoice?.paidAt).format('jYYYY/jMM/jDD') : '-'}
</div>
</div>
</div>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
);
};
export default Invoice;