change category by theme

This commit is contained in:
hamid zarghami
2025-11-29 11:32:14 +03:30
parent b999a764a6
commit 7cf27823ee
4 changed files with 59 additions and 33 deletions
+17 -12
View File
@@ -9,7 +9,6 @@ import Textarea from '../../components/Textarea'
import UploadBox from '../../components/UploadBox'
import Select from '../../components/Select'
import { type CategoryType, type CategoryTreeNode } from './types/Types'
import { CategoryThemeEnum } from './enum/Enum'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { useCreateCategory, useGetCategories, useSingleUpload } from './hooks/useCategoryData'
@@ -17,10 +16,12 @@ import { useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { Pages } from '../../config/Pages'
import { extractErrorMessage } from '@/helpers/utils'
import { useGetThemes } from '../theme/hooks/useThemeData'
const CreateCategory: FC = () => {
const navigate = useNavigate()
const getThemes = useGetThemes()
const [iconFile, setIconFile] = useState<File>()
const [imageFile, setImageFile] = useState<File>()
const [searchTerm, setSearchTerm] = useState('')
@@ -38,14 +39,14 @@ const CreateCategory: FC = () => {
imageUrl: '',
description: '',
parent: undefined,
theme: '',
themeId: undefined,
},
validationSchema: Yup.object({
title_fa: Yup.string().required('عنوان فارسی دسته الزامی است'),
title_en: Yup.string().required('عنوان انگلیسی دسته الزامی است'),
description: Yup.string().required('توضیحات دسته الزامی است'),
parent: Yup.string().optional(),
theme: Yup.string().optional(),
themeId: Yup.string().optional(),
}),
onSubmit: async (values) => {
@@ -76,12 +77,21 @@ const CreateCategory: FC = () => {
})
const categoriesData: CategoryTreeNode[] = getCategories.data?.results?.data || []
const themesData = getThemes.data?.results?.data || []
const filteredCategories = categoriesData.filter(cat =>
cat.title_fa.toLowerCase().includes(searchTerm.toLowerCase()) ||
cat.title_en.toLowerCase().includes(searchTerm.toLowerCase())
)
const themeItems = [
{ value: '', label: 'بدون تم' },
...themesData.map(theme => ({
value: theme._id,
label: theme.title
}))
]
const handleParentSelect = (category: CategoryTreeNode) => {
formik.setFieldValue('parent', category._id)
}
@@ -142,15 +152,10 @@ const CreateCategory: FC = () => {
<Select
label='تم دسته'
placeholder='انتخاب تم دسته'
items={[
{ value: CategoryThemeEnum.Sized, label: 'سایز' },
{ value: CategoryThemeEnum.Colored, label: 'رنگ' },
{ value: CategoryThemeEnum.Meterage, label: 'متراژ' },
{ value: CategoryThemeEnum.No_color_No_sized, label: 'بدون تنوع' },
]}
value={formik.values.theme}
onChange={(e) => formik.setFieldValue('theme', e.target.value)}
error_text={formik.touched.theme && formik.errors.theme ? formik.errors.theme : ''}
items={themeItems}
value={formik.values.themeId || ''}
onChange={(e) => formik.setFieldValue('themeId', e.target.value || undefined)}
error_text={formik.touched.themeId && formik.errors.themeId ? formik.errors.themeId : ''}
/>
</div>
</div>
-6
View File
@@ -73,11 +73,6 @@ const CategoryList: FC = () => {
</div>
</Td>
<Td text={category.description} />
<Td text=''>
{category.leaf && category.theme !== 'noColor_noSize' ? <Link to={`${Pages.category.variant}${category._id}`}>
<Button className='h-7 text-xs w-fit px-4' label='افزودن تنوع' />
</Link> : <Lock size={20} color='#8C90A3' />}
</Td>
<Td text="">
<div className="flex items-center gap-2">
{category.leaf ? <Link to={`${Pages.category.attributes}${category._id}`}>
@@ -151,7 +146,6 @@ const CategoryList: FC = () => {
<Td text={'عنوان انگلیسی'} />
<Td text={'تصویر'} />
<Td text={'توضیحات'} />
<Td text={'تنوع'} />
<Td text={'ویژگی‌ها'} />
<Td text={'عملیات'} />
</tr>
+40 -13
View File
@@ -8,7 +8,6 @@ import Textarea from '../../components/Textarea'
import UploadBox from '../../components/UploadBox'
import Select from '../../components/Select'
import { type CategoryType, type CategoryTreeNode } from './types/Types'
import { CategoryThemeEnum } from './enum/Enum'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { useUpdateCategory, useGetCategories, useGetCategoryById, useSingleUpload } from './hooks/useCategoryData'
@@ -16,10 +15,12 @@ import { useNavigate, useParams } from 'react-router-dom'
import { toast } from 'react-toastify'
import { Pages } from '../../config/Pages'
import { extractErrorMessage } from '@/helpers/utils'
import { useGetThemes } from '../theme/hooks/useThemeData'
const UpdateCategory: FC = () => {
const navigate = useNavigate()
const { id } = useParams<{ id: string }>()
const getThemes = useGetThemes()
const [iconFile, setIconFile] = useState<File>()
const [imageFile, setImageFile] = useState<File>()
const [searchTerm, setSearchTerm] = useState('')
@@ -41,14 +42,14 @@ const UpdateCategory: FC = () => {
imageUrl: '',
description: '',
parent: undefined,
theme: '',
themeId: undefined,
},
validationSchema: Yup.object({
title_fa: Yup.string().required('عنوان فارسی دسته الزامی است'),
title_en: Yup.string().required('عنوان انگلیسی دسته الزامی است'),
description: Yup.string().required('توضیحات دسته الزامی است'),
parent: Yup.string().optional(),
theme: Yup.string().optional(),
themeId: Yup.string().optional(),
}),
onSubmit: async (values) => {
const updatedValues = { ...values }
@@ -91,7 +92,7 @@ const UpdateCategory: FC = () => {
imageUrl: categoryData.imageUrl || '',
description: categoryData.description || '',
parent: categoryData.parent || undefined,
theme: categoryData.theme || '',
themeId: categoryData.theme || undefined,
})
setIsActive(!categoryData.deleted)
setIsDataLoaded(true)
@@ -100,6 +101,15 @@ const UpdateCategory: FC = () => {
}, [getCategoryById.data, isDataLoaded])
const categoriesData: CategoryTreeNode[] = getCategories.data?.results?.data || []
const themesData = getThemes.data?.results?.data || []
const themeItems = [
{ value: '', label: 'بدون تم' },
...themesData.map(theme => ({
value: theme._id,
label: theme.title
}))
]
const filteredCategories = categoriesData.filter(cat =>
@@ -193,15 +203,10 @@ const UpdateCategory: FC = () => {
<Select
label='تم دسته'
placeholder='انتخاب تم دسته'
items={[
{ value: CategoryThemeEnum.Sized, label: 'سایز' },
{ value: CategoryThemeEnum.Colored, label: 'رنگ' },
{ value: CategoryThemeEnum.Meterage, label: 'متراژ' },
{ value: CategoryThemeEnum.No_color_No_sized, label: 'بدون تنوع' },
]}
value={formik.values.theme}
onChange={(e) => formik.setFieldValue('theme', e.target.value)}
error_text={formik.touched.theme && formik.errors.theme ? formik.errors.theme : ''}
items={themeItems}
value={formik.values.themeId || ''}
onChange={(e) => formik.setFieldValue('themeId', e.target.value || undefined)}
error_text={formik.touched.themeId && formik.errors.themeId ? formik.errors.themeId : ''}
/>
</div>
</div>
@@ -263,6 +268,28 @@ const UpdateCategory: FC = () => {
<div className='text-sm bg-white py-6 px-4 rounded-2xl'>
<h2 className='text-lg font-medium mb-4'>انتخاب دسته والد</h2>
{formik.values.parent && (
<div className='mb-4 p-3 bg-blue-50 border border-blue-200 rounded-lg'>
<div className='text-sm font-medium text-blue-700 mb-1'>دسته انتخاب شده:</div>
<div className='text-xs text-blue-600'>
{(() => {
const findCategory = (cats: CategoryTreeNode[], id: string): CategoryTreeNode | null => {
for (const cat of cats) {
if (cat._id === id) return cat
if (cat.children.length > 0) {
const found = findCategory(cat.children, id)
if (found) return found
}
}
return null
}
const selected = findCategory(categoriesData, formik.values.parent)
return selected ? selected.title_fa : 'نامشخص'
})()}
</div>
</div>
)}
{/* جستجو */}
<div className='mb-4'>
<div className='relative'>
+2 -2
View File
@@ -5,7 +5,7 @@ export type CategoryType = {
imageUrl: string;
description: string;
parent?: string;
theme?: string;
themeId?: string;
};
export type CategoryResponseType = {
@@ -48,6 +48,7 @@ export type CategoryTreeNode = {
icon: string;
imageUrl: string;
description: string;
theme: string;
variants: number[];
hierarchy: string[];
leaf: boolean;
@@ -56,7 +57,6 @@ export type CategoryTreeNode = {
createdAt: string;
updatedAt: string;
url: string;
theme?: string;
children: CategoryTreeNode[];
};