create attribute

This commit is contained in:
hamid zarghami
2026-01-25 09:40:41 +03:30
parent 5fad34cc84
commit a37a7191dd
9 changed files with 165 additions and 12 deletions
+1 -1
View File
@@ -1,3 +1,3 @@
VITE_API_BASE_URL = 'http://172.27.69.89:4000'
VITE_API_BASE_URL = 'http://192.168.99.235:4000'
VITE_TOKEN_NAME = 'negareh_t'
VITE_REFRESH_TOKEN_NAME = 'negareh_rt'
+3 -3
View File
@@ -12,9 +12,9 @@ export const Paths = {
update: '/product/category/update/'
},
attribute: {
list: '/attribute/list',
create: '/attribute/create',
update: '/attribute/update'
list: '/product/attribute/',
create: '/product/attribute/create/',
update: '/product/attribute/update/'
}
},
order: {
+3 -3
View File
@@ -73,12 +73,12 @@ const ProductList: FC = () => {
{
key: 'attribute',
title: 'ویژگی ها',
render: () => {
render: (item) => {
return (
<div className='flex text-[#0037FF] gap-2 items-center'>
<Link to={Paths.product.attribute.list + item.id} className='flex text-[#0037FF] gap-2 items-center'>
<More2 size={18} color='#0037FF' />
<div className='text-[13px]'>ویژگی ها</div>
</div>
</Link>
)
}
},
+121 -3
View File
@@ -1,8 +1,126 @@
import React from 'react'
import { useFormik } from 'formik'
import { type FC } from 'react'
import type { CreateAttributeType } from '../types/Types'
import { FieldTypeEnum } from '../enum/Enum'
import * as Yup from 'yup'
import Button from '@/components/Button'
import { AddSquare } from 'iconsax-react'
import Input from '@/components/Input'
import Select from '@/components/Select'
import SwitchComponent from '@/components/Switch'
import { useCreateAttribute } from '../hooks/useProductData'
import { useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func'
import { Paths } from '@/config/Paths'
const CreateAttribute: FC = () => {
const { id } = useParams()
const navigate = useNavigate()
const { mutate: createAttribute, isPending } = useCreateAttribute()
const formik = useFormik<CreateAttributeType>({
initialValues: {
name: '',
isRequired: true,
order: 1,
type: FieldTypeEnum.text,
},
validationSchema: Yup.object({
name: Yup.string().required('این فیلد اجباری می باشد')
}),
onSubmit: (values) => {
createAttribute({ id: Number(id), params: values }, {
onSuccess: () => {
toast.success('با موفقیت ذخیره شد')
navigate(Paths.product.attribute.list + id)
},
onError: (error) => {
toast.error(extractErrorMessage(error))
}
})
}
})
const CreateAttribute = () => {
return (
<div>CreateAttribute</div>
<div className='mt-5'>
<div className='flex justify-between items-center'>
<h1 className='text-lg font-light'>ساخت ویژگی جدید</h1>
<Button
className='w-fit px-6'
onClick={() => formik.handleSubmit()}
isLoading={isPending}
>
<div className='flex gap-1.5'>
<AddSquare size={18} color='black' />
<div className='text-[13px] font-light'>ویژگی جدید</div>
</div>
</Button>
</div>
<div className='mt-8 bg-white p-6 rounded-3xl flex-1'>
<div className='rowTwoInput'>
<Input
label='نام ویژگی'
{...formik.getFieldProps('name')}
error_text={formik.touched.name && formik.errors.name ? formik.errors.name : ''}
/>
<Select
label='نوع'
items={[
{
label: 'متن',
value: FieldTypeEnum.text
},
{
label: 'چک باکس',
value: FieldTypeEnum.checkbox
},
{
label: 'تاریخ',
value: FieldTypeEnum.date
},
{
label: 'عدد',
value: FieldTypeEnum.number
},
{
label: 'رادیو',
value: FieldTypeEnum.radio
},
{
label: 'کامبوباکس',
value: FieldTypeEnum.select
},
{
label: 'متن بلند',
value: FieldTypeEnum.textarea
},
]}
{...formik.getFieldProps('type')}
/>
</div>
<div className='mt-6'>
<Input
label='ترتیب اولویت'
{...formik.getFieldProps('order')}
/>
</div>
<div className='mt-6'>
<SwitchComponent
active={formik.values.isRequired}
onChange={(value) => formik.setFieldValue('isRequired', value)}
label='اجباری'
/>
</div>
</div>
</div>
)
}
+9
View File
@@ -0,0 +1,9 @@
export const enum FieldTypeEnum {
text = "text",
textarea = "textarea",
number = "number",
select = "select",
radio = "radio",
checkbox = "checkbox",
date = "date",
}
+12 -1
View File
@@ -5,7 +5,11 @@ import {
useQueryClient,
} from "@tanstack/react-query";
import * as api from "../service/ProductService";
import type { CreateCategoryType, CreateProductType } from "../types/Types";
import type {
CreateAttributeType,
CreateCategoryType,
CreateProductType,
} from "../types/Types";
export const useGetCategory = () => {
return useQuery({
@@ -86,3 +90,10 @@ export const useDeleteProduct = () => {
mutationFn: (id: number) => api.deleteProduct(id),
});
};
export const useCreateAttribute = () => {
return useMutation({
mutationFn: ({ id, params }: { id: number; params: CreateAttributeType }) =>
api.createAttribute(id, params),
});
};
+6 -1
View File
@@ -1,5 +1,5 @@
import axios from "@/config/axios";
import { type CategoriesResponse, type CategoryResponse, type CreateCategoryType, type CreateProductType, type ProductDetailResponeType, type ProductResponeType } from "../types/Types";
import { type CategoriesResponse, type CategoryResponse, type CreateAttributeType, type CreateCategoryType, type CreateProductType, type ProductDetailResponeType, type ProductResponeType } from "../types/Types";
export const getCategory = async () => {
const { data } = await axios.get<CategoriesResponse>("/admin/category");
@@ -49,4 +49,9 @@ export const updateProduct = async (id: number, params:CreateProductType) => {
export const deleteProduct = async (id: number) => {
const { data } = await axios.delete(`/admin/products/${id}`);
return data;
};
export const createAttribute = async (id: number, params:CreateAttributeType) => {
const { data } = await axios.post(`/admin/product/${id}/attribute`, params);
return data;
};
+8
View File
@@ -1,5 +1,6 @@
import type { RowDataType } from "@/components/types/TableTypes";
import { type BaseResponse } from "@/shared/types/Types";
import type { FieldTypeEnum } from "../enum/Enum";
export interface CategoryType extends RowDataType {
avatarUrl: string | null;
@@ -50,3 +51,10 @@ export type ProductType = {
export type ProductResponeType = BaseResponse<ProductType[]>;
export type ProductDetailResponeType = BaseResponse<ProductType>;
export type CreateAttributeType = {
name: string,
isRequired: boolean,
type: FieldTypeEnum,
order: number
}
+2
View File
@@ -29,6 +29,7 @@ import CategoryList from '@/pages/product/category/List'
import CreateCategory from '@/pages/product/category/Create'
import UpdateCategory from '@/pages/product/category/Update'
import UpdateProduct from '@/pages/product/Update'
import CreateAttribute from '@/pages/product/attribute/Create'
const MainRouter: FC = () => {
return (
@@ -49,6 +50,7 @@ const MainRouter: FC = () => {
<Route path={Paths.product.list} element={<ProductList />} />
<Route path={Paths.product.create} element={<CreateProduct />} />
<Route path={Paths.product.update + ':id'} element={<UpdateProduct />} />
<Route path={Paths.product.attribute.create + ':id'} element={<CreateAttribute />} />
<Route path={Paths.product.category.list} element={<CategoryList />} />
<Route path={Paths.product.category.create} element={<CreateCategory />} />
<Route path={Paths.product.category.update + ':id'} element={<UpdateCategory />} />