invoice
This commit is contained in:
@@ -8,8 +8,6 @@ import { CreateReceiptType, ReceiptCreateItemsType } from './types/ReceiptTypes'
|
|||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { useGetCustomers } from '../customer/hooks/useCustomerData'
|
|
||||||
import { CustomerItemType } from '../customer/types/CustomerTypes'
|
|
||||||
import PageLoading from '../../components/PageLoading'
|
import PageLoading from '../../components/PageLoading'
|
||||||
import { useCreateInvoice } from './hooks/useReceiptData'
|
import { useCreateInvoice } from './hooks/useReceiptData'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
@@ -17,16 +15,19 @@ import { Pages } from '../../config/Pages'
|
|||||||
import { ErrorType } from '../../helpers/types'
|
import { ErrorType } from '../../helpers/types'
|
||||||
import { RecurringPeriodEnum } from './enum/ReceipEnum'
|
import { RecurringPeriodEnum } from './enum/ReceipEnum'
|
||||||
import SwitchComponent from '../../components/Switch'
|
import SwitchComponent from '../../components/Switch'
|
||||||
|
import { useGetCompanies } from '../company/hooks/useCompanyData'
|
||||||
|
import { CompanyItemType } from '../company/types/CompanyTypes'
|
||||||
|
import moment from 'moment-jalaali'
|
||||||
const CreateReceipt: FC = () => {
|
const CreateReceipt: FC = () => {
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
const [items, setItems] = useState<ReceiptCreateItemsType[]>([])
|
const [items, setItems] = useState<ReceiptCreateItemsType[]>([])
|
||||||
const [customer, setCustomer] = useState<CustomerItemType>()
|
const [customer, setCustomer] = useState<CompanyItemType>()
|
||||||
const [isRecurring, setIsRecurring] = useState<boolean>(false)
|
const [isRecurring, setIsRecurring] = useState<boolean>(false)
|
||||||
const [type, setType] = useState<RecurringPeriodEnum>(RecurringPeriodEnum.WEEKLY)
|
const [type, setType] = useState<RecurringPeriodEnum>(RecurringPeriodEnum.WEEKLY)
|
||||||
const [maxRecurringCycles, setMaxRecurringCycles] = useState<number>(0)
|
const [maxRecurringCycles, setMaxRecurringCycles] = useState<number>(0)
|
||||||
const getCustomers = useGetCustomers(1, true)
|
const getCustomers = useGetCompanies(1)
|
||||||
const createInvoice = useCreateInvoice()
|
const createInvoice = useCreateInvoice()
|
||||||
|
|
||||||
const formik = useFormik<ReceiptCreateItemsType>({
|
const formik = useFormik<ReceiptCreateItemsType>({
|
||||||
@@ -54,14 +55,14 @@ const CreateReceipt: FC = () => {
|
|||||||
|
|
||||||
const handleChangeCustomer = (e: ChangeEvent<HTMLSelectElement>) => {
|
const handleChangeCustomer = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
const value = e.target.value
|
const value = e.target.value
|
||||||
const customer = getCustomers.data?.data?.customers?.find((item: CustomerItemType) => item.id === value)
|
const customer = getCustomers.data?.data?.companies?.find((item: CompanyItemType) => item.id === value)
|
||||||
setCustomer(customer)
|
setCustomer(customer)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
if (customer) {
|
if (customer) {
|
||||||
const params: CreateReceiptType = {
|
const params: CreateReceiptType = {
|
||||||
userId: customer?.id,
|
companyId: customer?.id,
|
||||||
items: items,
|
items: items,
|
||||||
isRecurring: isRecurring,
|
isRecurring: isRecurring,
|
||||||
recurringPeriod: isRecurring ? +type : undefined,
|
recurringPeriod: isRecurring ? +type : undefined,
|
||||||
@@ -114,18 +115,18 @@ const CreateReceipt: FC = () => {
|
|||||||
|
|
||||||
<div className='flex gap-6 xl:mt-8 mt-4'>
|
<div className='flex gap-6 xl:mt-8 mt-4'>
|
||||||
<div className='flex-1 bg-white py-8 xl:px-10 px-4 rounded-3xl'>
|
<div className='flex-1 bg-white py-8 xl:px-10 px-4 rounded-3xl'>
|
||||||
<div>
|
{/* <div>
|
||||||
{t('receip.customer_information')}
|
{t('receip.customer_information')}
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className='mt-8'>
|
<div className='mt-8'>
|
||||||
<div className='w-full xl:w-1/2'>
|
<div className='w-full xl:w-1/2'>
|
||||||
<Select
|
<Select
|
||||||
label={t('receip.customer')}
|
label={t('company.select_company')}
|
||||||
placeholder={t('select')}
|
placeholder={t('select')}
|
||||||
items={getCustomers.data?.data?.customers?.map((item: CustomerItemType) => {
|
items={getCustomers.data?.data?.companies?.map((item: CompanyItemType) => {
|
||||||
return {
|
return {
|
||||||
label: item.firstName + ' ' + item.lastName,
|
label: item.name,
|
||||||
value: item.id
|
value: item.id
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
@@ -139,37 +140,25 @@ const CreateReceipt: FC = () => {
|
|||||||
<div className='mt-10 bg-[#F6F7FB] p-8 rounded-3xl text-sm'>
|
<div className='mt-10 bg-[#F6F7FB] p-8 rounded-3xl text-sm'>
|
||||||
<div className='flex justify-between items-center border-b border-border border-dashed pb-7'>
|
<div className='flex justify-between items-center border-b border-border border-dashed pb-7'>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<div className='text-description'>{t('receip.type_person')}</div>
|
<div className='text-description'>{t('company.company_name')}</div>
|
||||||
<div>{customer.legalUser ? 'حقوقی' : 'حقیقی'}</div>
|
<div>{customer.name}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<div className='text-description'>{t('receip.representativeـname')}</div>
|
<div className='text-description'>{t('company.ceo_name')}</div>
|
||||||
<div>{customer.firstName + ' ' + customer.lastName}</div>
|
<div>{customer.user?.firstName + ' ' + customer.user?.lastName}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<div className='text-description'>{t('receip.company_name')}</div>
|
<div className='text-description'>{t('company.register_date')}</div>
|
||||||
<div>{customer?.legalUser?.registrationName}</div>
|
<div>{moment(customer.createdAt).format('jYYYY/jMM/jDD')}</div>
|
||||||
</div>
|
|
||||||
<div className='flex items-center gap-2'>
|
|
||||||
<div className='text-description'>{t('receip.registration_number')}</div>
|
|
||||||
<div>{customer?.legalUser?.registrationCode}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex justify-between items-center mt-7'>
|
<div className='flex justify-between items-center mt-7'>
|
||||||
<div className='flex items-center gap-2 flex-1'>
|
<div className='flex items-center gap-2 flex-1'>
|
||||||
<div className='text-description'>{t('receip.tel_company')}</div>
|
<div className='text-description'>{t('company.industry')}</div>
|
||||||
<div>{customer?.realUser?.phone || customer?.legalUser?.phone}</div>
|
<div>{customer.industry?.title}</div>
|
||||||
</div>
|
|
||||||
<div className='flex items-center gap-2 flex-1'>
|
|
||||||
<div className='text-description'>{t('receip.national_code')}</div>
|
|
||||||
<div>{customer.nationalCode}</div>
|
|
||||||
</div>
|
|
||||||
<div className='flex items-center gap-2 flex-1'>
|
|
||||||
<div className='text-description'>{t('receip.postal_code')}</div>
|
|
||||||
<div>{customer?.realUser?.address?.postalCode || customer?.legalUser?.address?.postalCode}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='flex justify-between items-center mt-7'>
|
{/* <div className='flex justify-between items-center mt-7'>
|
||||||
<div className='flex items-center gap-2 flex-1'>
|
<div className='flex items-center gap-2 flex-1'>
|
||||||
<div className='text-description'>{t('receip.state')}</div>
|
<div className='text-description'>{t('receip.state')}</div>
|
||||||
<div>{customer?.realUser?.address?.city?.province?.name || customer?.legalUser?.address?.city?.province?.name}</div>
|
<div>{customer?.realUser?.address?.city?.province?.name || customer?.legalUser?.address?.city?.province?.name}</div>
|
||||||
@@ -182,7 +171,7 @@ const CreateReceipt: FC = () => {
|
|||||||
<div className='text-description'>{t('receip.address')}</div>
|
<div className='text-description'>{t('receip.address')}</div>
|
||||||
<div>{customer?.realUser?.address?.fullAddress || customer?.legalUser?.address?.fullAddress}</div>
|
<div>{customer?.realUser?.address?.fullAddress || customer?.legalUser?.address?.fullAddress}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-15
@@ -1,19 +1,20 @@
|
|||||||
import { FC, useEffect, useState } from 'react'
|
import { FC, useEffect, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Tabs from '../../components/Tabs'
|
import Tabs from '../../components/Tabs'
|
||||||
import { Edit, FolderOpen, WalletCheck, WalletMinus, WalletRemove, WalletSearch } from 'iconsax-react'
|
import { FolderOpen, WalletCheck, WalletRemove, WalletSearch, WalletMinus } from 'iconsax-react'
|
||||||
import Td from '../../components/Td'
|
import Td from '../../components/Td'
|
||||||
import { useGetInvoices } from './hooks/useReceiptData'
|
import { useGetInvoices } from './hooks/useReceiptData'
|
||||||
import PageLoading from '../../components/PageLoading'
|
import PageLoading from '../../components/PageLoading'
|
||||||
import { InvoiceStatus, InvoiceUserItemType, ReceiptItemType } from './types/ReceiptTypes'
|
import { InvoiceStatus, ReceiptItemType } from './types/ReceiptTypes'
|
||||||
import { NumberFormat } from '../../config/func'
|
import { NumberFormat } from '../../config/func'
|
||||||
import Select from '../../components/Select'
|
import Select from '../../components/Select'
|
||||||
import Input from '../../components/Input'
|
import Input from '../../components/Input'
|
||||||
import DatePickerComponent from '../../components/DatePicker'
|
import DatePickerComponent from '../../components/DatePicker'
|
||||||
import { Link, useSearchParams } from 'react-router-dom'
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import moment from 'moment-jalaali'
|
import moment from 'moment-jalaali'
|
||||||
|
import { CompanyItemType } from '../company/types/CompanyTypes'
|
||||||
import Pagination from '../../components/Pagination'
|
import Pagination from '../../components/Pagination'
|
||||||
import { Pages } from '../../config/Pages'
|
|
||||||
|
|
||||||
const ReceiptsList: FC = () => {
|
const ReceiptsList: FC = () => {
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ const ReceiptsList: FC = () => {
|
|||||||
const [search, setSearch] = useState<string>('')
|
const [search, setSearch] = useState<string>('')
|
||||||
const [date, setDate] = useState<string>('')
|
const [date, setDate] = useState<string>('')
|
||||||
const [endDate, setEndDate] = useState<string>('')
|
const [endDate, setEndDate] = useState<string>('')
|
||||||
const getInvoices = useGetInvoices(activeTab, customerId, search, date, endDate, page)
|
const getInvoices = useGetInvoices(activeTab, customerId, search, date, endDate)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const urlCustomerId = searchParams.get('user')
|
const urlCustomerId = searchParams.get('user')
|
||||||
@@ -45,11 +46,11 @@ const ReceiptsList: FC = () => {
|
|||||||
<div className='flex justify-between items-center mt-12'>
|
<div className='flex justify-between items-center mt-12'>
|
||||||
<div className='flex gap-4'>
|
<div className='flex gap-4'>
|
||||||
<Select
|
<Select
|
||||||
label={t('receip.customer')}
|
label={t('company.company')}
|
||||||
placeholder={t('select')}
|
placeholder={t('select')}
|
||||||
items={getInvoices.data?.data?.users?.map((item: InvoiceUserItemType) => {
|
items={getInvoices.data?.data?.companies?.map((item: CompanyItemType) => {
|
||||||
return {
|
return {
|
||||||
label: item.firstname + ' ' + item.lastname,
|
label: item.name,
|
||||||
value: item.id
|
value: item.id
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
@@ -146,7 +147,7 @@ const ReceiptsList: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<tr className='tr'>
|
<tr className='tr'>
|
||||||
<Td text={String(index + 1)} />
|
<Td text={String(index + 1)} />
|
||||||
<Td text={item.user.firstName + ' ' + item.user.lastName} />
|
<Td text={item.company.name} />
|
||||||
<Td text={moment(item.createdAt).format('jYYYY/jMM/jDD')} />
|
<Td text={moment(item.createdAt).format('jYYYY/jMM/jDD')} />
|
||||||
<Td text={moment(item.dueDate).format('jYYYY/jMM/jDD')} />
|
<Td text={moment(item.dueDate).format('jYYYY/jMM/jDD')} />
|
||||||
<Td text={NumberFormat(item.totalPrice)} />
|
<Td text={NumberFormat(item.totalPrice)} />
|
||||||
@@ -155,16 +156,12 @@ const ReceiptsList: FC = () => {
|
|||||||
<Td text={item.status === 'APPROVED' || item.status === 'PAID' ? t('receip.approved') : t('receip.pending')} />
|
<Td text={item.status === 'APPROVED' || item.status === 'PAID' ? t('receip.approved') : t('receip.pending')} />
|
||||||
<Td text={t(`receip.${item.status}`)} />
|
<Td text={t(`receip.${item.status}`)} />
|
||||||
<Td text=''>
|
<Td text=''>
|
||||||
{item.isRecurring ? t(`receip.${item.recurringPeriod}`) : '_'}
|
{item.isRecurring ? t('receip.recurringPeriod') : '_'}
|
||||||
</Td>
|
</Td>
|
||||||
<Td text=''>
|
<Td text=''>
|
||||||
{item.maxRecurringCycles}
|
{item.maxRecurringCycles}
|
||||||
</Td>
|
</Td>
|
||||||
<Td text={''}>
|
<Td text={''} />
|
||||||
<Link to={Pages.receipts.detail + item.id}>
|
|
||||||
<Edit size={20} color='#888' />
|
|
||||||
</Link>
|
|
||||||
</Td>
|
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ export const useGetInvoices = (
|
|||||||
customerId: string,
|
customerId: string,
|
||||||
search: string,
|
search: string,
|
||||||
date: string,
|
date: string,
|
||||||
endDate: string,
|
endDate: string
|
||||||
page: number
|
|
||||||
) => {
|
) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ["invoices", status, customerId, search, date, endDate, page],
|
queryKey: ["invoices", status, customerId, search, date, endDate],
|
||||||
queryFn: () =>
|
queryFn: () => api.getInvoces(status, customerId, search, date, endDate),
|
||||||
api.getInvoces(status, customerId, search, date, endDate, page),
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -22,17 +20,3 @@ export const useCreateInvoice = () => {
|
|||||||
mutationFn: (variables: CreateReceiptType) => api.createInvoice(variables),
|
mutationFn: (variables: CreateReceiptType) => api.createInvoice(variables),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetInvoiceById = (id: string) => {
|
|
||||||
return useQuery({
|
|
||||||
queryKey: ["invoice", id],
|
|
||||||
queryFn: () => api.getInvoiceById(id),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useUpdateInvoice = () => {
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({ id, params }: { id: string; params: CreateReceiptType }) =>
|
|
||||||
api.updateInvoice(id, params),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -6,16 +6,14 @@ export const getInvoces = async (
|
|||||||
customerId: string,
|
customerId: string,
|
||||||
search: string,
|
search: string,
|
||||||
date: string,
|
date: string,
|
||||||
endDate: string,
|
endDate: string
|
||||||
page: number
|
|
||||||
) => {
|
) => {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (status) params.append("status", status);
|
if (status) params.append("status", status);
|
||||||
if (customerId) params.append("userId", customerId);
|
if (customerId) params.append("companyId", customerId);
|
||||||
if (search) params.append("q", search);
|
if (search) params.append("q", search);
|
||||||
if (date) params.append("since", date);
|
if (date) params.append("since", date);
|
||||||
if (endDate) params.append("to", endDate);
|
if (endDate) params.append("to", endDate);
|
||||||
if (page) params.append("page", page.toString());
|
|
||||||
const query = params.toString();
|
const query = params.toString();
|
||||||
const { data } = await axios.get(`/invoices?${query}`);
|
const { data } = await axios.get(`/invoices?${query}`);
|
||||||
return data;
|
return data;
|
||||||
@@ -25,13 +23,3 @@ export const createInvoice = async (params: CreateReceiptType) => {
|
|||||||
const { data } = await axios.post(`/invoices`, params);
|
const { data } = await axios.post(`/invoices`, params);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getInvoiceById = async (id: string) => {
|
|
||||||
const { data } = await axios.get(`/invoices/${id}`);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const updateInvoice = async (id: string, params: CreateReceiptType) => {
|
|
||||||
const { data } = await axios.patch(`/invoices/${id}`, params);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export type CreateReceiptType = {
|
export type CreateReceiptType = {
|
||||||
userId: string;
|
companyId: string;
|
||||||
items: ReceiptCreateItemsType[];
|
items: ReceiptCreateItemsType[];
|
||||||
isRecurring: boolean;
|
isRecurring: boolean;
|
||||||
recurringPeriod: number | undefined;
|
recurringPeriod: number | undefined;
|
||||||
@@ -24,9 +24,9 @@ export type ReceiptItemType = {
|
|||||||
totalPrice: number;
|
totalPrice: number;
|
||||||
subscriptionPlan?: string | null;
|
subscriptionPlan?: string | null;
|
||||||
items: ReceiptItemType[];
|
items: ReceiptItemType[];
|
||||||
user: {
|
lateFee: number;
|
||||||
firstName: string;
|
company: {
|
||||||
lastName: string;
|
name: string;
|
||||||
};
|
};
|
||||||
dueDate: string;
|
dueDate: string;
|
||||||
status: "PENDING" | "PAID" | "CANCELLED" | "EXPIRED" | "APPROVED";
|
status: "PENDING" | "PAID" | "CANCELLED" | "EXPIRED" | "APPROVED";
|
||||||
@@ -34,7 +34,6 @@ export type ReceiptItemType = {
|
|||||||
isRecurring: boolean;
|
isRecurring: boolean;
|
||||||
recurringPeriod?: number;
|
recurringPeriod?: number;
|
||||||
maxRecurringCycles?: number;
|
maxRecurringCycles?: number;
|
||||||
lateFee: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InvoiceUserItemType = {
|
export type InvoiceUserItemType = {
|
||||||
|
|||||||
Reference in New Issue
Block a user