update attribute

This commit is contained in:
hamid zarghami
2026-01-25 10:23:56 +03:30
parent f8f79e3a9d
commit 33130ba76d
5 changed files with 185 additions and 1 deletions
+143
View File
@@ -0,0 +1,143 @@
import { useFormik } from 'formik'
import { useEffect, 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 { useGetAttributeDetail, useUpdateAttribute } from '../hooks/useProductData'
import { useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify'
import { extractErrorMessage } from '@/config/func'
const UpdateAttribute: FC = () => {
const { id } = useParams()
const navigate = useNavigate()
const { data, refetch } = useGetAttributeDetail(Number(id))
const { mutate: createAttribute, isPending } = useUpdateAttribute()
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('با موفقیت ذخیره شد')
refetch()
navigate(-1)
},
onError: (error) => {
toast.error(extractErrorMessage(error))
}
})
}
})
useEffect(() => {
if (data) {
formik.setValues({
isRequired: data?.data?.isRequired,
name: data?.data?.name,
order: data?.data?.order,
type: data?.data?.type
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [data])
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'
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>
)
}
export default UpdateAttribute
+28
View File
@@ -92,9 +92,16 @@ export const useDeleteProduct = () => {
};
export const useCreateAttribute = () => {
const queryClient = new QueryClient();
return useMutation({
mutationFn: ({ id, params }: { id: number; params: CreateAttributeType }) =>
api.createAttribute(id, params),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["product-attributes"],
});
},
});
};
@@ -105,3 +112,24 @@ export const useGetAttributes = (id: number) => {
enabled: !!id,
});
};
export const useGetAttributeDetail = (id: number) => {
return useQuery({
queryKey: ["product-attribute", id],
queryFn: () => api.getAttributeDetail(id),
enabled: !!id,
});
};
export const useUpdateAttribute = () => {
const queryClient = new QueryClient();
return useMutation({
mutationFn: ({ id, params }: { id: number; params: CreateAttributeType }) =>
api.updateAttribute(id, params),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["product-attributes"],
});
},
});
};
+11 -1
View File
@@ -1,5 +1,5 @@
import axios from "@/config/axios";
import { type AttributeResponseType, type CategoriesResponse, type CategoryResponse, type CreateAttributeType, type CreateCategoryType, type CreateProductType, type ProductDetailResponeType, type ProductResponeType } from "../types/Types";
import { type AttributeDetailResponseType, type AttributeResponseType, 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");
@@ -59,4 +59,14 @@ export const createAttribute = async (id: number, params:CreateAttributeType) =>
export const getAttributes = async (id: number) => {
const { data } = await axios.get<AttributeResponseType>(`/admin/products/${id}/attributes`);
return data;
};
export const getAttributeDetail = async (id: number) => {
const { data } = await axios.get<AttributeDetailResponseType>(`/admin/products/attributes/${id}`);
return data;
};
export const updateAttribute = async (id: number, params:CreateAttributeType) => {
const { data } = await axios.patch(`/admin/products/attributes/${id}`, params);
return data;
};
+1
View File
@@ -70,3 +70,4 @@ export type AttributeType = {
}
export type AttributeResponseType = BaseResponse<AttributeType[]>;
export type AttributeDetailResponseType = BaseResponse<AttributeType>;