This commit is contained in:
parent
f5e4738c2e
commit
92077cbe60
|
|
@ -2,21 +2,13 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Col, Row } from 'reactstrap';
|
import { Col, Row } from 'reactstrap';
|
||||||
import ValidationField from '../../../../Components/ValidationField/ValidationField';
|
import ValidationField from '../../../../Components/ValidationField/ValidationField';
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
|
|
||||||
import { DatePicker } from 'antd';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useGetCategories } from '../../../../api/Categories';
|
import { useGetCategories } from '../../../../api/Categories';
|
||||||
import useFormatToSelect from '../../../../Hooks/useFormatToSelect';
|
import useFormatToSelect from '../../../../Hooks/useFormatToSelect';
|
||||||
import { useGetOneAttribute } from '../../../../api/attribute';
|
|
||||||
import Atteibute from '../Atteibute';
|
|
||||||
|
|
||||||
function Form() {
|
function Form() {
|
||||||
const formik = useFormikContext<any>();
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const { data } = useGetCategories()
|
const { data } = useGetCategories()
|
||||||
const SelectData = useFormatToSelect(data?.categories)
|
const SelectData = useFormatToSelect(data?.categories)
|
||||||
const { values } = useFormikContext<any>();
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -30,10 +22,6 @@ function Form() {
|
||||||
<Col>
|
<Col>
|
||||||
<ValidationField name="parent_id" type="Search" option={SelectData} searchBy={"search"} />
|
<ValidationField name="parent_id" type="Search" option={SelectData} searchBy={"search"} />
|
||||||
<ValidationField name="photo" type="File" />
|
<ValidationField name="photo" type="File" />
|
||||||
{/* <ObjectField/> */}
|
|
||||||
{/* {values?.id &&
|
|
||||||
<Atteibute />
|
|
||||||
} */}
|
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
// AttributeValueTabs.tsx
|
// AttributeValueTabs.tsx
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Col, Row } from 'reactstrap';
|
import { Col, Label, Row } from 'reactstrap';
|
||||||
import { FormItem } from './Field/FormItem';
|
import { FormItem } from './Field/FormItem';
|
||||||
import { useFormikContext, FormikValues } from 'formik';
|
import { useFormikContext, FormikValues } from 'formik';
|
||||||
import File from './Field/File';
|
import File from './Field/File';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { ColorPicker, type ColorPickerProps, type GetProp } from 'antd';
|
||||||
|
|
||||||
interface AttributeValueTabsProps {
|
interface AttributeValueTabsProps {
|
||||||
tabKey: string;
|
tabKey: string;
|
||||||
|
|
@ -14,7 +15,7 @@ interface AttributeValueTabsProps {
|
||||||
export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKey, tabKey }) => {
|
export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKey, tabKey }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const formikContext = useFormikContext<FormikValues>();
|
const formikContext = useFormikContext<FormikValues>();
|
||||||
const { values, handleChange } = formikContext;
|
const { values, handleChange,setFieldValue } = formikContext;
|
||||||
const [valuesChanged, setvaluesChanged] = useState(values?.Attribute[parentKey]?.type)
|
const [valuesChanged, setvaluesChanged] = useState(values?.Attribute[parentKey]?.type)
|
||||||
|
|
||||||
const handleFieldChange = (fieldName: string) => (
|
const handleFieldChange = (fieldName: string) => (
|
||||||
|
|
@ -29,6 +30,13 @@ export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKe
|
||||||
}, [values?.Attribute[parentKey]?.type])
|
}, [values?.Attribute[parentKey]?.type])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type Color = GetProp<ColorPickerProps, 'value'>;
|
||||||
|
const handelchangeColor = (value: Color, hex: string)=>{
|
||||||
|
console.log(hex);
|
||||||
|
|
||||||
|
setFieldValue(`Attribute.${parentKey}.AttributeValue.${tabKey}.value_en`,hex)
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h5>{t("Value")} {tabKey}</h5>
|
<h5>{t("Value")} {tabKey}</h5>
|
||||||
|
|
@ -50,14 +58,26 @@ export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKe
|
||||||
|
|
||||||
|
|
||||||
:
|
:
|
||||||
<>
|
<div className='ValidationFiledCusom'>
|
||||||
<FormItem
|
{/* <FormItem
|
||||||
label={t(`Value`)}
|
label={t(`Value`)}
|
||||||
value={FormikName("value_en")}
|
value={FormikName("value_en")}
|
||||||
onChange={handleFieldChange('value_en')}
|
onChange={handleFieldChange('value_en')}
|
||||||
|
/> */}
|
||||||
|
<Label className="tabstext">{t("Value")} </Label>
|
||||||
|
|
||||||
|
<ColorPicker
|
||||||
|
value={FormikName("value_en")}
|
||||||
|
showText={(color:any) => <span>({color.toHexString()})</span>}
|
||||||
|
onChange={handelchangeColor}
|
||||||
|
className=' '
|
||||||
|
format='hex'
|
||||||
|
size='large'
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</>
|
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
// AttributeTabs.tsx
|
|
||||||
import React from 'react';
|
|
||||||
import { Col, Row } from 'reactstrap';
|
|
||||||
import { FormItem } from './Field/FormItem';
|
|
||||||
import { useFormikContext, FormikValues } from 'formik';
|
|
||||||
import File from './Field/File';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { TabsContainer } from '../AttributeValueTab/TabsContainer';
|
|
||||||
import SelectField from './Field/Select';
|
|
||||||
|
|
||||||
interface AttributeTabsProps {
|
|
||||||
tabKey: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AttributeTabs: React.FC<AttributeTabsProps> = ({ tabKey }) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const formikContext = useFormikContext<FormikValues>();
|
|
||||||
const { values, handleChange } = formikContext;
|
|
||||||
|
|
||||||
const handleFieldChange = (fieldName: string) => (
|
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | any
|
|
||||||
) => {
|
|
||||||
handleChange(`Attribute.${tabKey}.${fieldName}`)(e); // Prepend "Attribute"
|
|
||||||
};
|
|
||||||
const FormikName = (FormikFieldname: any) => values?.Attribute[tabKey]?.[FormikFieldname];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h5>{t("Attribute")} {tabKey}</h5>
|
|
||||||
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
|
||||||
<Col>
|
|
||||||
<FormItem
|
|
||||||
label={t(`name`)}
|
|
||||||
value={FormikName("name")}
|
|
||||||
onChange={handleFieldChange('name')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<SelectField tabKey={tabKey}/>
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
<div className='mt-3'>
|
|
||||||
<TabsContainer parentKey={tabKey} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { Button, Upload, UploadFile } from 'antd'
|
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
|
|
||||||
|
|
||||||
const File = ({ tabKey}:any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const formik = useFormikContext<any>();
|
|
||||||
const name = `Attribute[${tabKey}].${"main_photo"}`;
|
|
||||||
const imageUrl = formik?.values?.Attribute[tabKey]?.main_photo ? URL.createObjectURL(formik?.values?.Attribute[tabKey]?.main_photo) : "" ;
|
|
||||||
|
|
||||||
const fileList: UploadFile[] = [
|
|
||||||
|
|
||||||
{
|
|
||||||
uid: '-1',
|
|
||||||
name: formik?.values?.Attribute[tabKey]?.main_photo?.name ?? "",
|
|
||||||
status: 'done',
|
|
||||||
url: imageUrl ,
|
|
||||||
thumbUrl: imageUrl ,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const FilehandleChange = (value:any) => {
|
|
||||||
|
|
||||||
formik.setFieldValue(name, value.file.originFileObj)
|
|
||||||
|
|
||||||
};
|
|
||||||
const customRequest = async ({ onSuccess}: any) => {
|
|
||||||
onSuccess();
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className="ValidationField">
|
|
||||||
<label className="text">
|
|
||||||
{t(`main_photo`)}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<Upload
|
|
||||||
listType="picture"
|
|
||||||
maxCount={1}
|
|
||||||
defaultFileList={[...fileList]}
|
|
||||||
onChange={ FilehandleChange}
|
|
||||||
customRequest={customRequest}
|
|
||||||
className={`w-100`}
|
|
||||||
|
|
||||||
|
|
||||||
>
|
|
||||||
<Button className={" w-100"} icon={<UploadOutlined />}>
|
|
||||||
{ t("upload_image") }
|
|
||||||
|
|
||||||
</Button>
|
|
||||||
</Upload>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default File
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
// FormItem.tsx
|
|
||||||
import React from 'react';
|
|
||||||
import { Input, Label } from 'reactstrap';
|
|
||||||
|
|
||||||
interface FormItemProps {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
||||||
type?: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FormItem: React.FC<FormItemProps> = ({ label, value, onChange ,type = "text"}) => {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Label className="tabstext w-100">
|
|
||||||
{label}
|
|
||||||
<Input className='w-100' value={value} type={type} onChange={onChange} />
|
|
||||||
</Label>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
import { Form, Select } from 'antd'
|
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
import React from 'react'
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const SelectField = ({tabKey}: any) => {
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const formik = useFormikContext<any>();
|
|
||||||
const Formikname = `Attribute[${tabKey}].type`;
|
|
||||||
const FormikValue = formik?.values?.Attribute[tabKey]?.["type"];
|
|
||||||
|
|
||||||
const onChange = (value:any) => {
|
|
||||||
formik.setFieldValue(Formikname,value)
|
|
||||||
console.log(value);
|
|
||||||
|
|
||||||
}
|
|
||||||
const Data = [{label: "color",value :"color"},{label: "text",value :"text"},{label: "image",value :"image"}]
|
|
||||||
return (
|
|
||||||
<div className='ValidationField'>
|
|
||||||
<label className="text w-100">
|
|
||||||
{t(`${"type"}`)}
|
|
||||||
<Select
|
|
||||||
placeholder={t(`${"type"}`)}
|
|
||||||
options={Data}
|
|
||||||
size="large"
|
|
||||||
className={` w-100`}
|
|
||||||
defaultValue={FormikValue}
|
|
||||||
allowClear
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default React.memo(SelectField);
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
// TabsContainer.tsx
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Tabs, Space } from 'antd';
|
|
||||||
import { CopyOutlined, DeleteFilled } from '@ant-design/icons';
|
|
||||||
import { FormikValues, useFormikContext } from 'formik';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { AttributeTabs as AddAttributeTabs} from '../../Add/AttributeTab/AttributeTabs';
|
|
||||||
import { MdOutlineDeleteOutline } from 'react-icons/md';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const TabsContainer: React.FC = () => {
|
|
||||||
const [activeKey, setActiveKey] = useState('1');
|
|
||||||
const { setFieldValue } = useFormikContext();
|
|
||||||
const formikContext = useFormikContext<FormikValues>();
|
|
||||||
const { values } = formikContext;
|
|
||||||
const [width, setWidth] = useState(window.innerWidth);
|
|
||||||
const [t] = useTranslation()
|
|
||||||
|
|
||||||
|
|
||||||
const initialItemShape: any = {
|
|
||||||
label: `${t(`Attribute`)} 1`,
|
|
||||||
key: '1',
|
|
||||||
closable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const varianCount = values?.Attribute?.slice(1)?.map((item:any,index:any)=>{
|
|
||||||
return {
|
|
||||||
// eslint-disable-next-line no-useless-concat
|
|
||||||
label: `${t(`Attribute`)}`+ `${index+1}`,
|
|
||||||
key: index+1,
|
|
||||||
closable: true,
|
|
||||||
}
|
|
||||||
})?? initialItemShape
|
|
||||||
|
|
||||||
const [items, setItems] = useState(varianCount ?? [initialItemShape]); // Ensure items is always an array
|
|
||||||
useEffect(() => {
|
|
||||||
if (items.length > 0) {
|
|
||||||
setActiveKey(items[0].key);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
const findFirstMissingKey = (itemKeys:string[]) => {
|
|
||||||
const keysAsNumbers = itemKeys.map(Number); // Convert strings to numbers
|
|
||||||
for (let i = 1; i <= keysAsNumbers.length + 1; i++) {
|
|
||||||
if (!keysAsNumbers.includes(i)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const [nextKey, setNextKey] = useState<any>(items.map((item: any) => `${item.key}`)); // Initialize the key counter to the length of items + 1
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const keys = items.map((item: any) => `${item.key}`);
|
|
||||||
setNextKey(findFirstMissingKey(keys))
|
|
||||||
|
|
||||||
}, [items]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleAdd = () => {
|
|
||||||
|
|
||||||
const newKey = `${nextKey}`;
|
|
||||||
setItems([...items, { key: newKey, label: `${t(`Attribute`)} ${newKey}`, closable: true ,Add:true}]);
|
|
||||||
setActiveKey(newKey);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDuplicate = (targetKey: string) => {
|
|
||||||
const targetItem = items.find((item:any) => item.key === targetKey);
|
|
||||||
if (targetItem) {
|
|
||||||
const newKey = `${nextKey}`;
|
|
||||||
const newItem = { ...targetItem, key: newKey, label: `${t(`Attribute`)} ${newKey}`,Add:true };
|
|
||||||
setItems([...items, newItem]);
|
|
||||||
setActiveKey(newKey);
|
|
||||||
setNextKey((prevKey : any) => prevKey + 1);
|
|
||||||
|
|
||||||
|
|
||||||
const originalValues = values?.Attribute?.[targetKey];
|
|
||||||
const AttributeValue = originalValues?.AttributeValue?.slice(1)?.map((item:any,index:any)=>{
|
|
||||||
return {...item,id:null}
|
|
||||||
})
|
|
||||||
const newValue = { ...originalValues, id: null,AttributeValue:[{},...AttributeValue] };
|
|
||||||
|
|
||||||
console.log(newValue,"newValue");
|
|
||||||
|
|
||||||
setFieldValue(`Attribute.${newKey}`, newValue);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const [removedAttribute, setRemovedAttribute] = useState<string[]>([]);
|
|
||||||
useEffect(() => {
|
|
||||||
setFieldValue(`removedAttribute`, removedAttribute);
|
|
||||||
|
|
||||||
}, [removedAttribute,setFieldValue]);
|
|
||||||
|
|
||||||
|
|
||||||
const handleRemove = (targetKey: string) => {
|
|
||||||
const newItems = items.filter((item:any) => item.key !== targetKey);
|
|
||||||
const removedItem = values?.Attribute[targetKey] as any;
|
|
||||||
if (removedItem?.id && removedItem?.id !== null &&removedItem?.id !== 0 ) {
|
|
||||||
setRemovedAttribute((prevRemovedAttribute) => [...prevRemovedAttribute, removedItem.id]);
|
|
||||||
}
|
|
||||||
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
|
|
||||||
setItems(newItems);
|
|
||||||
setActiveKey(newActiveKey);
|
|
||||||
setFieldValue(`Attribute.${targetKey}`, undefined);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleResize = () => {
|
|
||||||
setWidth(window.innerWidth);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('resize', handleResize);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
const tabPosition = width > 1000 ? 'left' : 'top';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
|
|
||||||
<Tabs
|
|
||||||
type="editable-card"
|
|
||||||
onChange={setActiveKey}
|
|
||||||
activeKey={activeKey}
|
|
||||||
onEdit={(targetKey: any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))}
|
|
||||||
tabPosition={tabPosition}
|
|
||||||
removeIcon={<MdOutlineDeleteOutline size={20}/>}
|
|
||||||
items={items.map((item: any) => ({
|
|
||||||
label: <Space>{t(`${item.label}`)} <CopyOutlined onClick={() => handleDuplicate(item.key)} /></Space>,
|
|
||||||
// children: item?.Add ? <AddAttributeTabs tabKey={item.key} /> : <AttributeTabs tabKey={item.key} />,
|
|
||||||
children: <AddAttributeTabs tabKey={item.key}/>,
|
|
||||||
|
|
||||||
key: item.key,
|
|
||||||
closable: item.closable,
|
|
||||||
}))}
|
|
||||||
>
|
|
||||||
</Tabs>
|
|
||||||
{ items.length === 0 && (
|
|
||||||
<h6 className='AddNewTabText'>{t("Add New Attribute")}</h6>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
// AttributeValueTabs.tsx
|
|
||||||
import React from 'react';
|
|
||||||
import { Col, Row } from 'reactstrap';
|
|
||||||
import { FormItem } from './Field/FormItem';
|
|
||||||
import { useFormikContext, FormikValues } from 'formik';
|
|
||||||
import File from './Field/File';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
interface AttributeValueTabsProps {
|
|
||||||
tabKey: string;
|
|
||||||
parentKey:string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKey,tabKey }) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const formikContext = useFormikContext<FormikValues>();
|
|
||||||
const { values, handleChange } = formikContext;
|
|
||||||
|
|
||||||
const handleFieldChange = (fieldName: string) => (
|
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | any
|
|
||||||
) => {
|
|
||||||
handleChange(`Attribute.${parentKey}.AttributeValue.${tabKey}.${fieldName}`)(e); // Prepend "AttributeValue"
|
|
||||||
};
|
|
||||||
const FormikName = (FormikFieldname: any) => values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.[FormikFieldname];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h5>{t("Value")} {tabKey}</h5>
|
|
||||||
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
|
||||||
<Col>
|
|
||||||
<FormItem
|
|
||||||
label={t(`value`)}
|
|
||||||
value={FormikName("value")}
|
|
||||||
onChange={handleFieldChange('value')}
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<File parentKey={parentKey} tabKey={tabKey} />
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { Button, Upload, UploadFile } from 'antd'
|
|
||||||
import { UploadOutlined } from '@ant-design/icons';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
|
|
||||||
|
|
||||||
const File = ({ parentKey,tabKey}:any) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const formik = useFormikContext<any>();
|
|
||||||
const name = `Attribute.[${parentKey}].AttributeValue[${tabKey}].${"image"}`;
|
|
||||||
const imageUrl = formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["image"] ? URL.createObjectURL(formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["image"]) : "" ;
|
|
||||||
|
|
||||||
const fileList: UploadFile[] = [
|
|
||||||
|
|
||||||
{
|
|
||||||
uid: '-1',
|
|
||||||
name: "",
|
|
||||||
status: 'done',
|
|
||||||
url: imageUrl ,
|
|
||||||
thumbUrl: imageUrl ,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
const FilehandleChange = (value:any) => {
|
|
||||||
|
|
||||||
formik.setFieldValue(name, value.file.originFileObj)
|
|
||||||
|
|
||||||
};
|
|
||||||
const customRequest = async ({ onSuccess}: any) => {
|
|
||||||
onSuccess();
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div className="ValidationField">
|
|
||||||
<label className="text">
|
|
||||||
{t(`image`)}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<Upload
|
|
||||||
listType="picture"
|
|
||||||
maxCount={1}
|
|
||||||
defaultFileList={[...fileList]}
|
|
||||||
onChange={ FilehandleChange}
|
|
||||||
customRequest={customRequest}
|
|
||||||
className={`w-100`}
|
|
||||||
|
|
||||||
|
|
||||||
>
|
|
||||||
<Button className={" w-100"} icon={<UploadOutlined />}>
|
|
||||||
{ t("upload_image") }
|
|
||||||
|
|
||||||
</Button>
|
|
||||||
</Upload>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default File
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
// FormItem.tsx
|
|
||||||
import React from 'react';
|
|
||||||
import { Input, Label } from 'reactstrap';
|
|
||||||
|
|
||||||
interface FormItemProps {
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
||||||
type?: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FormItem: React.FC<FormItemProps> = ({ label, value, onChange ,type = "text"}) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Label className="tabstext w-100" >
|
|
||||||
{label}
|
|
||||||
<Input className='w-100' value={value} type={type} onChange={onChange} />
|
|
||||||
</Label>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
// TabsContainer.tsx
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Tabs, Space } from 'antd';
|
|
||||||
import { CopyOutlined } from '@ant-design/icons';
|
|
||||||
import { toast } from 'react-toastify';
|
|
||||||
import { FormikValues, useFormikContext } from 'formik';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { AttributeValueTabs } from './AttributeTabs';
|
|
||||||
|
|
||||||
import { AttributeValueTabs as AddAttributeValueTabs } from '../../Add/AttributeValueTab/AttributeTabs';
|
|
||||||
import { MdOutlineDeleteOutline } from 'react-icons/md';
|
|
||||||
|
|
||||||
export const TabsContainer = ({ parentKey }: any) => {
|
|
||||||
const [activeKey, setActiveKey] = useState('1');
|
|
||||||
const [t] = useTranslation()
|
|
||||||
|
|
||||||
const { setFieldValue } = useFormikContext();
|
|
||||||
const formikContext = useFormikContext<FormikValues>();
|
|
||||||
const { values, handleChange } = formikContext;
|
|
||||||
const [width, setWidth] = useState(window.innerWidth);
|
|
||||||
|
|
||||||
|
|
||||||
const initialItemShape: any = {
|
|
||||||
label: `${t(`Value`)} 1`,
|
|
||||||
key: '1',
|
|
||||||
closable: true,
|
|
||||||
};
|
|
||||||
const varianCount = values?.Attribute[parentKey]?.AttributeValue?.slice(1)?.map((item: any, index: any) => {
|
|
||||||
return {
|
|
||||||
label: `${t(`Value`)}` + `${index + 1}`,
|
|
||||||
key: index + 1,
|
|
||||||
closable: true,
|
|
||||||
}
|
|
||||||
}) ?? initialItemShape
|
|
||||||
|
|
||||||
const [items, setItems] = useState(Array.isArray(varianCount) ? varianCount : [initialItemShape]); // Ensure items is always an array
|
|
||||||
const findFirstMissingKey = (itemKeys:string[]) => {
|
|
||||||
const keysAsNumbers = itemKeys.map(Number); // Convert strings to numbers
|
|
||||||
for (let i = 1; i <= keysAsNumbers.length + 1; i++) {
|
|
||||||
if (!keysAsNumbers.includes(i)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const [nextKey, setNextKey] = useState<any>(items.map((item: any) => `${item.key}`)); // Initialize the key counter to the length of items + 1
|
|
||||||
useEffect(() => {
|
|
||||||
// Set the active key to the first tab key when the component mounts or items change
|
|
||||||
if (items.length > 0) {
|
|
||||||
setActiveKey(items[0].key);
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const keys = items.map((item: any) => `${item.key}`);
|
|
||||||
setNextKey(findFirstMissingKey(keys))
|
|
||||||
|
|
||||||
}, [items]);
|
|
||||||
const handleAdd = () => {
|
|
||||||
const newKey = `${nextKey}`;
|
|
||||||
setItems([...items, { key: newKey, label: `${t(`Value`)} ${newKey}`, closable: true,Add:true }]);
|
|
||||||
setActiveKey(newKey);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDuplicate = (targetKey: string) => {
|
|
||||||
const targetItem = items.find((item: any) => item.key === targetKey);
|
|
||||||
if (targetItem) {
|
|
||||||
const newKey = `${nextKey}`;
|
|
||||||
const newItem = { ...targetItem, key: newKey, label: `${t(`Value`)} ${newKey}`,Add:true };
|
|
||||||
setItems([...items, newItem]);
|
|
||||||
setActiveKey(newKey);
|
|
||||||
setNextKey((prevKey : any) => prevKey + 1);
|
|
||||||
|
|
||||||
|
|
||||||
const originalValues = values?.Attribute?.[parentKey]?.AttributeValue?.[targetKey];
|
|
||||||
|
|
||||||
setFieldValue(`Attribute.${parentKey}.AttributeValue.${newKey}`, {...originalValues,id:null});
|
|
||||||
console.log({...originalValues,id:null},"{...originalValues,id:null}");
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const [removedAttributeValues, setRemovedAttributeValues] = useState<string[]>([]);
|
|
||||||
useEffect(() => {
|
|
||||||
setFieldValue(`removedAttributeValue[${parentKey}]`, removedAttributeValues);
|
|
||||||
|
|
||||||
}, [removedAttributeValues]);
|
|
||||||
|
|
||||||
const handleRemove = (targetKey: string) => {
|
|
||||||
const newItems = items?.filter((item: any) => item.key !== targetKey) as any;
|
|
||||||
const removedItem = values?.Attribute?.[parentKey]?.AttributeValue?.[targetKey] as any;
|
|
||||||
console.log(removedItem?.id,"attrrubute value?.id");
|
|
||||||
|
|
||||||
if (removedItem?.id && removedItem?.id !== null &&removedItem?.id !== 0 ) {
|
|
||||||
setRemovedAttributeValues((prevRemovedAttributeValues) => [...prevRemovedAttributeValues, removedItem.id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
|
|
||||||
setItems(newItems);
|
|
||||||
setActiveKey(newActiveKey);
|
|
||||||
setFieldValue(`Attribute.${parentKey}.AttributeValue.${targetKey}`, undefined);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleResize = () => {
|
|
||||||
setWidth(window.innerWidth);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('resize', handleResize);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('resize', handleResize);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const tabPosition = 'top';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Tabs
|
|
||||||
type="editable-card"
|
|
||||||
onChange={setActiveKey}
|
|
||||||
activeKey={activeKey}
|
|
||||||
onEdit={(targetKey: any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))}
|
|
||||||
tabPosition={tabPosition}
|
|
||||||
removeIcon={<MdOutlineDeleteOutline size={20}/>}
|
|
||||||
|
|
||||||
items={
|
|
||||||
items.map((item: any) => ({
|
|
||||||
label: <Space>{t(`${item.label}`)} <CopyOutlined onClick={() => handleDuplicate(item.key)} /></Space>,
|
|
||||||
// children: item?.Add ? <AddAttributeValueTabs parentKey={parentKey} tabKey={item.key} /> : <AttributeValueTabs parentKey={parentKey} tabKey={item.key} />,
|
|
||||||
children: <AddAttributeValueTabs parentKey={parentKey} tabKey={item.key} /> ,
|
|
||||||
|
|
||||||
key: item.key,
|
|
||||||
closable: item.closable,
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
>
|
|
||||||
|
|
||||||
</Tabs>
|
|
||||||
{ items.length === 0 && (
|
|
||||||
<h6>{t("Add_New_value")}</h6>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
|
|
||||||
import React from 'react'
|
|
||||||
import { Col, Row } from 'reactstrap';
|
|
||||||
import ValidationField from '../../../../Components/ValidationField/ValidationField';
|
|
||||||
import { useFormikContext } from 'formik';
|
|
||||||
|
|
||||||
import { DatePicker } from 'antd';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useGetCategories } from '../../../../api/Categories';
|
|
||||||
import useFormatToSelect from '../../../../Hooks/useFormatToSelect';
|
|
||||||
import { useGetOneAttribute } from '../../../../api/attribute';
|
|
||||||
import Atteibute from '../Atteibute';
|
|
||||||
|
|
||||||
function Form() {
|
|
||||||
const formik = useFormikContext<any>();
|
|
||||||
const [t] = useTranslation();
|
|
||||||
const { data } = useGetCategories()
|
|
||||||
const SelectData = useFormatToSelect(data?.categories)
|
|
||||||
const { values } = useFormikContext<any>();
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
|
|
||||||
<Col>
|
|
||||||
<ValidationField name="name_ar" />
|
|
||||||
<ValidationField name="name_en" />
|
|
||||||
<ValidationField name="name_de" />
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<ValidationField name="parent_id" type="Search" option={SelectData} searchBy={"search"} />
|
|
||||||
<ValidationField name="photo" type="File" />
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Form
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -11,7 +11,7 @@ import LoadingPage from '../../../Layout/app/LoadingPage';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetOneCategories, useUpdateCategories } from '../../../api/Categories';
|
import { useGetOneCategories, useUpdateCategories } from '../../../api/Categories';
|
||||||
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
|
||||||
import { TabsContainer } from './Edit/AttributeTab/TabsContainer';
|
import { TabsContainer } from './Add/AttributeTab/TabsContainer';
|
||||||
import { useAddAttribute, useGetSingleAttribute } from '../../../api/attribute';
|
import { useAddAttribute, useGetSingleAttribute } from '../../../api/attribute';
|
||||||
import { useDeleteAttribute, useUpdateAttribute } from '../../../api/attribute';
|
import { useDeleteAttribute, useUpdateAttribute } from '../../../api/attribute';
|
||||||
import { useAddAttributeValue, useDeleteAttributeValue, useUpdateAttributeValue } from '../../../api/attributeValue';
|
import { useAddAttributeValue, useDeleteAttributeValue, useUpdateAttributeValue } from '../../../api/attributeValue';
|
||||||
|
|
|
||||||
|
|
@ -551,3 +551,12 @@ padding: 10px 40px;
|
||||||
.gomecards{
|
.gomecards{
|
||||||
min-height: 220px;
|
min-height: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ValidationFiledCusom{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
>*{
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
import useGetQueryPagination from "./helper/ueGetPagination";
|
import useGetQueryPagination from "./helper/ueGetPagination";
|
||||||
import useAddMutation from "./helper/useAddMutation"
|
import useAddMutation from "./helper/useAddMutation"
|
||||||
import useDeleteMutation from "./helper/useDeleteMutation"
|
import useDeleteMutation from "./helper/useDeleteMutation"
|
||||||
import useGetOneQuery from "./helper/useGetOneQuery";
|
|
||||||
import useGetQuery from "./helper/useGetQuery"
|
|
||||||
import useGetSingleQuery from "./helper/useGetSingleQuery";
|
import useGetSingleQuery from "./helper/useGetSingleQuery";
|
||||||
import useUpdateMutation from "./helper/useUpdateMutation";
|
import useUpdateMutation from "./helper/useUpdateMutation";
|
||||||
import useUpdateMutationById from "./helper/useUpdateMutationById";
|
import useUpdateMutationById from "./helper/useUpdateMutationById";
|
||||||
|
|
@ -17,11 +15,10 @@ const API = {
|
||||||
|
|
||||||
};
|
};
|
||||||
const KEY = "ATTRIBUTE"
|
const KEY = "ATTRIBUTE"
|
||||||
const KEY2 = "ATTRIBUTEValue"
|
const KEYS =['ATTRIBUTE', 'CATEGORIES']
|
||||||
|
|
||||||
|
export const useGetAttribute = (params?:any) => useGetQueryPagination(KEYS, API.GET_ALL,params);
|
||||||
export const useGetAttribute = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
|
// export const useGetOneAttribute = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
||||||
export const useGetOneAttribute = (params?:any) => useGetOneQuery(KEY, API.GET_ALL,params);
|
|
||||||
export const useGetSingleAttribute = (params?:any,options?:any) => useGetSingleQuery(KEY, API.GET_ALL,params,options);
|
export const useGetSingleAttribute = (params?:any,options?:any) => useGetSingleQuery(KEY, API.GET_ALL,params,options);
|
||||||
|
|
||||||
export const useAddAttribute = () => useAddMutation(KEY, API.ADD);
|
export const useAddAttribute = () => useAddMutation(KEY, API.ADD);
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,22 @@ import useAxios from './useAxios';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import useAuthState from '../../lib/state mangment/AuthState';
|
import useAuthState from '../../lib/state mangment/AuthState';
|
||||||
|
|
||||||
export default function useGetQueryPagination(KEY:string , Api: string , params:any={},options:any={}) {
|
export default function useGetQueryPagination(KEY: string | string[], Api: string, params: any = {}, options: any = {}) {
|
||||||
const axios = useAxios();
|
const axios = useAxios();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const pagination = location?.search || '';
|
const pagination = location?.search || '';
|
||||||
// console.log(params);
|
// console.log(params);
|
||||||
const {logout} = useAuthState()
|
const {logout} = useAuthState()
|
||||||
const language = localStorage.getItem("language") ?? "en"
|
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
return useQuery(
|
return useQuery(
|
||||||
[KEY, pagination], async () => {
|
[Array.isArray(KEY) ? KEY.join(',') : KEY, pagination], async () => {
|
||||||
const response = await axios.get(Api + pagination , {params});
|
const response = await axios.get(Api + pagination , {params});
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onError: (error:any) => {
|
onError: (error:any) => {
|
||||||
if(error?.response?.status == 401 || error?.response?.status == 403){
|
if(error?.response?.status === 401 || error?.response?.status === 403){
|
||||||
logout()
|
logout()
|
||||||
navigate("/auth")
|
navigate("/auth")
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user