Files
danak-console/src/pages/receipts/Detail.tsx
T
2025-05-14 16:29:30 +03:30

343 lines
19 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 { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom'
import { useApplyDiscount, useGetInvoiceDetail, useRemoveDiscount } from './hooks/useReceiptData'
import { ApplyDiscountType, ReceiptDetailItemType } from './types/ReceiptTypes'
import { NumberFormat } from '../../config/func'
import moment from 'moment-jalaali'
import PageLoading from '../../components/PageLoading'
import LegalInfo from './components/LegalInfo'
import RealInfo from './components/RealInfo'
import RegisterInfo from './components/RegisterInfo'
import { clx } from '../../helpers/utils'
import Button from '../../components/Button'
import ApproveInvoice from './components/ApproveInvoice'
import PayInvoice from './components/PayInvoice'
import Input from '../../components/Input'
import { Helmet } from 'react-helmet-async'
import { useGetProfile } from '../profile/hooks/useProfileData'
import { toast } from 'react-toastify'
import { ErrorType } from '../../helpers/types'
import PDFGenerator from '../../components/PDFGenerator'
import { useGetGetWays } from '../wallet/hooks/useWalletData'
import { GatewayItemType } from '../wallet/types/WalletTypes'
const ReceiptsDetail: FC = () => {
const { id } = useParams()
const { t } = useTranslation('global')
const [code, setCode] = useState<string>('')
const [gateWayId, setGateWayId] = useState<string>('')
const getProfile = useGetProfile()
const getInvoce = useGetInvoiceDetail(id ? id : '')
const applyDiscount = useApplyDiscount()
const removeDiscount = useRemoveDiscount()
const getWays = useGetGetWays()
const handleApplyDiscount = () => {
const params: ApplyDiscountType = {
id: id ? id : '',
code: code
}
applyDiscount.mutate(params, {
onSuccess: () => {
toast.success(t('receip.discount_applied'))
getInvoce.refetch()
},
onError: (error: ErrorType) => {
toast.error(error?.response?.data?.error?.message[0])
}
})
}
const handleRemoveDiscount = () => {
removeDiscount.mutate({ id: id ? id : '' }, {
onSuccess: () => {
toast.success(t('receip.discount_removed'))
getInvoce.refetch()
},
onError: (error: ErrorType) => {
toast.error(error?.response?.data?.error?.message[0])
}
})
}
useEffect(() => {
if (getWays.data) {
setGateWayId(getWays.data?.data?.paymentGateways?.[0]?.id)
}
}, [getWays.data])
return (
<div className='mt-4'>
<Helmet>
<title>
داناک | صورتحساب
</title>
</Helmet>
<div className='flex xl:flex-row flex-col gap-4 items-center'>
<div className='flex gap-6 items-center'>
<div className='whitespace-nowrap'>{t('receip.detail_account')}</div>
<ApproveInvoice status={getInvoce.data?.data?.invoice?.status} id={id ? id : ''} refetch={getInvoce.refetch} />
</div>
{
!getInvoce.data?.data?.invoice?.discount && ['PENDING', 'APPROVED', 'WAIT_PAYMENT'].includes(getInvoce.data?.data?.invoice?.status) ?
<div className='flex -mt-1 gap-2 items-center w-full'>
<div className='w-full xl:w-fit'>
<Input
className='bg-transparent border border-border xl:max-w-40'
placeholder={t('receip.discount_code')}
value={code}
onChange={(e) => setCode(e.target.value)}
/>
</div>
<Button
label={t('receip.apply')}
className='bg-transparent text-black border border-black mt-1 px-5 w-fit'
onClick={handleApplyDiscount}
isLoading={applyDiscount.isPending}
/>
</div>
: getInvoce.data?.data?.invoice?.discount &&
<div className='flex -mt-1 gap-2 items-center w-full'>
<div className='w-full xl:w-fit'>
<Button
label={t('receip.remove_discount')}
className='bg-transparent text-black border border-black mt-1 px-5 w-fit'
onClick={handleRemoveDiscount}
/>
</div>
</div>
}
</div>
{
getInvoce.isPending || getProfile.isPending ?
<PageLoading />
:
<div className='flex xl:flex-row flex-col mt-8 gap-6'>
<div className='flex-1'>
<div id="receipt-details" className='w-full bg-white rounded-3xl p-8'>
<div className='flex justify-between items-center mb-6'>
<div className='text-lg font-medium'>
{t('receip.personal_information')}
</div>
</div>
{
getProfile.data?.data?.user?.financialType === 'LEGAL' ?
<LegalInfo />
:
getProfile.data?.data?.user?.financialType === 'REAL' ?
<RealInfo />
: <RegisterInfo data={getProfile.data?.data} />
}
<div className='mt-8'>
<div className='flex justify-between items-center mb-6'>
<div className='text-lg font-medium'>
{t('receip.detail_receip')}
</div>
</div>
<div className='mt-7 text-sm'>
<div className='flex justify-between items-center text-description h-14 font-medium'>
<div>
{t('receip.description')}
</div>
<div>
{t('receip.price')}
</div>
</div>
{
getInvoce.data?.data?.invoice?.items?.map((item: ReceiptDetailItemType) => {
return (
<div key={item.id} className='flex justify-between items-center text-xs border-t border-[#EAEDF5] h-14'>
<div className='flex gap-0.5'>
<span>{item.name}</span>
<span>{item.count}</span>
<span>عدد</span>
</div>
<div>
<span>{NumberFormat(item.totalPrice)}</span> تومان
</div>
</div>
)
})
}
<div className='flex justify-between items-center text-xs border-t border-[#EAEDF5] h-14'>
<div>
۱۰٪ ارزش افزوده
</div>
<div>
<span>{NumberFormat(getInvoce.data?.data?.invoice?.tax)}</span> تومان
</div>
</div>
<div className='flex justify-between gap-1 items-center text-xs border-t border-[#EAEDF5] h-14'>
<div>
جمع کل
</div>
<div className='flex gap-1'>
{
getInvoce.data?.data?.invoice?.originalPrice !== getInvoce.data?.data?.invoice?.totalPrice && (
<><span className='line-through'>{NumberFormat(getInvoce.data?.data?.invoice?.originalPrice)}</span></>
)
}
<span>{NumberFormat(getInvoce.data?.data?.invoice?.totalPrice)}</span> تومان
</div>
</div>
</div>
</div>
<div className='mt-8'>
<div className='flex justify-between items-center mb-6'>
<div className='text-lg font-medium'>
{t('receip.receip_information')}
</div>
</div>
<div className='mt-6 text-xs font-extralight'>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.date_factor')}
</div>
<div>
{moment(getInvoce.data?.data?.invoice?.createdAt).format('jYYYY-jMM-jDD')}
</div>
</div>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.due_date')}
</div>
<div>
{moment(getInvoce.data?.data?.invoice?.dueDate).format('jYYYY-jMM-jDD')}
</div>
</div>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.factor_number')}
</div>
<div>
{moment(getInvoce.data?.data?.invoice.createdAt).format('jYYYY') + getInvoce.data?.data?.invoice.numericId}
</div>
</div>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.status_factor')}
</div>
<div>
{t(`receip.${getInvoce.data?.data?.invoice?.status}`)}
</div>
</div>
</div>
</div>
</div>
</div>
<div className='bg-white xl:w-sidebar text-sm h-fit rounded-3xl p-8'>
{
getInvoce.data?.data?.invoice?.status === 'PAID' &&
<div className='p-6 bg-green-50 rounded-2xl text-green-400 text-xs mb-6'>
<p>{t('receip.thank_pay_1')}</p>
<p className='mt-1'>{t('receip.thank_pay_2')}</p>
</div>
}
<div className='flex justify-between items-center'>
<div>
{t('receip.receip_information')}
</div>
<div className={clx(
'border border-orange-400 text-orange-400 rounded-lg text-[9px] h-6 flex items-center px-1',
getInvoce.data?.data?.invoice?.status === 'PAID' ? 'border-green-400 text-green-400' : getInvoce.data?.data?.invoice?.status !== 'PENDING' ? 'border-red-400 text-red-400' : 'border-orange-400 text-orange-400'
)}>
<div>{t(`receip.${getInvoce.data?.data?.invoice?.status}`)}</div>
</div>
</div>
<div className='mt-6 text-xs font-extralight'>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.date_factor')}
</div>
<div>
{moment(getInvoce.data?.data?.invoice?.createdAt).format('jYYYY-jMM-jDD')}
</div>
</div>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.due_date')}
</div>
<div>
{moment(getInvoce.data?.data?.invoice?.dueDate).format('jYYYY-jMM-jDD')}
</div>
</div>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.factor_number')}
</div>
<div>
{moment(getInvoce.data?.data?.invoice.createdAt).format('jYYYY') + getInvoce.data?.data?.invoice.numericId}
</div>
</div>
<div className='flex justify-between h-12 border-b items-center'>
<div className='text-description'>
{t('receip.status_factor')}
</div>
<div>
{t(`receip.${getInvoce.data?.data?.invoice?.status}`)}
</div>
</div>
{
getInvoce.data?.data?.invoice?.status === 'WAIT_PAYMENT' &&
<div className='flex gap-4 items-center mt-8'>
<PDFGenerator
elementId="receipt-details"
fileName={`receipt-${getInvoce.data?.data?.invoice.numericId}`}
/>
<PayInvoice
id={id ? id : ''}
refetch={getInvoce.refetch}
gateWayId={gateWayId}
/>
</div>
}
{
getInvoce.data?.data?.remainingToCharge > 0 &&
<div className='flex mt-6 justify-center gap-2'>
{
getWays.data?.data?.paymentGateways?.map((item: GatewayItemType) => {
return (
<div key={item.id} className={clx(
'size-[72px] rounded-xl border border-border flex flex-col justify-center items-center',
gateWayId === item.id && 'border-black'
)}>
<img src={item.logoUrl} className='w-8' />
<div className='mt-1 text-[10px]'>
{item.name}
</div>
</div>
)
})
}
</div>
}
</div>
</div>
</div>
}
</div>
)
}
export default ReceiptsDetail