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

@ -18,7 +18,7 @@ const BasicInfo = ({setIsValed}:any) => {
console.log(values); console.log(values);
} }
}, [isValid,values]); }, [isValid,values]);
return ( return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
@ -30,7 +30,7 @@ const BasicInfo = ({setIsValed}:any) => {
<Col> <Col>
<KarimField name="main_photo" type='File' /> <KarimField name="main_photo" type='File' />
<KarimField name="category_id" type='Select' option={[]} label='category' placeholder='category' /> <KarimField name="category_id" type='Select' option={[]} label='category' placeholder='category' />
</Col> </Col>

View File

@ -3,7 +3,7 @@ import { CloseOutlined } from '@ant-design/icons';
import { Button, Card, Form, Input, Space, Typography } from 'antd'; import { Button, Card, Form, Input, Space, Typography } from 'antd';
import { useFormikContext } from 'formik'; import { useFormikContext } from 'formik';
const ObjectField: React.FC = () => { const ObjectField = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const [FieldItems, setFieldItems] = useState<any>([]) const [FieldItems, setFieldItems] = useState<any>([])
@ -13,8 +13,9 @@ const ObjectField: React.FC = () => {
...prevState, ...prevState,
[name]: value [name]: value
})); }));
formik.setFieldValue("info", FieldItems) formik.setFieldValue("info", FieldItems)
}; };
useEffect(() => { useEffect(() => {
@ -22,6 +23,7 @@ const ObjectField: React.FC = () => {
items: [{ list: [{ Attribute: '', Description: '' }] }] items: [{ list: [{ Attribute: '', Description: '' }] }]
}); });
}, []); }, []);
return ( 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 { Tabs, Space, Input } from 'antd';
import { CopyOutlined } from '@ant-design/icons'; import { CopyOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next'; 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; const { TabPane } = Tabs;
@ -26,6 +31,22 @@ const App: React.FC = () => {
const onChange = (newActiveKey: string) => { const onChange = (newActiveKey: string) => {
setActiveKey(newActiveKey); 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 add = () => {
const newActiveKey = `${items.length + 1}`; const newActiveKey = `${items.length + 1}`;
@ -48,11 +69,23 @@ const App: React.FC = () => {
key: newActiveKey, key: newActiveKey,
label: `variable ${newActiveKey}`, label: `variable ${newActiveKey}`,
}; };
// Get the values of the original tab
const originalValues = inputValues[targetKey] || ['', '', '', ''];
const newPanes = [...items, newItem]; const newPanes = [...items, newItem];
setItems(newPanes); setItems(newPanes);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
// Update the inputValues state with the original values for the new tab
setInputValues((prevInputValues) => ({
...prevInputValues,
[newActiveKey]: originalValues,
}));
} }
}; };
const remove = (targetKey: string) => { const remove = (targetKey: string) => {
let newActiveKey = activeKey; let newActiveKey = activeKey;
@ -127,25 +160,72 @@ interface VariableTabsProps {
onChange: (value: string[]) => void; onChange: (value: string[]) => void;
} }
const VariableTabs: React.FC<VariableTabsProps> = ({ value, onChange }) => {
const VariableTabs: React.FC<VariableTabsProps> = ({ value, onChange } ) => {
const handleInputChange = (index: number) => (e: React.ChangeEvent<HTMLInputElement>) => { const handleInputChange = (index: number) => (e: React.ChangeEvent<HTMLInputElement>) => {
const newValues = [...value]; const newValues = [...value];
newValues[index] = e.target.value; newValues[index] = e.target.value;
onChange(newValues); 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 ( return (
<div> <>
<label className="text"> <Row>
{t(`Name`)} <Col>
</label> <label className="tabstext"> {t(`Name`)} </label>
<Input value={value[0]} onChange={handleInputChange(0)} /> <Input value={value[0]} onChange={handleInputChange(0)} />
<label className="tabstext"> {t(`Description`)} </label>
<Input value={value[1]} onChange={handleInputChange(1)} /> <Input value={value[1]} onChange={handleInputChange(1)} />
<Input value={value[2]} onChange={handleInputChange(2)} /> <SearchTabs value={value[2]} onChange={SelecthandleChange(2)} name={"color"} />
<Input value={value[3]} onChange={handleInputChange(3)} /> <label className="tabstext"> {t(`main_photo`)} </label>
</div>
<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??"", images:objectToEdit?.images??"",
category_id:objectToEdit?.category_id??1, category_id:objectToEdit?.category_id??1,
variable:[], variable:[],
info : []
} }
}; };

View File

@ -362,13 +362,14 @@ background: var(--bg);
border-radius: 20px; border-radius: 20px;
} }
.SingleInfo{ .SingleInfo{
svg{ svg{
color: green !important; color: green !important;
} }
} }
.ResposiveTabs{ .ResposiveTabs{
padding-block: 20px; padding-block: 20px;
min-height: 300px; min-height: 500px;
} }
/* Ant tabs tab active */ /* Ant tabs tab active */
.ant-tabs-nav-wrap .ant-tabs-nav-list .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{ .ant-tabs-nav-wrap .ant-tabs-nav-list .ant-tabs-tab{
align-self: center !important; 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%;
}