This commit is contained in:
KarimAldeen 2024-02-21 17:43:06 +03:00
parent 82c7c0d09b
commit cd66a46088
10 changed files with 361 additions and 19 deletions

View File

@ -0,0 +1,92 @@
import React, { useEffect, useState } from 'react';
import { CloseOutlined } from '@ant-design/icons';
import { Button, Card, Form, Input, Space, Typography } from 'antd';
import { useFormikContext } from 'formik';
const ObjectField = ({value , onChange}:any) => {
const [form] = Form.useForm();
const formik = useFormikContext<any>();
const [FieldItems, setFieldItems] = useState<any>([])
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFieldItems((prevState:any) => ({
...prevState,
[name]: value
}));
formik.setFieldValue("info", FieldItems)
};
useEffect(() => {
form.setFieldsValue({
items: [{ list: [{ Attribute: '', Description: '' }] }]
});
}, []);
return (
<Form
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
form={form}
name="dynamic_form_complex"
style={{ width: '100%' }} // Set width to 100%
autoComplete="off"
>
<Form.List name="items">
{(fields, { add, remove }) => (
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
{fields.map((field, index) => (
<div key={field.key}>
<Typography.Text strong style={{ marginBottom: 8 }}>
Information
</Typography.Text>
{/* Nested Form.List for sub-items */}
<Form.Item>
<Form.List name={[field.name, 'list']}>
{(subFields, subOpt) => (
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}>
{subFields.map((subField) => (
<Space key={subField.key}>
<Form.Item noStyle name={[subField.name, 'Attribute']}>
<Input
placeholder="Attribute"
onChange={handleChange} // Assign onChange handler
name={`${subField.name}.Attribute`} // Ensure proper name for dynamic state update
/>
</Form.Item>
<Form.Item noStyle name={[subField.name, 'Description']}>
<Input
placeholder="Description"
onChange={handleChange} // Assign onChange handler
name={`${subField.name}.Description`} // Ensure proper name for dynamic state update
/>
</Form.Item>
<CloseOutlined
onClick={() => {
subOpt.remove(subField.name);
}}
/>
</Space>
))}
<Button type="dashed" onClick={() => subOpt.add()} block>
+ Add Another Item
</Button>
</div>
)}
</Form.List>
</Form.Item>
</div>
))}
</div>
)}
</Form.List>
</Form>
);
};
export default ObjectField;

View File

@ -3,7 +3,7 @@ import { CloseOutlined } from '@ant-design/icons';
import { Button, Card, Form, Input, Space, Typography } from 'antd';
import { useFormikContext } from 'formik';
const ObjectField: React.FC = () => {
const ObjectField = () => {
const [form] = Form.useForm();
const formik = useFormikContext<any>();
const [FieldItems, setFieldItems] = useState<any>([])
@ -13,6 +13,7 @@ const ObjectField: React.FC = () => {
...prevState,
[name]: value
}));
formik.setFieldValue("info", FieldItems)
};
@ -22,6 +23,7 @@ const ObjectField: React.FC = () => {
items: [{ list: [{ Attribute: '', Description: '' }] }]
});
}, []);
return (

View File

@ -0,0 +1,41 @@
import React from 'react';
import { UploadOutlined } from '@ant-design/icons';
import { Button, Upload } from 'antd';
import type { UploadFile } from 'antd';
const fileList: UploadFile[] = [
];
const App = ({value, onChange}:any) => {
const FilehandleChange = (data:any) => {
console.log('====================================');
console.log(data?.fileList);
console.log('====================================');
};
const customRequest = async ({ onSuccess}: any) => {
onSuccess();
};
return(
<>
<Upload
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
listType="picture"
maxCount={1}
defaultFileList={[...fileList]}
className="upload-list-inline"
onChange={(data:any)=>onChange(data?.fileList)}
customRequest={customRequest}
>
<Button icon={<UploadOutlined />}>Upload</Button>
</Upload>
</>
);
}
export default App;

View File

@ -0,0 +1,39 @@
import React from 'react';
import { UploadOutlined } from '@ant-design/icons';
import { Button, Upload } from 'antd';
import type { UploadFile } from 'antd';
const fileList: UploadFile[] = [
];
const App = ({value, onChange}:any) => {
const FilehandleChange = (data:any) => {
console.log('====================================');
console.log(data?.fileList);
console.log('====================================');
};
const customRequest = async ({ onSuccess}: any) => {
onSuccess();
};
return(
<>
<Upload
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
listType="picture"
defaultFileList={[...fileList]}
className="upload-list-inline"
onChange={(data:any)=>onChange(data?.fileList)}
customRequest={customRequest}
>
<Button icon={<UploadOutlined />}>Upload</Button>
</Upload>
</>
);
}
export default App;

View File

@ -1,7 +1,12 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Tabs, Space, Input } from 'antd';
import { CopyOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { Col, Row } from 'reactstrap';
import FileImage from './FileImage';
import SearchTabs from './SearchTabs';
import ObjectField from '../ObjectField';
import { useFormikContext } from 'formik';
const { TabPane } = Tabs;
@ -26,6 +31,22 @@ const App: React.FC = () => {
const onChange = (newActiveKey: string) => {
setActiveKey(newActiveKey);
};
useEffect(() => {
console.log(inputValues);
}, [inputValues])
const formikContext = useFormikContext();
const { values } :any = formikContext;
useEffect(() => {
setInputValues((prevInputValues:any) => ({
...prevInputValues,
[14]: values?.info,
}));
}, [values?.info])
const add = () => {
const newActiveKey = `${items.length + 1}`;
@ -48,12 +69,24 @@ const App: React.FC = () => {
key: newActiveKey,
label: `variable ${newActiveKey}`,
};
// Get the values of the original tab
const originalValues = inputValues[targetKey] || ['', '', '', ''];
const newPanes = [...items, newItem];
setItems(newPanes);
setActiveKey(newActiveKey);
// Update the inputValues state with the original values for the new tab
setInputValues((prevInputValues) => ({
...prevInputValues,
[newActiveKey]: originalValues,
}));
}
};
const remove = (targetKey: string) => {
let newActiveKey = activeKey;
let lastIndex = -1;
@ -127,25 +160,72 @@ interface VariableTabsProps {
onChange: (value: string[]) => void;
}
const VariableTabs: React.FC<VariableTabsProps> = ({ value, onChange } ) => {
const handleInputChange = (index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
const newValues = [...value];
newValues[index] = e.target.value;
onChange(newValues);
};
const [t] = useTranslation()
//@ts-ignore
const SelecthandleChange = (index: number) => (Selectvalue:any) => {
const newValues = [...value];
newValues[index] = Selectvalue;
onChange(newValues);
};
const FilehandleChange = (index: number) => (data:any) => {
const newValues = [...value];
newValues[index] = data;
onChange(newValues);
};
const [t] = useTranslation();
return (
<div>
<label className="text">
{t(`Name`)}
</label>
<>
<Row>
<Col>
<label className="tabstext"> {t(`Name`)} </label>
<Input value={value[0]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`Description`)} </label>
<Input value={value[1]} onChange={handleInputChange(1)} />
<Input value={value[2]} onChange={handleInputChange(2)} />
<Input value={value[3]} onChange={handleInputChange(3)} />
</div>
<SearchTabs value={value[2]} onChange={SelecthandleChange(2)} name={"color"} />
<label className="tabstext"> {t(`main_photo`)} </label>
<FileImage value={value[13]} onChange={FilehandleChange(13)} />
<label className="tabstext"> {t(`name_en`)} </label>
<Input value={value[6]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`name_ar`)} </label>
<Input value={value[7]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`name_de`)} </label>
<Input value={value[8]} onChange={handleInputChange(0)} />
<ObjectField key="14" />
</Col>
<Col>
<label className="tabstext"> {t(`Image`)} </label>
<FileImage value={value[3]} onChange={FilehandleChange(3)} />
<SearchTabs value={value[4]} onChange={SelecthandleChange(4)} name={"size"} />
<label className="tabstext"> {t(`Price`)} </label>
<Input value={value[5]} onChange={handleInputChange(5)} />
<label className="tabstext"> {t(`description_en`)} </label>
<Input value={value[9]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`description_ar`)} </label>
<Input value={value[10]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`description_de`)} </label>
<Input value={value[11]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`quantity`)} </label>
<Input value={value[12]} onChange={handleInputChange(0)} />
</Col>
</Row>
</>
);
};

