This commit is contained in:
hamid zarghami
2025-02-20 11:14:32 +03:30
parent d0800d959a
commit 9f2762ff24
7 changed files with 174 additions and 78 deletions
+21 -1
View File
@@ -201,7 +201,27 @@
"date_factor": "تاریخ صدور فاکتور",
"due_date": "تاریخ سررسید فاکتور",
"factor_number": "شماره فاکتور",
"status_factor": "وضعیت فاکتور"
"status_factor": "وضعیت فاکتور",
"customer": "مشتری",
"receipt_information": "اطلاعات صورتحساب",
"number": "شماره",
"product_name": "نام کالا",
"count": "تعداد",
"unit_amount": "مبلغ واحد",
"discount": "تخفیف(٪)",
"total_amount": "مبلغ کل(ریال)",
"tax": "مالیات بر ارزش افزوده (۰.۹ درصد)",
"total": "جمع",
"error_empty": "همه فیلد ها را پر کنید",
"date_receipt": "تاریخ صورتحساب",
"last_date_receipt": "آخرین مهلت پرداخت",
"service": "سرویس",
"status": "وضعیت تایید",
"status_paid": "وضعیت پرداخت",
"PENDING": "در انتظار",
"PAID": "پرداخت شده",
"CANCELED": "لغو شده",
"EXPIRED": "منقضی شده"
},
"edit": "ویرایش",
"transaction": {
+14 -5
View File
@@ -2,7 +2,7 @@ import { FC, useCallback, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import AvatarImage from '../../assets/images/avatar_image.png'
import Button from '../../components/Button'
import { DocumentUpload, Edit } from 'iconsax-react'
import { DocumentUpload, Edit, TickCircle } from 'iconsax-react'
import Input from '../../components/Input'
import DatePickerComponent from '../../components/DatePicker'
import Select from '../../components/Select'
@@ -258,17 +258,26 @@ const Profile: FC = () => {
error_text={formik.touched.userAddress && formik.errors.userAddress ? formik.errors.userAddress : ''}
/>
</div>
</div>
<div className='flex justify-end'>
<div className='flex justify-end mt-5'>
<Button
label={t('save')}
className='w-fit px-10'
onClick={() => formik.handleSubmit()}
isLoading={updateProfile.isPending}
/>
>
<div className='flex gap-2 items-center'>
<TickCircle size={20} color='white' />
<div>
{t('save')}
</div>
</div>
</Button>
</div>
</div>
</div>
<div className='h-20 xl:hidden'></div>
</div>
+4
View File
@@ -3,10 +3,14 @@ import { useTranslation } from 'react-i18next'
import { Edit } from 'iconsax-react'
import StatusCircle from '../../components/StatusCircle'
import SamanImage from '../../assets/images/saman.png'
import { useParams } from 'react-router-dom'
import { useGetInvoiceDetail } from './hooks/useReceiptData'
const ReceiptsDetail: FC = () => {
const { id } = useParams()
const { t } = useTranslation('global')
const getInvoce = useGetInvoiceDetail(id ? id : '')
return (
<div className='mt-4'>
+66 -50
View File
@@ -1,15 +1,21 @@
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Tabs from '../../components/Tabs'
import { Calendar, CloseCircle, Eye, FolderOpen, MoneyChange, WalletCheck, WalletRemove, WalletSearch } from 'iconsax-react'
import { CloseCircle, Eye, FolderOpen, WalletCheck, WalletRemove } from 'iconsax-react'
import Td from '../../components/Td'
import { Link } from 'react-router-dom'
import { Pages } from '../../config/Pages'
import { useGetInvoices } from './hooks/useReceiptData'
import PageLoading from '../../components/PageLoading'
import { NumberFormat } from '../../config/func'
import { ReceiptItemType } from './types/ReceiptTypes'
import moment from 'moment-jalaali'
const ReceiptsList: FC = () => {
const { t } = useTranslation('global')
const [activeTab, setActiveTab] = useState<string>('unpaid')
const [activeTab, setActiveTab] = useState<"PENDING" | "PAID" | "CANCELED" | "EXPIRED">('PENDING')
const getInvoices = useGetInvoices(activeTab)
return (
<div className='mt-4'>
@@ -22,87 +28,97 @@ const ReceiptsList: FC = () => {
active={activeTab}
items={[
{
icon: <WalletRemove color={activeTab === 'unpaid' ? 'black' : '#8C90A3'} size={22} />,
icon: <WalletRemove color={activeTab === 'PENDING' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.dont_pay'),
value: 'unpaid'
value: 'PENDING'
},
{
icon: <WalletSearch color={activeTab === 'not_confimed' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.dont_confrim'),
value: 'not_confimed'
},
{
icon: <WalletCheck color={activeTab === 'paid' ? 'black' : '#8C90A3'} size={22} />,
icon: <WalletCheck color={activeTab === 'PAID' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.paid'),
value: 'paid'
value: 'PAID'
},
{
icon: <CloseCircle color={activeTab === 'canceled' ? 'black' : '#8C90A3'} size={22} />,
icon: <CloseCircle color={activeTab === 'CANCELED' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.canceled'),
value: 'canceled'
value: 'CANCELED'
},
{
icon: <MoneyChange color={activeTab === 'returned' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.returned'),
value: 'returned'
},
{
icon: <Calendar color={activeTab === 'time' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.its_time'),
value: 'time'
},
{
icon: <FolderOpen color={activeTab === 'archive' ? 'black' : '#8C90A3'} size={22} />,
icon: <FolderOpen color={activeTab === 'EXPIRED' ? 'black' : '#8C90A3'} size={22} />,
label: t('receip.archive'),
value: 'archive'
value: 'EXPIRED'
},
]}
onChange={setActiveTab}
onChange={(value) => setActiveTab(value as "PENDING" | "PAID" | "CANCELED" | "EXPIRED")}
/>
</div>
{
getInvoices.isPending ?
<div className='mt-5'>
<PageLoading />
</div>
:
<div className='relative overflow-x-auto rounded-3xl mt-9 w-full'>
<table className='w-full text-sm '>
<thead className='thead'>
<tr>
<Td text={t('ticket.number')} />
<Td text={t('ticket.title')} />
<Td text={t('ticket.team')} />
<Td text={t('ticket.date')} />
<Td text={t('ticket.status')} />
<Td text={t('ticket.priority')} />
<Td text={t('ticket.detail')} />
{/* <Td text={t('receip.customer')} /> */}
<Td text={t('receip.date_receipt')} />
<Td text={t('receip.last_date_receipt')} />
<Td text={t('receip.total')} />
<Td text={t('receip.service')} />
<Td text={t('receip.status')} />
<Td text={t('receip.status_paid')} />
<Td text={''} />
</tr>
</thead>
<tbody>
{
getInvoices.data?.data?.invoices?.map((item: ReceiptItemType, index: number) => {
return (
<tr className='tr'>
<Td text={t('ticket.number')} />
<Td text={t('ticket.title')} />
<Td text={t('ticket.team')} />
<Td text={t('ticket.date')} />
<Td text={t('ticket.status')} />
<Td text={t('ticket.priority')} />
<Td text={t('ticket.detail')} />
<Td text={String(index + 1)} />
{/* <Td text={item.user.firstName + ' ' + item.user.lastName} /> */}
<Td text={''}>
<Link to={Pages.receipts.detail + '1'}>
<div className='dltr text-right'>
{moment(item.createdAt).format('jYYYY-jMM-jDD HH:mm')}
</div>
</Td>
<Td text={''}>
<div className='dltr text-right'>
{moment(item.dueDate).format('jYYYY-jMM-jDD HH:mm')}
</div>
</Td>
<Td text={NumberFormat(item.totalPrice)} />
<Td text={''}>
<div className='flex flex-wrap gap-1.5'>
{
item.items.map((item => {
return (
<div className='bg-primary p-2 rounded-full text-white flex gap-1'><span>{item.name}</span> <span>({item.count})</span></div>
)
}))
}
</div>
</Td>
<Td text={t(`receip.${item.status}`)} />
<Td text={item.paidAt ? t('receip.paid') : t('receip.not_paid')} />
<Td text={''}>
<Link to={Pages.receipts.detail + item.id}>
<Eye size={20} color='black' />
</Link>
</Td>
</tr>
<tr className='tr'>
<Td text={t('ticket.number')} />
<Td text={t('ticket.title')} />
<Td text={t('ticket.team')} />
<Td text={t('ticket.date')} />
<Td text={t('ticket.status')} />
<Td text={t('ticket.priority')} />
<Td text={t('ticket.detail')} />
<Td text={''} />
</tr>
)
})
}
</tbody>
</table>
</div>
}
</div>
)
}
@@ -0,0 +1,17 @@
import { useQuery } from "@tanstack/react-query";
import * as api from "../service/ReceiptService";
export const useGetInvoices = (status: string) => {
return useQuery({
queryKey: ["invoices", status],
queryFn: () => api.getInvoice(status),
});
};
export const useGetInvoiceDetail = (id: string) => {
return useQuery({
queryKey: ["invoice", id],
queryFn: () => api.getInvoiceDetail(id),
enabled: !!id,
});
};
@@ -0,0 +1,11 @@
import axios from "../../../config/axios";
export const getInvoice = async (status: string) => {
const { data } = await axios.get(`/invoices/user?status=${status}`);
return data;
};
export const getInvoiceDetail = async (id: string) => {
const { data } = await axios.get(`/invoices/${id}`);
return data;
};
+19
View File
@@ -0,0 +1,19 @@
export type ReceiptItemType = {
id: string;
createdAt: string;
updatedAt: string;
name: string;
count: string | number;
unitPrice: string | number;
discount: string | number;
totalPrice: number;
subscriptionPlan?: string | null;
items: ReceiptItemType[];
user: {
firstName: string;
lastName: string;
};
dueDate: string;
status: "PENDING" | "PAID" | "CANCELED" | "EXPIRED";
paidAt: string;
};