change category by theme
This commit is contained in:
@@ -9,7 +9,6 @@ import Textarea from '../../components/Textarea'
|
|||||||
import UploadBox from '../../components/UploadBox'
|
import UploadBox from '../../components/UploadBox'
|
||||||
import Select from '../../components/Select'
|
import Select from '../../components/Select'
|
||||||
import { type CategoryType, type CategoryTreeNode } from './types/Types'
|
import { type CategoryType, type CategoryTreeNode } from './types/Types'
|
||||||
import { CategoryThemeEnum } from './enum/Enum'
|
|
||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { useCreateCategory, useGetCategories, useSingleUpload } from './hooks/useCategoryData'
|
import { useCreateCategory, useGetCategories, useSingleUpload } from './hooks/useCategoryData'
|
||||||
@@ -17,10 +16,12 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { Pages } from '../../config/Pages'
|
import { Pages } from '../../config/Pages'
|
||||||
import { extractErrorMessage } from '@/helpers/utils'
|
import { extractErrorMessage } from '@/helpers/utils'
|
||||||
|
import { useGetThemes } from '../theme/hooks/useThemeData'
|
||||||
|
|
||||||
const CreateCategory: FC = () => {
|
const CreateCategory: FC = () => {
|
||||||
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const getThemes = useGetThemes()
|
||||||
const [iconFile, setIconFile] = useState<File>()
|
const [iconFile, setIconFile] = useState<File>()
|
||||||
const [imageFile, setImageFile] = useState<File>()
|
const [imageFile, setImageFile] = useState<File>()
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
@@ -38,14 +39,14 @@ const CreateCategory: FC = () => {
|
|||||||
imageUrl: '',
|
imageUrl: '',
|
||||||
description: '',
|
description: '',
|
||||||
parent: undefined,
|
parent: undefined,
|
||||||
theme: '',
|
themeId: undefined,
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
title_fa: Yup.string().required('عنوان فارسی دسته الزامی است'),
|
title_fa: Yup.string().required('عنوان فارسی دسته الزامی است'),
|
||||||
title_en: Yup.string().required('عنوان انگلیسی دسته الزامی است'),
|
title_en: Yup.string().required('عنوان انگلیسی دسته الزامی است'),
|
||||||
description: Yup.string().required('توضیحات دسته الزامی است'),
|
description: Yup.string().required('توضیحات دسته الزامی است'),
|
||||||
parent: Yup.string().optional(),
|
parent: Yup.string().optional(),
|
||||||
theme: Yup.string().optional(),
|
themeId: Yup.string().optional(),
|
||||||
}),
|
}),
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
|
|
||||||
@@ -76,12 +77,21 @@ const CreateCategory: FC = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const categoriesData: CategoryTreeNode[] = getCategories.data?.results?.data || []
|
const categoriesData: CategoryTreeNode[] = getCategories.data?.results?.data || []
|
||||||
|
const themesData = getThemes.data?.results?.data || []
|
||||||
|
|
||||||
const filteredCategories = categoriesData.filter(cat =>
|
const filteredCategories = categoriesData.filter(cat =>
|
||||||
cat.title_fa.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
cat.title_fa.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||||
cat.title_en.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) => {
|
const handleParentSelect = (category: CategoryTreeNode) => {
|
||||||
formik.setFieldValue('parent', category._id)
|
formik.setFieldValue('parent', category._id)
|
||||||
}
|
}
|
||||||
@@ -142,15 +152,10 @@ const CreateCategory: FC = () => {
|
|||||||
<Select
|
<Select
|
||||||
label='تم دسته'
|
label='تم دسته'
|
||||||
placeholder='انتخاب تم دسته'
|
placeholder='انتخاب تم دسته'
|
||||||
items={[
|
items={themeItems}
|
||||||
{ value: CategoryThemeEnum.Sized, label: 'سایز' },
|
value={formik.values.themeId || ''}
|
||||||
{ value: CategoryThemeEnum.Colored, label: 'رنگ' },
|
onChange={(e) => formik.setFieldValue('themeId', e.target.value || undefined)}
|
||||||
{ value: CategoryThemeEnum.Meterage, label: 'متراژ' },
|
error_text={formik.touched.themeId && formik.errors.themeId ? formik.errors.themeId : ''}
|
||||||
{ 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 : ''}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -73,11 +73,6 @@ const CategoryList: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
<Td text={category.description} />
|
<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="">
|
<Td text="">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{category.leaf ? <Link to={`${Pages.category.attributes}${category._id}`}>
|
{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={'توضیحات'} />
|
||||||
<Td text={'تنوع'} />
|
|
||||||
<Td text={'ویژگیها'} />
|
<Td text={'ویژگیها'} />
|
||||||
<Td text={'عملیات'} />
|
<Td text={'عملیات'} />
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import Textarea from '../../components/Textarea'
|
|||||||
import UploadBox from '../../components/UploadBox'
|
import UploadBox from '../../components/UploadBox'
|
||||||
import Select from '../../components/Select'
|
import Select from '../../components/Select'
|
||||||
import { type CategoryType, type CategoryTreeNode } from './types/Types'
|
import { type CategoryType, type CategoryTreeNode } from './types/Types'
|
||||||
import { CategoryThemeEnum } from './enum/Enum'
|
|
||||||
import { useFormik } from 'formik'
|
import { useFormik } from 'formik'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { useUpdateCategory, useGetCategories, useGetCategoryById, useSingleUpload } from './hooks/useCategoryData'
|
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 { toast } from 'react-toastify'
|
||||||
import { Pages } from '../../config/Pages'
|
import { Pages } from '../../config/Pages'
|
||||||
import { extractErrorMessage } from '@/helpers/utils'
|
import { extractErrorMessage } from '@/helpers/utils'
|
||||||
|
import { useGetThemes } from '../theme/hooks/useThemeData'
|
||||||
|
|
||||||
const UpdateCategory: FC = () => {
|
const UpdateCategory: FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
|
const getThemes = useGetThemes()
|
||||||
const [iconFile, setIconFile] = useState<File>()
|
const [iconFile, setIconFile] = useState<File>()
|
||||||
const [imageFile, setImageFile] = useState<File>()
|
const [imageFile, setImageFile] = useState<File>()
|
||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
@@ -41,14 +42,14 @@ const UpdateCategory: FC = () => {
|
|||||||
imageUrl: '',
|
imageUrl: '',
|
||||||
description: '',
|
description: '',
|
||||||
parent: undefined,
|
parent: undefined,
|
||||||
theme: '',
|
themeId: undefined,
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object({
|
validationSchema: Yup.object({
|
||||||
title_fa: Yup.string().required('عنوان فارسی دسته الزامی است'),
|
title_fa: Yup.string().required('عنوان فارسی دسته الزامی است'),
|
||||||
title_en: Yup.string().required('عنوان انگلیسی دسته الزامی است'),
|
title_en: Yup.string().required('عنوان انگلیسی دسته الزامی است'),
|
||||||
description: Yup.string().required('توضیحات دسته الزامی است'),
|
description: Yup.string().required('توضیحات دسته الزامی است'),
|
||||||
parent: Yup.string().optional(),
|
parent: Yup.string().optional(),
|
||||||
theme: Yup.string().optional(),
|
themeId: Yup.string().optional(),
|
||||||
}),
|
}),
|
||||||
onSubmit: async (values) => {
|
onSubmit: async (values) => {
|
||||||
const updatedValues = { ...values }
|
const updatedValues = { ...values }
|
||||||
@@ -91,7 +92,7 @@ const UpdateCategory: FC = () => {
|
|||||||
imageUrl: categoryData.imageUrl || '',
|
imageUrl: categoryData.imageUrl || '',
|
||||||
description: categoryData.description || '',
|
description: categoryData.description || '',
|
||||||
parent: categoryData.parent || undefined,
|
parent: categoryData.parent || undefined,
|
||||||
theme: categoryData.theme || '',
|
themeId: categoryData.theme || undefined,
|
||||||
})
|
})
|
||||||
setIsActive(!categoryData.deleted)
|
setIsActive(!categoryData.deleted)
|
||||||
setIsDataLoaded(true)
|
setIsDataLoaded(true)
|
||||||
@@ -100,6 +101,15 @@ const UpdateCategory: FC = () => {
|
|||||||
}, [getCategoryById.data, isDataLoaded])
|
}, [getCategoryById.data, isDataLoaded])
|
||||||
|
|
||||||
const categoriesData: CategoryTreeNode[] = getCategories.data?.results?.data || []
|
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 =>
|
const filteredCategories = categoriesData.filter(cat =>
|
||||||
@@ -193,15 +203,10 @@ const UpdateCategory: FC = () => {
|
|||||||
<Select
|
<Select
|
||||||
label='تم دسته'
|
label='تم دسته'
|
||||||
placeholder='انتخاب تم دسته'
|
placeholder='انتخاب تم دسته'
|
||||||
items={[
|
items={themeItems}
|
||||||
{ value: CategoryThemeEnum.Sized, label: 'سایز' },
|
value={formik.values.themeId || ''}
|
||||||
{ value: CategoryThemeEnum.Colored, label: 'رنگ' },
|
onChange={(e) => formik.setFieldValue('themeId', e.target.value || undefined)}
|
||||||
{ value: CategoryThemeEnum.Meterage, label: 'متراژ' },
|
error_text={formik.touched.themeId && formik.errors.themeId ? formik.errors.themeId : ''}
|
||||||
{ 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 : ''}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -263,6 +268,28 @@ const UpdateCategory: FC = () => {
|
|||||||
<div className='text-sm bg-white py-6 px-4 rounded-2xl'>
|
<div className='text-sm bg-white py-6 px-4 rounded-2xl'>
|
||||||
<h2 className='text-lg font-medium mb-4'>انتخاب دسته والد</h2>
|
<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='mb-4'>
|
||||||
<div className='relative'>
|
<div className='relative'>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export type CategoryType = {
|
|||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
description: string;
|
description: string;
|
||||||
parent?: string;
|
parent?: string;
|
||||||
theme?: string;
|
themeId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CategoryResponseType = {
|
export type CategoryResponseType = {
|
||||||
@@ -48,6 +48,7 @@ export type CategoryTreeNode = {
|
|||||||
icon: string;
|
icon: string;
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
theme: string;
|
||||||
variants: number[];
|
variants: number[];
|
||||||
hierarchy: string[];
|
hierarchy: string[];
|
||||||
leaf: boolean;
|
leaf: boolean;
|
||||||
@@ -56,7 +57,6 @@ export type CategoryTreeNode = {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
url: string;
|
url: string;
|
||||||
theme?: string;
|
|
||||||
children: CategoryTreeNode[];
|
children: CategoryTreeNode[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user