create print form
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
import { type FC } from 'react'
|
||||||
|
import { useNavigate, useParams } from 'react-router-dom'
|
||||||
|
import { useCreatePrintForm, useGetSections } from './hooks/usePrintData'
|
||||||
|
import { useFormik } from 'formik'
|
||||||
|
import type { CreatePrintFormType } from './types/Types'
|
||||||
|
import ManageForms from './components/ManageForms'
|
||||||
|
import { toast } from '@/shared/toast'
|
||||||
|
import { extractErrorMessage } from '@/config/func'
|
||||||
|
import Button from '@/components/Button'
|
||||||
|
import { TickSquare } from 'iconsax-react'
|
||||||
|
|
||||||
|
const PrintForm: FC = () => {
|
||||||
|
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const { itemId, orderId } = useParams()
|
||||||
|
const { isPending, mutate } = useCreatePrintForm()
|
||||||
|
const { data } = useGetSections()
|
||||||
|
|
||||||
|
const formik = useFormik<CreatePrintFormType>({
|
||||||
|
initialValues: {
|
||||||
|
printAttributes: []
|
||||||
|
},
|
||||||
|
onSubmit: (values) => {
|
||||||
|
mutate({ itemId: +itemId!, orderId: orderId!, params: values }, {
|
||||||
|
onSuccess: () => {
|
||||||
|
toast('با موفقیت ذخیره شد', 'success')
|
||||||
|
navigate(-1)
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
toast(extractErrorMessage(error), 'error')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-5'>
|
||||||
|
<div className='flex justify-between items-center'>
|
||||||
|
<h1 className='text-lg font-light'>فرم پرینت</h1>
|
||||||
|
<Button
|
||||||
|
className='w-fit px-6'
|
||||||
|
isLoading={isPending}
|
||||||
|
onClick={() => formik.handleSubmit()}
|
||||||
|
>
|
||||||
|
<div className='flex gap-1.5'>
|
||||||
|
<TickSquare size={18} color='black' />
|
||||||
|
<div className='text-[13px] font-light'>ذخیره</div>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col gap-5 mt-6'>
|
||||||
|
{
|
||||||
|
data?.data?.map((item) => {
|
||||||
|
return (
|
||||||
|
<div key={item.id} className='bg-white p-6 rounded-3xl'>
|
||||||
|
<div className='font-bold'>{item.title}</div>
|
||||||
|
<ManageForms formik={formik} attributes={item.fields} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PrintForm
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
import { type FC } from 'react'
|
||||||
|
import { clx } from '@/helpers/utils'
|
||||||
|
import Select from '@/components/Select'
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox'
|
||||||
|
import RadioGroup from '@/components/RadioGroup'
|
||||||
|
import DatePickerComponent from '@/components/DatePicker'
|
||||||
|
import Input from '@/components/Input'
|
||||||
|
import Textarea from '@/components/Textarea'
|
||||||
|
import type { FormikProps } from 'formik'
|
||||||
|
import type { CreatePrintFormType } from '../types/Types'
|
||||||
|
import type { EntityType } from '@/pages/formBuilder/types/Types'
|
||||||
|
import { FieldTypeEnum } from '@/pages/formBuilder/enum/Enum'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
attributes?: EntityType[],
|
||||||
|
formik: FormikProps<CreatePrintFormType>
|
||||||
|
}
|
||||||
|
|
||||||
|
const ManageForms: FC<Props> = (props) => {
|
||||||
|
|
||||||
|
const { attributes, formik } = props
|
||||||
|
|
||||||
|
const handleChange = (attributeId: number, value: string) => {
|
||||||
|
const attribute = formik.values.printAttributes
|
||||||
|
const index: number = attribute.findIndex(o => o.fieldId === attributeId)
|
||||||
|
if (index > -1) {
|
||||||
|
attribute[index].value = value
|
||||||
|
} else {
|
||||||
|
attribute.push({ fieldId: attributeId, value: value })
|
||||||
|
}
|
||||||
|
formik.setFieldValue('attributes', attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={clx(
|
||||||
|
'grid grid-cols-1 md:grid-cols-2 gap-6',
|
||||||
|
!attributes && 'hidden'
|
||||||
|
)}>
|
||||||
|
{
|
||||||
|
attributes?.map((item) => {
|
||||||
|
if (item?.type === FieldTypeEnum.select)
|
||||||
|
return (
|
||||||
|
<div key={item.id}>
|
||||||
|
<Select
|
||||||
|
placeholder={`انتخاب ${item.isRequired ? '(اجباری)' : '(اختاری)'}`}
|
||||||
|
label={item.name}
|
||||||
|
items={item.options?.map((value) => {
|
||||||
|
return {
|
||||||
|
label: value.value,
|
||||||
|
value: value.value
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
onChange={(e) => handleChange(item.id, e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
else if (item.type === FieldTypeEnum.checkbox)
|
||||||
|
return (
|
||||||
|
<div key={item.id}>
|
||||||
|
<div className='text-sm mb-3'>{item.name}</div>
|
||||||
|
<div className='flex gap-5 flex-wrap'>
|
||||||
|
{
|
||||||
|
item.options?.map((value) => {
|
||||||
|
const object = formik.values.printAttributes.find(o => o.fieldId === item.id)
|
||||||
|
return (
|
||||||
|
<div key={value.id} className='flex gap-2 items-center'>
|
||||||
|
<div>{value.value}</div>
|
||||||
|
<Checkbox
|
||||||
|
name={item.id + ''}
|
||||||
|
checked={object?.value === value.value}
|
||||||
|
onCheckedChange={(checked) => handleChange(item.id, checked ? value.value : '')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
else if (item.type === FieldTypeEnum.radio) {
|
||||||
|
const object = formik.values.printAttributes.find(o => o.fieldId === item.id)
|
||||||
|
return (
|
||||||
|
<div key={item.id}>
|
||||||
|
<div className='text-sm mb-3'>{item.name}</div>
|
||||||
|
<RadioGroup
|
||||||
|
items={item.options?.map((value) => {
|
||||||
|
return {
|
||||||
|
label: value.value,
|
||||||
|
value: value.value
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
onChange={(v) => handleChange(item.id, v)}
|
||||||
|
selected={object?.value + '' || ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (item.type === FieldTypeEnum.date)
|
||||||
|
return (
|
||||||
|
<div key={item.id}>
|
||||||
|
<DatePickerComponent
|
||||||
|
onChange={(date) => handleChange(item.id, date)}
|
||||||
|
placeholder=''
|
||||||
|
label={item.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
else if (item.type === FieldTypeEnum.number || item.type === FieldTypeEnum.text)
|
||||||
|
return (
|
||||||
|
<div key={item.id}>
|
||||||
|
<Input
|
||||||
|
label={item.name}
|
||||||
|
type={item.type}
|
||||||
|
onChange={(e) => handleChange(item.id, e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
else if (item.type === FieldTypeEnum.textarea)
|
||||||
|
return (
|
||||||
|
<div key={item.id} className="md:col-span-2">
|
||||||
|
<Textarea
|
||||||
|
label={item.name}
|
||||||
|
onChange={(e) => handleChange(item.id, e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ManageForms
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||||
import * as api from "../service/PrintService";
|
import * as api from "../service/PrintService";
|
||||||
import type { CreateSectionType } from "../types/Types";
|
import type { CreatePrintFormType, CreateSectionType } from "../types/Types";
|
||||||
|
|
||||||
export const useGetSections = () => {
|
export const useGetSections = () => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
@@ -55,3 +55,25 @@ export const useDeleteSection = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useCreatePrintForm = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: ({
|
||||||
|
orderId,
|
||||||
|
itemId,
|
||||||
|
params,
|
||||||
|
}: {
|
||||||
|
orderId: string;
|
||||||
|
itemId: number;
|
||||||
|
params: CreatePrintFormType;
|
||||||
|
}) => api.createPrintForm(orderId, itemId, params),
|
||||||
|
// onSuccess: (_, params) => {
|
||||||
|
// queryClient.refetchQueries({
|
||||||
|
// queryKey: ["sections"],
|
||||||
|
// });
|
||||||
|
// queryClient.refetchQueries({
|
||||||
|
// queryKey: ["section", params.id],
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import axios from "@/config/axios";
|
import axios from "@/config/axios";
|
||||||
import type {
|
import type {
|
||||||
|
CreatePrintFormType,
|
||||||
CreateSectionType,
|
CreateSectionType,
|
||||||
SectionDetailResponseType,
|
SectionDetailResponseType,
|
||||||
SectionsResponseType,
|
SectionsResponseType,
|
||||||
@@ -31,3 +32,15 @@ export const deleteSection = async (id: number) => {
|
|||||||
const { data } = await axios.delete(`/admin/section/${id}`);
|
const { data } = await axios.delete(`/admin/section/${id}`);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const createPrintForm = async (
|
||||||
|
orderId: string,
|
||||||
|
itemId: number,
|
||||||
|
params: CreatePrintFormType
|
||||||
|
) => {
|
||||||
|
const { data } = await axios.patch(
|
||||||
|
`/admin/orders/${orderId}/item/${itemId}/print`,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { EntityType } from "@/pages/formBuilder/types/Types";
|
||||||
import type { BaseResponse } from "@/shared/types/Types";
|
import type { BaseResponse } from "@/shared/types/Types";
|
||||||
|
|
||||||
export type CreateSectionType = {
|
export type CreateSectionType = {
|
||||||
@@ -10,7 +11,17 @@ export type SectionItemType = {
|
|||||||
id: number;
|
id: number;
|
||||||
order: number;
|
order: number;
|
||||||
title: string;
|
title: string;
|
||||||
|
fields: EntityType[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SectionsResponseType = BaseResponse<SectionItemType[]>;
|
export type SectionsResponseType = BaseResponse<SectionItemType[]>;
|
||||||
export type SectionDetailResponseType = BaseResponse<SectionItemType>;
|
export type SectionDetailResponseType = BaseResponse<SectionItemType>;
|
||||||
|
|
||||||
|
export type PrintAttributesType = {
|
||||||
|
fieldId: number;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CreatePrintFormType = {
|
||||||
|
printAttributes: PrintAttributesType[];
|
||||||
|
};
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import EditOrder from '@/pages/order/EditOrder'
|
|||||||
import SectionList from '@/pages/print/List'
|
import SectionList from '@/pages/print/List'
|
||||||
import CreateSection from '@/pages/print/Create'
|
import CreateSection from '@/pages/print/Create'
|
||||||
import UpdateSection from '@/pages/print/Update'
|
import UpdateSection from '@/pages/print/Update'
|
||||||
|
import PrintForm from '@/pages/print/Form'
|
||||||
|
|
||||||
const MainRouter: FC = () => {
|
const MainRouter: FC = () => {
|
||||||
return (
|
return (
|
||||||
@@ -84,6 +85,7 @@ const MainRouter: FC = () => {
|
|||||||
<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 />} />
|
||||||
<Route path={Paths.print.update + ':id'} element={<UpdateSection />} />
|
<Route path={Paths.print.update + ':id'} element={<UpdateSection />} />
|
||||||
|
<Route path={Paths.print.form + ':itemId/:orderId'} element={<PrintForm />} />
|
||||||
|
|
||||||
<Route path={Paths.features.list} element={<FeaturesList />} />
|
<Route path={Paths.features.list} element={<FeaturesList />} />
|
||||||
<Route path={Paths.features.create} element={<CreateFeature />} />
|
<Route path={Paths.features.create} element={<CreateFeature />} />
|
||||||
|
|||||||
Reference in New Issue
Block a user