delete and edit category attribute
This commit is contained in:
@@ -6,7 +6,8 @@ import { AttributesModal } from './components'
|
||||
import { useAttributesLogic } from './hooks/useAttributesLogic'
|
||||
import { useGetCategoryAttributes } from './hooks/useCategoryData'
|
||||
import { type CategoryAttributeType } from './types/Types'
|
||||
import { Add, Edit, Trash } from 'iconsax-react'
|
||||
import { Add, Edit } from 'iconsax-react'
|
||||
import TrashWithConfrim from '../../components/TrashWithConfrim'
|
||||
|
||||
const Attributes: FC = () => {
|
||||
const { id } = useParams()
|
||||
@@ -16,13 +17,17 @@ const Attributes: FC = () => {
|
||||
isLoading,
|
||||
isModalOpen,
|
||||
newAttribute,
|
||||
editingAttributeId,
|
||||
openModal,
|
||||
closeModal,
|
||||
openEditModal,
|
||||
setNewAttribute,
|
||||
addAttribute,
|
||||
deleteAttribute,
|
||||
addValueToAttribute,
|
||||
removeValueFromAttribute,
|
||||
isAddingLoading
|
||||
isAddingLoading,
|
||||
isDeletingLoading
|
||||
} = useAttributesLogic({ id })
|
||||
|
||||
const attributes = attributesData?.results?.data?.category?.attributes || []
|
||||
@@ -83,7 +88,7 @@ const Attributes: FC = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50">
|
||||
<div className="min-h-screen">
|
||||
<PageTitle />
|
||||
<div className="max-w-6xl mx-auto p-6">
|
||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 p-6 mb-6">
|
||||
@@ -157,20 +162,12 @@ const Attributes: FC = () => {
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-blue-500 hover:text-blue-700"
|
||||
>
|
||||
<Edit size={16} />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-red-500 hover:text-red-700"
|
||||
>
|
||||
<Trash size={16} />
|
||||
</Button>
|
||||
|
||||
<Edit onClick={() => openEditModal(attribute)} color='#8C90A3' size={16} />
|
||||
<TrashWithConfrim
|
||||
onDelete={() => deleteAttribute(attribute._id)}
|
||||
isLoading={isDeletingLoading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{attribute.hint && (
|
||||
@@ -204,6 +201,7 @@ const Attributes: FC = () => {
|
||||
onAddValue={addValueToAttribute}
|
||||
onRemoveValue={removeValueFromAttribute}
|
||||
isLoading={isAddingLoading}
|
||||
isEditing={!!editingAttributeId}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ interface AttributesModalProps {
|
||||
onAddValue: (text: string) => void
|
||||
onRemoveValue: (index: number) => void
|
||||
isLoading?: boolean
|
||||
isEditing?: boolean
|
||||
}
|
||||
|
||||
const AttributesModal: FC<AttributesModalProps> = ({
|
||||
@@ -27,7 +28,8 @@ const AttributesModal: FC<AttributesModalProps> = ({
|
||||
onAdd,
|
||||
onAddValue,
|
||||
onRemoveValue,
|
||||
isLoading = false
|
||||
isLoading = false,
|
||||
isEditing = false
|
||||
}) => {
|
||||
const [newValue, setNewValue] = useState('')
|
||||
|
||||
@@ -55,7 +57,7 @@ const AttributesModal: FC<AttributesModalProps> = ({
|
||||
open={isOpen}
|
||||
close={onClose}
|
||||
isHeader={true}
|
||||
title_header="اضافه کردن ویژگی جدید"
|
||||
title_header={isEditing ? "ویرایش ویژگی" : "اضافه کردن ویژگی جدید"}
|
||||
width={600}
|
||||
>
|
||||
<div className="space-y-6">
|
||||
@@ -150,7 +152,7 @@ const AttributesModal: FC<AttributesModalProps> = ({
|
||||
onClick={onAdd}
|
||||
disabled={!isFormValid() || isLoading}
|
||||
>
|
||||
{isLoading ? 'در حال اضافه کردن...' : 'اضافه کردن'}
|
||||
{isLoading ? (isEditing ? 'در حال ویرایش...' : 'در حال اضافه کردن...') : (isEditing ? 'ویرایش' : 'اضافه کردن')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useGetCategoryById, useCreateCategoryAttribute } from './useCategoryData'
|
||||
import { useGetCategoryById, useCreateCategoryAttribute, useUpdateCategoryAttribute, useDeleteCategoryAttribute } from './useCategoryData'
|
||||
import { type CreateCategoryAttributeType } from '../types/Types'
|
||||
import { toast } from 'react-toastify'
|
||||
import { extractErrorMessage } from '../../../helpers/utils'
|
||||
@@ -13,8 +13,11 @@ export const useAttributesLogic = ({ id }: UseAttributesLogicProps) => {
|
||||
const queryClient = useQueryClient()
|
||||
const { data, isLoading } = useGetCategoryById(id!)
|
||||
const createAttributeMutation = useCreateCategoryAttribute()
|
||||
const updateAttributeMutation = useUpdateCategoryAttribute()
|
||||
const deleteAttributeMutation = useDeleteCategoryAttribute()
|
||||
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
const [editingAttributeId, setEditingAttributeId] = useState<number | null>(null)
|
||||
const [newAttribute, setNewAttribute] = useState<CreateCategoryAttributeType>({
|
||||
title: '',
|
||||
type: 'text',
|
||||
@@ -27,6 +30,7 @@ export const useAttributesLogic = ({ id }: UseAttributesLogicProps) => {
|
||||
|
||||
const resetModal = () => {
|
||||
setIsModalOpen(false)
|
||||
setEditingAttributeId(null)
|
||||
setNewAttribute({
|
||||
title: '',
|
||||
type: 'text',
|
||||
@@ -38,23 +42,68 @@ export const useAttributesLogic = ({ id }: UseAttributesLogicProps) => {
|
||||
const openModal = () => setIsModalOpen(true)
|
||||
const closeModal = () => resetModal()
|
||||
|
||||
const openEditModal = (attribute: any) => {
|
||||
setEditingAttributeId(attribute._id)
|
||||
setNewAttribute({
|
||||
title: attribute.title,
|
||||
type: attribute.type,
|
||||
multiple: attribute.multiple,
|
||||
hint: attribute.hint || '',
|
||||
required: attribute.required,
|
||||
values: attribute.values.map((v: any) => ({ text: v.text }))
|
||||
})
|
||||
setIsModalOpen(true)
|
||||
}
|
||||
|
||||
const addAttribute = async () => {
|
||||
if (!id || !newAttribute.title.trim()) return
|
||||
|
||||
createAttributeMutation.mutate(
|
||||
{ id, data: newAttribute },
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success('ویژگی با موفقیت اضافه شد')
|
||||
resetModal()
|
||||
queryClient.invalidateQueries({ queryKey: ['category', id] })
|
||||
queryClient.invalidateQueries({ queryKey: ['category', 'attributes', id] })
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
if (editingAttributeId) {
|
||||
// ویرایش ویژگی
|
||||
updateAttributeMutation.mutate(
|
||||
{ attrId: editingAttributeId, ...newAttribute },
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success('ویژگی با موفقیت ویرایش شد')
|
||||
resetModal()
|
||||
queryClient.invalidateQueries({ queryKey: ['category', id] })
|
||||
queryClient.invalidateQueries({ queryKey: ['category', 'attributes', id] })
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
// ایجاد ویژگی جدید
|
||||
createAttributeMutation.mutate(
|
||||
{ id, data: newAttribute },
|
||||
{
|
||||
onSuccess: () => {
|
||||
toast.success('ویژگی با موفقیت اضافه شد')
|
||||
resetModal()
|
||||
queryClient.invalidateQueries({ queryKey: ['category', id] })
|
||||
queryClient.invalidateQueries({ queryKey: ['category', 'attributes', id] })
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const deleteAttribute = async (attributeId: number) => {
|
||||
deleteAttributeMutation.mutate(attributeId, {
|
||||
onSuccess: () => {
|
||||
toast.success('ویژگی با موفقیت حذف شد')
|
||||
queryClient.invalidateQueries({ queryKey: ['category', id] })
|
||||
queryClient.invalidateQueries({ queryKey: ['category', 'attributes', id] })
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(extractErrorMessage(error))
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const updateNewAttribute = (field: keyof CreateCategoryAttributeType, value: any) => {
|
||||
@@ -87,16 +136,20 @@ export const useAttributesLogic = ({ id }: UseAttributesLogicProps) => {
|
||||
// Modal state
|
||||
isModalOpen,
|
||||
newAttribute,
|
||||
editingAttributeId,
|
||||
|
||||
// Actions
|
||||
openModal,
|
||||
closeModal,
|
||||
openEditModal,
|
||||
setNewAttribute: updateNewAttribute,
|
||||
addAttribute,
|
||||
deleteAttribute,
|
||||
addValueToAttribute,
|
||||
removeValueFromAttribute,
|
||||
|
||||
// Loading states
|
||||
isAddingLoading: createAttributeMutation.isPending
|
||||
isAddingLoading: createAttributeMutation.isPending || updateAttributeMutation.isPending,
|
||||
isDeletingLoading: deleteAttributeMutation.isPending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,4 +83,17 @@ export const useGetCategoryAttributes = (id: string) => {
|
||||
queryFn: () => api.getCategoryAttributes(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateCategoryAttribute = () => {
|
||||
return useMutation({
|
||||
mutationFn: (params: CreateCategoryAttributeType & { attrId: number }) =>
|
||||
api.updateCategoryAttribute(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteCategoryAttribute = () => {
|
||||
return useMutation({
|
||||
mutationFn: (id: number) => api.deleteCategoryAttribute(id),
|
||||
});
|
||||
};
|
||||
@@ -66,4 +66,14 @@ export const createCategoryAttribute = async (id: string, params: CreateCategory
|
||||
export const getCategoryAttributes = async (id: string): Promise<CategoryAttributesResponseType> => {
|
||||
const { data } = await axios.get(`/category/${id}/attributes`);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const updateCategoryAttribute = async (params: CreateCategoryAttributeType & { attrId: number }) => {
|
||||
const { data } = await axios.patch(`/admin/category/attributes`, params);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const deleteCategoryAttribute = async (id: number) => {
|
||||
const { data } = await axios.delete(`/admin/category/attributes/${id}/delete`);
|
||||
return data;
|
||||
};
|
||||
Reference in New Issue
Block a user