Create order

This commit is contained in:
hamid zarghami
2026-02-22 09:50:36 +03:30
parent 502e8c538f
commit d357a5000b
7 changed files with 164 additions and 145 deletions
+1 -1
View File
@@ -91,5 +91,5 @@ export const Paths = {
update: '/print/update/', update: '/print/update/',
form: '/print/form/', form: '/print/form/',
}, },
convertToOrder: '/convert-to-order/', convertToOrder: '/convert-to-order',
}; };
@@ -123,7 +123,7 @@ const InvoiceItemRow: FC<Props> = ({
</button> </button>
)} )}
{item.id && ( {item.id && (
<Link to={Paths.convertToOrder + '/' + item.id}> <Link to={Paths.convertToOrder + '?invoiceItemId=' + item.id}>
<button <button
type="button" type="button"
onClick={onConvertToOrder} onClick={onConvertToOrder}
+147 -140
View File
@@ -5,165 +5,172 @@ import Input from '@/components/Input'
import Select from '@/components/Select' import Select from '@/components/Select'
import UploadBox from '@/components/UploadBox' import UploadBox from '@/components/UploadBox'
import Button from '@/components/Button' import Button from '@/components/Button'
import { useGetUsers } from '../user/hooks/useUserData'
import { useGetProducts } from './hooks/useOrderData'
import { useMultiUpload } from '@/pages/uploader/hooks/useUploader' import { useMultiUpload } from '@/pages/uploader/hooks/useUploader'
import { OrderStatusEnum } from './enum/OrderEnum'
import type { ConvertToOrderItemType } from './types/Types' import type { ConvertToOrderItemType } from './types/Types'
import { useConverToOrder, useGetProducts } from './hooks/useOrderData'
import { useGetCategory } from '@/pages/product/hooks/useProductData'
import { useGetUsers } from '@/pages/user/hooks/useUserData'
import { useSearchParams } from 'react-router-dom'
const initialValues: ConvertToOrderItemType = { const getInitialValues = (invoiceItemId: string | null): ConvertToOrderItemType => ({
userId: '', invoiceItemId: invoiceItemId ?? '',
invoiceItemId: '', productId: '',
typeId: '', userId: '',
estimatedDays: 0, typeId: '',
productId: '', estimatedDays: 0,
title: '', title: '',
attachments: [], attachments: [],
}
const validationSchema = Yup.object({
userId: Yup.string().required('انتخاب کاربر اجباری است.'),
invoiceItemId: Yup.string(),
typeId: Yup.string().required('انتخاب نوع اجباری است.'),
estimatedDays: Yup.number().required('تخمین روز اجباری است.').min(0, 'باید عدد مثبت باشد'),
productId: Yup.string().required('انتخاب محصول اجباری است.'),
title: Yup.string().required('عنوان اجباری است.'),
}) })
const getValidationSchema = (invoiceItemId: string | null) =>
Yup.object({
invoiceItemId: Yup.string(),
productId: invoiceItemId ? Yup.string() : Yup.string().required('انتخاب محصول اجباری است.'),
userId: invoiceItemId ? Yup.string() : Yup.string().required('انتخاب کاربر اجباری است.'),
typeId: Yup.string().required('انتخاب نوع اجباری است.'),
estimatedDays: Yup.number().required('تخمین روز اجباری است.').min(0, 'باید عدد مثبت باشد'),
title: Yup.string().required('عنوان اجباری است.'),
})
const ConvertToOrders: FC = () => { const ConvertToOrders: FC = () => {
const { data: users } = useGetUsers()
const { data: products } = useGetProducts()
const multiUpload = useMultiUpload()
const [attachmentFiles, setAttachmentFiles] = useState<File[]>([])
const formik = useFormik<ConvertToOrderItemType>({ const [searchParams] = useSearchParams()
initialValues, const invoiceItemId = searchParams.get('invoiceItemId')
validationSchema, const multiUpload = useMultiUpload()
onSubmit: async (values) => { const [attachmentFiles, setAttachmentFiles] = useState<File[]>([])
const attachments: string[] = [...values.attachments] const { data: categories } = useGetCategory()
const { data: users } = useGetUsers()
const { data: products } = useGetProducts()
if (attachmentFiles.length > 0) { const { mutate: converToOrder, isPending } = useConverToOrder()
const result = await multiUpload.mutateAsync(attachmentFiles)
result?.data?.forEach((item) => {
attachments.push(item.url)
})
}
const payload: ConvertToOrderItemType = { const formik = useFormik<ConvertToOrderItemType>({
...values, initialValues: getInitialValues(invoiceItemId),
estimatedDays: Number(values.estimatedDays), validationSchema: getValidationSchema(invoiceItemId),
attachments, enableReinitialize: true,
} onSubmit: async (values) => {
const attachments: string[] = [...values.attachments]
console.log('Submit:', payload) if (attachmentFiles.length > 0) {
// TODO: call API const result = await multiUpload.mutateAsync(attachmentFiles)
}, result?.data?.forEach((item) => {
}) attachments.push(item.url)
})
}
return ( const payload: ConvertToOrderItemType = {
<div className="mt-5"> ...values,
<h1 className="text-lg font-light">تبدیل به سفارش</h1> invoiceItemId: invoiceItemId ?? values.invoiceItemId ?? '',
productId: invoiceItemId ? undefined : values.productId,
userId: invoiceItemId ? undefined : values.userId,
estimatedDays: Number(values.estimatedDays),
attachments,
}
<div className="bg-white rounded-3xl p-6 mt-8"> await converToOrder(payload)
<form },
onSubmit={formik.handleSubmit} })
className="space-y-6"
>
<div className="rowTwoInput">
<Select
items={
users?.data?.map((item) => ({
label: item.firstName && item.lastName ? `${item.firstName} ${item.lastName}` : item.phone,
value: item.id,
})) ?? []
}
label="کاربر"
placeholder="انتخاب کاربر"
{...formik.getFieldProps('userId')}
error_text={
formik.touched.userId && formik.errors.userId ? formik.errors.userId : ''
}
/>
<Select return (
items={ <div className="mt-5">
products?.data?.map((item) => ({ <h1 className="text-lg font-light">تبدیل به سفارش</h1>
label: item.title,
value: item.id,
})) ?? []
}
label="محصول"
placeholder="انتخاب محصول"
{...formik.getFieldProps('productId')}
error_text={
formik.touched.productId && formik.errors.productId ? formik.errors.productId : ''
}
/>
</div>
<div className="rowTwoInput"> <div className="bg-white rounded-3xl p-6 mt-8">
<Input <form
label="شناسه آیتم فاکتور" onSubmit={formik.handleSubmit}
{...formik.getFieldProps('invoiceItemId')} className="space-y-6"
error_text={ >
formik.touched.invoiceItemId && formik.errors.invoiceItemId {!invoiceItemId && (
? formik.errors.invoiceItemId <div className="rowTwoInput">
: '' <Select
} items={
/> users?.data?.map((item) => ({
label: item.firstName ? `${item.firstName} ${item.lastName}` : item.phone,
value: item.id,
})) ?? []
}
label="کاربر"
placeholder="انتخاب کاربر"
{...formik.getFieldProps('userId')}
error_text={
formik.touched.userId && formik.errors.userId ? formik.errors.userId : ''
}
/>
<Select
items={
products?.data?.map((item) => ({
label: item.title,
value: String(item.id),
})) ?? []
}
label="محصول"
placeholder="انتخاب محصول"
{...formik.getFieldProps('productId')}
error_text={
formik.touched.productId && formik.errors.productId
? formik.errors.productId
: ''
}
/>
</div>
)}
<Select <div className="rowTwoInput">
items={Object.values(OrderStatusEnum).map((item) => ({
label: item,
value: item,
}))}
label="نوع"
placeholder="انتخاب نوع"
{...formik.getFieldProps('typeId')}
error_text={
formik.touched.typeId && formik.errors.typeId ? formik.errors.typeId : ''
}
/>
</div>
<div className="rowTwoInput"> <Select
<Input items={
label="تخمین روز" categories?.data?.map((item) => ({
type="number" label: item.title,
{...formik.getFieldProps('estimatedDays')} value: String(item.id),
error_text={ })) ?? []
formik.touched.estimatedDays && formik.errors.estimatedDays }
? formik.errors.estimatedDays label="نوع"
: '' placeholder="انتخاب نوع"
} {...formik.getFieldProps('typeId')}
/> error_text={
formik.touched.typeId && formik.errors.typeId ? formik.errors.typeId : ''
}
/>
</div>
<Input <div className="rowTwoInput">
label="عنوان" <Input
{...formik.getFieldProps('title')} label="تخمین روز"
error_text={ type="number"
formik.touched.title && formik.errors.title ? formik.errors.title : '' {...formik.getFieldProps('estimatedDays')}
} error_text={
/> formik.touched.estimatedDays && formik.errors.estimatedDays
</div> ? formik.errors.estimatedDays
: ''
}
/>
<div> <Input
<UploadBox label="عنوان"
label="پیوست‌ها" {...formik.getFieldProps('title')}
isMultiple error_text={
onChange={setAttachmentFiles} formik.touched.title && formik.errors.title ? formik.errors.title : ''
/> }
</div> />
</div>
<div className="flex justify-end"> <div>
<Button type="submit" isLoading={multiUpload.isPending}> <UploadBox
ثبت label="پیوست‌ها"
</Button> isMultiple
</div> onChange={setAttachmentFiles}
</form> />
</div> </div>
</div>
) <div className="flex justify-end">
<Button type="submit" isLoading={multiUpload.isPending || isPending}>
ثبت
</Button>
</div>
</form>
</div>
</div>
)
} }
export default ConvertToOrders export default ConvertToOrders
+6
View File
@@ -57,6 +57,12 @@ export const useCreateOrder = () => {
}); });
}; };
export const useConverToOrder = () => {
return useMutation({
mutationFn: api.converToOrder,
});
};
export const useUpdateOrder = () => { export const useUpdateOrder = () => {
return useMutation({ return useMutation({
mutationFn: ({ mutationFn: ({
+6
View File
@@ -1,6 +1,7 @@
import axios from "@/config/axios"; import axios from "@/config/axios";
import type { import type {
AddTicketType, AddTicketType,
ConvertToOrderItemType,
CreateFinalOrderType, CreateFinalOrderType,
OrderDetailResponseType, OrderDetailResponseType,
OrderItemResponseType, OrderItemResponseType,
@@ -82,3 +83,8 @@ export const getOrderItem = async (itemId?: number) => {
); );
return data; return data;
}; };
export const converToOrder = async (params: ConvertToOrderItemType) => {
const { data } = await axios.post(`/admin/orders`, params);
return data;
};
+2 -2
View File
@@ -178,11 +178,11 @@ export interface CreateFinalOrderType extends CreateBaseOrderType {
} }
export type ConvertToOrderItemType = { export type ConvertToOrderItemType = {
userId: string;
invoiceItemId: string; invoiceItemId: string;
productId?: string;
userId?: string;
typeId: string; typeId: string;
estimatedDays: number; estimatedDays: number;
productId: string;
title: string; title: string;
attachments: string[]; attachments: string[];
}; };
+1 -1
View File
@@ -88,7 +88,7 @@ const MainRouter: FC = () => {
<Route path={Paths.order.details + ":id"} element={<OrderDetail />} /> <Route path={Paths.order.details + ":id"} element={<OrderDetail />} />
<Route path={Paths.order.create} element={<NewOrder />} /> <Route path={Paths.order.create} element={<NewOrder />} />
<Route path={Paths.order.edit + ":id"} element={<EditOrder />} /> <Route path={Paths.order.edit + ":id"} element={<EditOrder />} />
<Route path={Paths.convertToOrder + ":id"} element={<ConvertToOrders />} /> <Route path={Paths.convertToOrder} element={<ConvertToOrders />} />
<Route path={Paths.print.list} element={<SectionList />} /> <Route path={Paths.print.list} element={<SectionList />} />
<Route path={Paths.print.create} element={<CreateSection />} /> <Route path={Paths.print.create} element={<CreateSection />} />