formbuilder

This commit is contained in:
hamid zarghami
2026-01-29 10:24:41 +03:30
parent 2234c44202
commit f9899f108c
6 changed files with 48 additions and 30 deletions
+5
View File
@@ -20,6 +20,11 @@ export const Paths = {
list: '/product/attribute-value/' list: '/product/attribute-value/'
} }
}, },
formBuilder: {
list: '/form-builder/list/',
create: '/form-builder/create/',
update: '/form-builder/update/',
},
order: { order: {
list: '/order/list' list: '/order/list'
}, },
+12 -10
View File
@@ -1,40 +1,42 @@
import { useFormik } from 'formik' import { useFormik } from 'formik'
import { type FC } from 'react' import { type FC } from 'react'
import type { CreateAttributeType } from '../types/Types' import type { CreateFieldType } from './types/Types'
import { FieldTypeEnum } from '../enum/Enum' import { FieldTypeEnum } from './enum/Enum'
import * as Yup from 'yup' import * as Yup from 'yup'
import Button from '@/components/Button' import Button from '@/components/Button'
import { AddSquare } from 'iconsax-react' import { AddSquare } from 'iconsax-react'
import Input from '@/components/Input' import Input from '@/components/Input'
import Select from '@/components/Select' import Select from '@/components/Select'
import SwitchComponent from '@/components/Switch' import SwitchComponent from '@/components/Switch'
import { useCreateAttribute } from '../hooks/useProductData' import { useCreateField } from './hooks/useFormBuilderData'
import { useNavigate, useParams } from 'react-router-dom' import { useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func' import { extractErrorMessage } from '@/config/func'
import { Paths } from '@/config/Paths' import { Paths } from '@/config/Paths'
const CreateAttribute: FC = () => { const FormBuilderCreate: FC = () => {
const { id } = useParams() const { id, type } = useParams()
const navigate = useNavigate() const navigate = useNavigate()
const { mutate: createAttribute, isPending } = useCreateAttribute() const { mutate: createField, isPending } = useCreateField()
const formik = useFormik<CreateAttributeType>({ const formik = useFormik<CreateFieldType>({
initialValues: { initialValues: {
name: '', name: '',
isRequired: true, isRequired: true,
order: 1, order: 1,
type: FieldTypeEnum.text, type: FieldTypeEnum.text,
entityType: 'product',
multiple: false,
}, },
validationSchema: Yup.object({ validationSchema: Yup.object({
name: Yup.string().required('این فیلد اجباری می باشد') name: Yup.string().required('این فیلد اجباری می باشد')
}), }),
onSubmit: (values) => { onSubmit: (values) => {
createAttribute({ id: Number(id), params: values }, { createField({ id: Number(id), params: values }, {
onSuccess: () => { onSuccess: () => {
toast.success('با موفقیت ذخیره شد') toast.success('با موفقیت ذخیره شد')
navigate(Paths.product.attribute.list + id) navigate(Paths.formBuilder.list + `${id}/${type} `)
}, },
onError: (error) => { onError: (error) => {
toast.error(extractErrorMessage(error)) toast.error(extractErrorMessage(error))
@@ -124,4 +126,4 @@ const CreateAttribute: FC = () => {
) )
} }
export default CreateAttribute export default FormBuilderCreate
+9 -9
View File
@@ -3,20 +3,20 @@ import { Paths } from '@/config/Paths'
import { AddSquare, Edit } from 'iconsax-react' import { AddSquare, Edit } from 'iconsax-react'
import { type FC } from 'react' import { type FC } from 'react'
import { Link, useParams } from 'react-router-dom' import { Link, useParams } from 'react-router-dom'
import { useDeleteAttribute, useGetAttributes } from '../hooks/useProductData' import { useDeleteField, useGetFields } from './hooks/useFormBuilderData'
import Table from '@/components/Table' import Table from '@/components/Table'
import TrashWithConfrim from '@/components/TrashWithConfrim' import TrashWithConfrim from '@/components/TrashWithConfrim'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func' import { extractErrorMessage } from '@/config/func'
const AttributeList: FC = () => { const FormBuilderList: FC = () => {
const { id } = useParams() const { id } = useParams()
const { mutate: deleteAttribute, isPending } = useDeleteAttribute() const { mutate: deleteField, isPending } = useDeleteField()
const { data, refetch } = useGetAttributes(Number(id)) const { data, refetch } = useGetFields(Number(id))
const handleDelete = (id: number) => { const handleDelete = (id: number) => {
deleteAttribute(id, { deleteField(id, {
onSuccess: () => { onSuccess: () => {
refetch() refetch()
}, },
@@ -33,7 +33,7 @@ const AttributeList: FC = () => {
<h1 className='text-lg font-light'>ویژگی ها</h1> <h1 className='text-lg font-light'>ویژگی ها</h1>
<Link <Link
to={Paths.product.attribute.create + id} to={Paths.formBuilder.create + id}
> >
<Button <Button
className='w-fit px-6' className='w-fit px-6'
@@ -71,7 +71,7 @@ const AttributeList: FC = () => {
title: 'مقادیر', title: 'مقادیر',
render: (item) => { render: (item) => {
return ( return (
<Link to={Paths.product.attributeValue.list + item.id}> <Link to={Paths.formBuilder.list + item.id}>
<Button className='w-fit px-5'> <Button className='w-fit px-5'>
میدیریت مقادیر میدیریت مقادیر
</Button> </Button>
@@ -85,7 +85,7 @@ const AttributeList: FC = () => {
render: (item) => { render: (item) => {
return ( return (
<div className='flex gap-2 items-center'> <div className='flex gap-2 items-center'>
<Link to={Paths.product.attribute.update + item.id}> <Link to={Paths.formBuilder.update + item.id}>
<Edit <Edit
color='#0037FF' color='#0037FF'
size={20} size={20}
@@ -110,4 +110,4 @@ const AttributeList: FC = () => {
) )
} }
export default AttributeList export default FormBuilderList
+14 -10
View File
@@ -1,37 +1,39 @@
import { useFormik } from 'formik' import { useFormik } from 'formik'
import { useEffect, type FC } from 'react' import { useEffect, type FC } from 'react'
import type { CreateAttributeType } from '../types/Types' import type { CreateFieldType } from './types/Types'
import { FieldTypeEnum } from '../enum/Enum' import { FieldTypeEnum } from './enum/Enum'
import * as Yup from 'yup' import * as Yup from 'yup'
import Button from '@/components/Button' import Button from '@/components/Button'
import { AddSquare } from 'iconsax-react' import { AddSquare } from 'iconsax-react'
import Input from '@/components/Input' import Input from '@/components/Input'
import Select from '@/components/Select' import Select from '@/components/Select'
import SwitchComponent from '@/components/Switch' import SwitchComponent from '@/components/Switch'
import { useGetAttributeDetail, useUpdateAttribute } from '../hooks/useProductData' import { useGetFieldDetail, useUpdateField } from './hooks/useFormBuilderData'
import { useNavigate, useParams } from 'react-router-dom' import { useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func' import { extractErrorMessage } from '@/config/func'
const UpdateAttribute: FC = () => { const FormBuilderUpdate: FC = () => {
const { id } = useParams() const { id } = useParams()
const navigate = useNavigate() const navigate = useNavigate()
const { data, refetch } = useGetAttributeDetail(Number(id)) const { data, refetch } = useGetFieldDetail(Number(id))
const { mutate: createAttribute, isPending } = useUpdateAttribute() const { mutate: createField, isPending } = useUpdateField()
const formik = useFormik<CreateAttributeType>({ const formik = useFormik<CreateFieldType>({
initialValues: { initialValues: {
name: '', name: '',
isRequired: true, isRequired: true,
order: 1, order: 1,
type: FieldTypeEnum.text, type: FieldTypeEnum.text,
entityType: 'product',
multiple: false
}, },
validationSchema: Yup.object({ validationSchema: Yup.object({
name: Yup.string().required('این فیلد اجباری می باشد') name: Yup.string().required('این فیلد اجباری می باشد')
}), }),
onSubmit: (values) => { onSubmit: (values) => {
createAttribute({ id: Number(id), params: values }, { createField({ id: Number(id), params: values }, {
onSuccess: () => { onSuccess: () => {
toast.success('با موفقیت ذخیره شد') toast.success('با موفقیت ذخیره شد')
refetch() refetch()
@@ -51,7 +53,9 @@ const UpdateAttribute: FC = () => {
isRequired: data?.data?.isRequired, isRequired: data?.data?.isRequired,
name: data?.data?.name, name: data?.data?.name,
order: data?.data?.order, order: data?.data?.order,
type: data?.data?.type type: data?.data?.type,
entityType: data?.data?.entityType,
multiple: data?.data?.multiple
}) })
} }
@@ -140,4 +144,4 @@ const UpdateAttribute: FC = () => {
) )
} }
export default UpdateAttribute export default FormBuilderUpdate
+1 -1
View File
@@ -75,7 +75,7 @@ const ProductList: FC = () => {
title: 'ویژگی ها', title: 'ویژگی ها',
render: (item) => { render: (item) => {
return ( return (
<Link to={Paths.product.attribute.list + item.id} className='flex text-[#0037FF] gap-2 items-center'> <Link to={Paths.formBuilder.list + item.id + `/product`} className='flex text-[#0037FF] gap-2 items-center'>
<More2 size={18} color='#0037FF' /> <More2 size={18} color='#0037FF' />
<div className='text-[13px]'>ویژگی ها</div> <div className='text-[13px]'>ویژگی ها</div>
</Link> </Link>
+7
View File
@@ -33,6 +33,9 @@ import CreateAttribute from '@/pages/product/attribute/Create'
import AttributeList from '@/pages/product/attribute/List' import AttributeList from '@/pages/product/attribute/List'
import UpdateAttribute from '@/pages/product/attribute/Update' import UpdateAttribute from '@/pages/product/attribute/Update'
import AttributeValues from '@/pages/product/attribute/AttributeValues' import AttributeValues from '@/pages/product/attribute/AttributeValues'
import FormBuilderList from '@/pages/formBuilder/List'
import FormBuilderCreate from '@/pages/formBuilder/Create'
import FormBuilderUpdate from '@/pages/formBuilder/Update'
const MainRouter: FC = () => { const MainRouter: FC = () => {
return ( return (
@@ -61,6 +64,10 @@ const MainRouter: FC = () => {
<Route path={Paths.product.category.create} element={<CreateCategory />} /> <Route path={Paths.product.category.create} element={<CreateCategory />} />
<Route path={Paths.product.category.update + ':id'} element={<UpdateCategory />} /> <Route path={Paths.product.category.update + ':id'} element={<UpdateCategory />} />
<Route path={Paths.formBuilder.list + ':id/:type'} element={<FormBuilderList />} />
<Route path={Paths.formBuilder.create + ':id/:type'} element={<FormBuilderCreate />} />
<Route path={Paths.formBuilder.update + ':id'} element={<FormBuilderUpdate />} />
<Route path={Paths.order.list} element={<OrdersList />} /> <Route path={Paths.order.list} element={<OrdersList />} />
<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 />} />