View File

@ -0,0 +1,60 @@
import React from 'react';
import { Select } from 'antd';
import { useTranslation } from 'react-i18next';
interface SearchTabsProps {
value: string;
onChange:any
name:any
}
const SearchTabs: React.FC<SearchTabsProps> = ({ value, onChange ,name}) =>{
const [t] = useTranslation()
return (
<div className='SellectTab'>
<label className="tabstext"> {t(`${name}`)} </label>
<Select
showSearch
style={{ width: "100%" }}
placeholder="Search to Select"
optionFilterProp="children"
filterOption={(input, option) => (option?.label ?? '').toLowerCase().includes(input.toLowerCase())}
filterSort={(optionA, optionB) =>
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase())
}
onChange={onChange}
value={value}
options={[
{
value: '1',
label: 'label 1',
},
{
value: '2',
label: 'label 2',
},
{
value: '3',
label: 'label 3',
},
{
value: '4',
label: 'label 4',
},
{
value: '5',
label: 'label 5',
},
{
value: '6',
label: 'label 6',
},
]}
/>
</div>
);
}
export default SearchTabs;

View File

@ -0,0 +1,9 @@
import React from 'react'
const VariableTabs = () => {
return (
<div>VariableTabs</div>
)
}
export default VariableTabs

View File

@ -21,6 +21,7 @@ export const getInitialValues = (objectToEdit: any | null = null) => {
images:objectToEdit?.images??"",
category_id:objectToEdit?.category_id??1,
variable:[],
info : []
}
};

View File

@ -362,13 +362,14 @@ background: var(--bg);
border-radius: 20px;
}
.SingleInfo{
svg{
color: green !important;
}
}
.ResposiveTabs{
padding-block: 20px;
min-height: 300px;
min-height: 500px;
}
/* Ant tabs tab active */
.ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab-active{
@ -383,7 +384,24 @@ background: var(--bg);
}
.ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab{
align-self: center !important;
padding: 10px 40px;
}
.VarianInfo{
padding: 10px 70px;
}
.react-tabs__tab-panel--selected .mt-4 .VarianInfo .ant-tabs-editable .ant-tabs-content-holder .ant-tabs-content .ant-tabs-tabpane .row .col .ant-upload-wrapper .ant-upload-select .ant-upload .ant-btn{
width:100% !important;
}
.tabstext{
margin-bottom: 10px;
}
.SellectTab{
display: flex;
flex-direction: column;
width: 100%;
}