This commit is contained in:
KarimAldeen 2024-03-05 11:35:35 +03:00
parent 7fa5a79391
commit c47ea73fdb
114 changed files with 2067 additions and 2860 deletions

View File

@ -3,7 +3,7 @@ import React from 'react'
import useFormField from '../../../Hooks/useFormField'; import useFormField from '../../../Hooks/useFormField';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
const Date = ({ name, label,picker="date" ,isDisabled,props,onChange,placeholder ,className}: any) => { const Date = ({ name, label,picker="date" ,isDisabled,props,onChange,placeholder ,className,Format}: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props) const { errorMsg, isError, t, formik } = useFormField(name, props)
const onCalendarChange = (value: any) => { const onCalendarChange = (value: any) => {
@ -15,7 +15,7 @@ const Date = ({ name, label,picker="date" ,isDisabled,props,onChange,placeholder
<div className='ValidationField'> <div className='ValidationField'>
<label htmlFor={name} className="text"> <label htmlFor={name} className="text">
{t(`${label}`)} {t(`${label ? label : name}`)}
</label> </label>
<Form.Item <Form.Item
hasFeedback hasFeedback
@ -31,6 +31,7 @@ const Date = ({ name, label,picker="date" ,isDisabled,props,onChange,placeholder
size="large" size="large"
onChange={onChange || onCalendarChange} onChange={onChange || onCalendarChange}
disabled={isDisabled} disabled={isDisabled}
format={Format ?? ""}
/> />

View File

@ -1,11 +1,13 @@
import { Form, Select } from 'antd'; import { Form, Select } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import useFormField from '../../../Hooks/useFormField'; import useFormField from '../../../Hooks/useFormField';
import { useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
const SearchField = ({ name, label, placeholder, isDisabled, searchBy, option, isMulti, onChange, className, props }: any) => { const SearchField = ({ name, label, placeholder, isDisabled, searchBy, option, isMulti, onChange, className, props }: any) => {
const { errorMsg, isError, t, formik } = useFormField(name, props); const { errorMsg, isError, t, formik } = useFormField(name, props);
const [searchQuery, setSearchQuery] = useState<string>(''); const [searchQuery, setSearchQuery] = useState<string>('');
const location = useLocation()
const navigate = useNavigate() const navigate = useNavigate()
useEffect(() => { useEffect(() => {
const searchParams = new URLSearchParams(window?.location?.search); const searchParams = new URLSearchParams(window?.location?.search);
@ -17,9 +19,16 @@ const SearchField = ({ name, label, placeholder, isDisabled, searchBy, option, i
const SelecthandleChange = (value: { value: string; label: React.ReactNode }) => { const SelecthandleChange = (value: { value: string; label: React.ReactNode }) => {
formik?.setFieldValue(name, value); formik?.setFieldValue(name, value);
console.log(value);
}; };
const SearchHandleChange = (value:any) => { const SearchHandleChange = (value:any) => {
navigate(`${window?.location?.pathname}?${searchBy}=${value}`, { replace: true }); if (value || value !== "") {
navigate(`${window?.location?.pathname}?${searchBy}=${value}`, { replace: true });
} else {
const params = new URLSearchParams(location.search);
params.delete(searchBy ?? "search");
navigate(`${window?.location.pathname}?${params.toString()}`, { replace: true });
}
}; };

View File

@ -25,7 +25,7 @@ const SelectField = ({ name, label, placeholder, isDisabled,option,isMulti,onCha
options={option} options={option}
size="large" size="large"
className={`${className} w-100`} className={`${className} w-100`}
defaultValue={formik.values[name]} defaultValue={formik.values?.name}
allowClear allowClear
{...(isMulti && { mode: "multiple" })} {...(isMulti && { mode: "multiple" })}
onChange={onChange || SelecthandleChange} onChange={onChange || SelecthandleChange}

View File

@ -33,7 +33,7 @@
label?: string; label?: string;
className?: string; className?: string;
isDisabled?: boolean; isDisabled?: boolean;
onChange?: (value: any) => void; onChange?:any;
dir?:'ltr' | "rtl"; dir?:'ltr' | "rtl";
option: any[]; option: any[];
isMulti?: boolean; isMulti?: boolean;
@ -75,6 +75,8 @@
onChange?: (value: any) => void; onChange?: (value: any) => void;
dir?:'ltr' | "rtl" dir?:'ltr' | "rtl"
picker?: "data" | "week" | "month" | "quarter" | "year"; picker?: "data" | "week" | "month" | "quarter" | "year";
Format?: "YYYY/MM/DD" | "MM/DD" | "YYYY/MM" | "YYYY-MM-DD HH:mm:ss.SSS" | "YYYY-MM-DD HH:MM:SS";
} }

View File

@ -0,0 +1,13 @@
export async function fetchImage(imageUrl:any) {
try {
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error(`Failed to fetch image: ${response.status} ${response.statusText}`);
}
const blob = await response.blob();
return new File([blob], 'image.png', { type: 'image/png' });
} catch (error) {
console.error('Error fetching image:', error);
return null;
}
}

View File

@ -1,9 +1,11 @@
const useFormatToSelect = (Data : any) => { const useFormatToSelect = (Data : any) => {
const format = (data :any) => { const format = (data :any) => {
if (!data) return []; if (!data) return [];
const language = localStorage.getItem("language") ?? "en";
return data.map((item :any) => ({ return data.map((item :any) => ({
value: item?.id, value: item?.id,
label: item?.name, label: item?.name[language],
})); }));
}; };

View File

@ -5,25 +5,34 @@ import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
const { Search } = Input; const { Search } = Input;
const SearchField = ({searchBy } : any) => { const SearchField = ({ searchBy }: any) => {
const navigate = useNavigate() const navigate = useNavigate()
const [searchParams,] = useSearchParams(); const [searchParams,] = useSearchParams();
const location =useLocation() const location = useLocation()
const {t} = useTranslation(); const { t } = useTranslation();
console.log(searchBy,"searchBy");
const [searchValue, setSearchValue] = useState(searchParams.get(searchBy ?? "search") || "");
const [searchValue, setSearchValue] = useState(searchParams.get('search')|| "");
const onSearch: SearchProps['onSearch'] = (value, _e, info) => { const onSearch: SearchProps['onSearch'] = (value, _e, info) => {
// console.log(value); if (value || value !== "") {
navigate(`${location?.pathname}?${searchBy ?? "search"}=${value}`, { replace: true });
navigate(`${location?.pathname}?${searchBy ?? "search"}=${value}`, { replace: true }); } else {
const params = new URLSearchParams(location.search);
params.delete(searchBy ?? "search");
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}
} }
const onChange = (e :any) => {
setSearchValue(e.target.value);
} const onChange = (e: any) => {
const value = e.target.value
setSearchValue(e.target.value);
if (value === "") {
const params = new URLSearchParams(location.search);
params.delete(searchBy ?? "search");
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}
}
return ( return (
@ -33,12 +42,12 @@ const SearchField = ({searchBy } : any) => {
allowClear allowClear
enterButton={t("search")} enterButton={t("search")}
size="middle" size="middle"
placeholder={t("search")} placeholder={t(searchBy ?? "search")}
onSearch={onSearch} onSearch={onSearch}
style={{ width: 250 }} style={{ width: 250 }}
value={searchValue} value={searchValue}
onChange={onChange} onChange={onChange}
/> />
</div> </div>
) )

View File

@ -30,7 +30,7 @@ const ViewPage: React.FC<TViewPage>= ({children,getInitialValues, getValidation
<CardTitle className="View_information"> <CardTitle className="View_information">
{t("View_information")} {t("View_information")}
</CardTitle> </CardTitle>
<Button onClick={() => { navigate(-1);}}> {t("back")} </Button> <Button onClick={() => { navigate(-1);}}> {t("back")} </Button>
</CardHeader> </CardHeader>
<CardBody> <CardBody>
{ {

View File

@ -28,7 +28,7 @@ export const AttributeTabs: React.FC<AttributeTabsProps> = ({ tabKey }) => {
return ( return (
<> <>
<h5>{t("Attributes")} {tabKey}</h5> <h5>{t("Attribute")} {tabKey}</h5>
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<FormItem <FormItem

View File

@ -33,11 +33,9 @@ const File = ({ tabKey}:any) => {
}; };
return ( return (
<div className="ValidationField"> <div className="ValidationField">
<label className="text"> <label className="text w-100">
{t(`main_photo`)} {t(`main_photo`)}
</label> <Upload
<Upload
listType="picture" listType="picture"
maxCount={1} maxCount={1}
defaultFileList={[...fileList]} defaultFileList={[...fileList]}
@ -52,6 +50,9 @@ const File = ({ tabKey}:any) => {
</Button> </Button>
</Upload> </Upload>
</label>

View File

@ -13,7 +13,7 @@ export const FormItem: React.FC<FormItemProps> = ({ label, value, onChange ,type
return ( return (
<> <>
<Label className="tabstext">{label}</Label> <Label className="tabstext">{label}</Label>
<Input value={value} type={type} onChange={onChange} /> <Input value={value} type={type} onChange={onChange} />
</> </>
); );
}; };

View File

@ -13,16 +13,16 @@ const SelectField = ({tabKey}: any) => {
const onChange = (value:any) => { const onChange = (value:any) => {
formik.setFieldValue(Formikname,value) formik.setFieldValue(Formikname,value)
console.log(value); console.log(value);
console.log(formik?.errors,"errors");
} }
const Data = [{label: "color",value :"color"},{label: "text",value :"text"},{label: "image",value :"image"}] const Data = [{label: "color",value :"color"},{label: "text",value :"text"},{label: "image",value :"image"}]
return ( return (
<div className='ValidationField'> <div className='ValidationField'>
<label className="text"> <label className="text w-100">
{t(`${"type"}`)} {t(`${"type"}`)}
</label> <Select
<Select
placeholder={t(`${"type"}`)} placeholder={t(`${"type"}`)}
options={Data} options={Data}
size="large" size="large"
@ -30,10 +30,10 @@ const SelectField = ({tabKey}: any) => {
defaultValue={FormikValue} defaultValue={FormikValue}
allowClear allowClear
onChange={onChange} onChange={onChange}
/> />
</label>
</div> </div>
) )
} }

View File

@ -6,56 +6,103 @@ import { toast } from 'react-toastify';
import { FormikValues, useFormikContext } from 'formik'; import { FormikValues, useFormikContext } from 'formik';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { AttributeTabs } from './AttributeTabs'; import { AttributeTabs } from './AttributeTabs';
import { AttributeTabs as AddAttributeTabs} from '../../Add/AttributeTab/AttributeTabs';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const initialItemShape: any = {
label: 'Attribute 1',
key: '1',
closable: true,
};
export const TabsContainer: React.FC = () => { export const TabsContainer: React.FC = () => {
const [activeKey, setActiveKey] = useState('1'); const [activeKey, setActiveKey] = useState('1');
const [items, setItems] = useState([initialItemShape]);
const { setFieldValue } = useFormikContext(); const { setFieldValue } = useFormikContext();
const formikContext = useFormikContext<FormikValues>(); const formikContext = useFormikContext<FormikValues>();
const { values, handleChange } = formikContext; const { values, handleChange } = formikContext;
const [width, setWidth] = useState(window.innerWidth); const [width, setWidth] = useState(window.innerWidth);
const [t] = useTranslation() 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 {
label: `${t(`Attribute`)}`+ `${index+1}`,
key: index+1,
closable: true,
}
})?? initialItemShape
const [items, setItems] = useState(varianCount ?? [initialItemShape]); // Ensure items is always an array
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);
}
}, []);
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 handleAdd = () => {
const newKey = `${items.length + 1}`;
setItems([...items, { key: newKey, label: `Attribute ${newKey}`, closable: true }]); const newKey = `${nextKey}`;
setItems([...items, { key: newKey, label: `${t(`Attribute`)} ${newKey}`, closable: true ,Add:true}]);
setActiveKey(newKey); setActiveKey(newKey);
}; };
const handleDuplicate = (targetKey: string) => { const handleDuplicate = (targetKey: string) => {
const targetItem = items.find((item) => item.key === targetKey); const targetItem = items.find((item:any) => item.key === targetKey);
if (targetItem) { if (targetItem) {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
const newItem = { ...targetItem, key: newKey, label: `Attribute ${newKey}` }; const newItem = { ...targetItem, key: newKey, label: `${t(`Attribute`)} ${newKey}`,Add:true };
setItems([...items, newItem]); setItems([...items, newItem]);
setActiveKey(newKey); setActiveKey(newKey);
setNextKey((prevKey : any) => prevKey + 1);
const originalValues = values?.Attribute?.[targetKey]; const originalValues = values?.Attribute?.[targetKey];
setFieldValue(`Attribute.${newKey}`, originalValues);
setFieldValue(`Attribute.${newKey}`, {...originalValues,id:null});
} }
}; };
const [removedAttribute, setRemovedAttribute] = useState<string[]>([]);
useEffect(() => {
setFieldValue(`removedAttribute`, removedAttribute);
}, [removedAttribute]);
const handleRemove = (targetKey: string) => { const handleRemove = (targetKey: string) => {
const newItems = items.filter((item) => item.key !== targetKey); const newItems = items.filter((item:any) => item.key !== targetKey);
if (newItems.length > 0) { const removedItem = values?.Attribute[targetKey] as any;
if (removedItem?.id) {
setRemovedAttribute((prevRemovedAttribute) => [...prevRemovedAttribute, removedItem.id]);
}
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1'; const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
setItems(newItems); setItems(newItems);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
setFieldValue(`Attribute.${targetKey}`, undefined); setFieldValue(`Attribute.${targetKey}`, undefined);
} else {
toast.error("Cannot close the last tab");
}
}; };
useEffect(() => { useEffect(() => {
@ -72,31 +119,27 @@ useEffect(() => {
const tabPosition = width > 1000 ? 'left' : 'top'; const tabPosition = width > 1000 ? 'left' : 'top';
return ( return (
<Tabs <div className=''>
type="editable-card"
onChange={setActiveKey} <Tabs
activeKey={activeKey} type="editable-card"
onEdit={(targetKey:any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))} onChange={setActiveKey}
tabPosition={tabPosition} activeKey={activeKey}
onEdit={(targetKey: any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))}
tabPosition={tabPosition}
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,
{items.map((item :any) =>{ closable: item.closable,
return ( }))}
>
<TabPane </Tabs>
key={item?.key} { items.length === 0 && (
tab={ <h6 className='AddNewTabText'>{t("Add New Attribute")}</h6>
<Space> )}
{t(`${item.label}`)} </div>
<CopyOutlined onClick={() => handleDuplicate(item.key)} />
</Space>
}
closable={item.closable}
>
<AttributeTabs tabKey={item?.key} />
</TabPane>
)
})}
</Tabs>
); );
}; };

View File

@ -1,5 +1,5 @@
// AttributeValueTabs.tsx // AttributeValueTabs.tsx
import React from 'react'; import React, { useEffect, useState } from 'react';
import { Col, Row } from 'reactstrap'; import { Col, Row } from 'reactstrap';
import { FormItem } from './Field/FormItem'; import { FormItem } from './Field/FormItem';
import { useFormikContext, FormikValues } from 'formik'; import { useFormikContext, FormikValues } from 'formik';
@ -8,13 +8,14 @@ import { useTranslation } from 'react-i18next';
interface AttributeValueTabsProps { interface AttributeValueTabsProps {
tabKey: string; tabKey: string;
parentKey:string parentKey: string
} }
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 } = formikContext;
const [valuesChanged, setvaluesChanged] = useState(values?.Attribute[parentKey]?.type)
const handleFieldChange = (fieldName: string) => ( const handleFieldChange = (fieldName: string) => (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | any e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | any
@ -22,41 +23,72 @@ export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKe
handleChange(`Attribute.${parentKey}.AttributeValue.${tabKey}.${fieldName}`)(e); // Prepend "AttributeValue" handleChange(`Attribute.${parentKey}.AttributeValue.${tabKey}.${fieldName}`)(e); // Prepend "AttributeValue"
}; };
const FormikName = (FormikFieldname: any) => values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.[FormikFieldname]; const FormikName = (FormikFieldname: any) => values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.[FormikFieldname];
useEffect(() => {
setvaluesChanged(values?.Attribute[parentKey]?.type)
}, [values?.Attribute[parentKey]?.type])
return ( return (
<> <>
<h5>{t("Values")} {tabKey}</h5> <h5>{t("Value")} {tabKey}</h5>
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<FormItem {valuesChanged !== "color" ?
label={t(`value_en`)} <>
value={FormikName("value_en")} <FormItem
onChange={handleFieldChange('value_en')} label={t(`value_en`)}
/> value={FormikName("value_en")}
<FormItem onChange={handleFieldChange('value_en')}
label={t(`value_ar`)} />
value={FormikName("value_ar")} <FormItem
onChange={handleFieldChange('value_ar')} label={t(`value_ar`)}
/> value={FormikName("value_ar")}
onChange={handleFieldChange('value_ar')}
/>
</>
:
<>
<FormItem
label={t(`Value`)}
value={FormikName("value_en")}
onChange={handleFieldChange('value_en')}
/>
</>
}
</Col> </Col>
<Col> <Col>
{valuesChanged !== "color" ?
<FormItem <>
label={t(`value_de`)}
value={FormikName("value_de")} <FormItem
onChange={handleFieldChange('value_de')} label={t(`value_de`)}
value={FormikName("value_de")}
onChange={handleFieldChange('value_de')}
/>
</>
:
<>
</>
}
<File parentKey={parentKey} tabKey={tabKey} />
</Col>
/>
<File parentKey={parentKey} tabKey={tabKey} />
</Col>
</Row> </Row>
</> </>
); );

View File

@ -10,8 +10,8 @@ import { useFormikContext } from 'formik';
const File = ({ parentKey,tabKey}:any) => { const File = ({ parentKey,tabKey}:any) => {
const { t } = useTranslation(); const { t } = useTranslation();
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const name = `Attribute.[${parentKey}].AttributeValue[${tabKey}].${"main_photo"}`; const name = `Attribute.[${parentKey}].AttributeValue[${tabKey}].${"image"}`;
const imageUrl = formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["main_photo"] ? URL.createObjectURL(formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["main_photo"]) : "" ; const imageUrl = formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["image"] ? URL.createObjectURL(formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["image"]) : "" ;
const fileList: UploadFile[] = [ const fileList: UploadFile[] = [
@ -34,7 +34,7 @@ const File = ({ parentKey,tabKey}:any) => {
return ( return (
<div className="ValidationField"> <div className="ValidationField">
<label className="text"> <label className="text">
{t(`main_photo`)} {t(`image`)}
</label> </label>
<Upload <Upload

View File

@ -0,0 +1,18 @@
import { ColorPicker } from 'antd'
import React from 'react'
import { Label } from 'reactstrap'
const Hex = ({ label, value, onChange }:any) => {
return (
<Label className="tabstext">
{label}
<ColorPicker onChange={onChange} defaultValue={value} size="small" />
</Label>
)
}
export default Hex

View File

@ -9,76 +9,92 @@ import { AttributeValueTabs } from './AttributeTabs';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const initialItemShape: any = {
label: 'Value 1',
key: '1',
closable: true,
};
export const TabsContainer= ({parentKey}:any) => { export const TabsContainer= ({parentKey}:any) => {
const [activeKey, setActiveKey] = useState('1'); const [activeKey, setActiveKey] = useState('1');
const [t] = useTranslation() const [t] = useTranslation()
const { setFieldValue } = useFormikContext(); const { setFieldValue } = useFormikContext();
const formikContext = useFormikContext<FormikValues>(); const formikContext = useFormikContext<FormikValues>();
const { values, handleChange } = formikContext; const { values } = 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)=>{ const varianCount = values?.Attribute[parentKey]?.AttributeValue?.slice(1)?.map((item:any,index:any)=>{
return { return {
label: `${t(`Value`)}`+ `${index+1}`, label: `${t(`Value`)}`+ `${index+1}`,
key: index+1, key: `${index+1}`,
closable: true, closable: true,
} }
})?? initialItemShape })?? initialItemShape
const [items, setItems] = useState(Array.isArray(varianCount) ? varianCount : [initialItemShape]); // Ensure items is always an array const [items, setItems] = useState(Array.isArray(varianCount) ? 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 handleAdd = () => {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
setItems([...items, { key: newKey, label: `Value ${newKey}`, closable: true }]); setItems([...items, { key: newKey, label: `${t(`Value`)} ${newKey}`, closable: true }]);
setActiveKey(newKey); setActiveKey(newKey);
}; };
const handleDuplicate = (targetKey: string) => { const handleDuplicate = (targetKey: string) => {
const targetItem = items.find((item:any) => item.key === targetKey); const targetItem = items.find((item:any) => item.key === targetKey);
if (targetItem) { if (targetItem) {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
const newItem = { ...targetItem, key: newKey, label: `Value ${newKey}` }; const newItem = { ...targetItem, key: newKey, label: `${t(`Value`)} ${newKey}` };
setItems([...items, newItem]); setItems([...items, newItem]);
setActiveKey(newKey); setActiveKey(newKey);
const originalValues = values?.Attribute?.[parentKey]?.AttributeValue?.[targetKey]; const originalValues = values?.Attribute[parentKey].AttributeValue[targetKey];
setFieldValue(`Attribute.${parentKey}.AttributeValue.${newKey}`, originalValues); setFieldValue(`Attribute[${parentKey}].AttributeValue[${newKey}]`, originalValues);
} }
}; };
const [removedAttributeValue, setremovedAttributeValue] = useState<string[]>([]);
useEffect(() => {
setFieldValue(`removedAttributeValue`, removedAttributeValue);
}, [removedAttributeValue]);
const handleRemove = (targetKey: string) => { const handleRemove = (targetKey: string) => {
const newItems = items.filter((item:any) => item.key !== targetKey);
if (newItems.length > 0) { const newItems = items.filter((item:any) => item?.key !== targetKey);
console.log(newItems,"newItems",targetKey,"targetKey");
const removedItem = values?.Attribute[parentKey]?.AttributeValue[targetKey] as any;
if (removedItem?.id) {
console.log(removedItem?.id,"removedItem?.id");
setremovedAttributeValue((prevremovedAttributeValue) => [...prevremovedAttributeValue, removedItem.id]);
}
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1'; const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
setItems(newItems); setItems(newItems);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
setFieldValue(`Attribute.${parentKey}.AttributeValue.${targetKey}`, undefined); setFieldValue(`Attribute.${parentKey}.AttributeValue.${targetKey}`, undefined);
} else {
toast.error("Cannot close the last tab");
}
}; };
useEffect(() => {
const handleResize = () => {
setWidth(window.innerWidth);
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
const tabPosition ='top'; const tabPosition ='top';
return ( return (

View File

@ -5,43 +5,142 @@ import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage'; import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BsInfoCircle } from 'react-icons/bs';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import { useAddCategories } from '../../../api/Categories'; import { useAddCategories } from '../../../api/Categories';
import Form from './Add/AddForm'; import Form from './Add/AddForm';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'; import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { useAddAttribute } from '../../../api/attribute'; import { useAddAttribute } from '../../../api/attribute';
import { TabsContainer } from './Add/AttributeTab/TabsContainer'; import { TabsContainer } from './Add/AttributeTab/TabsContainer';
import { useAddAttributeValue } from '../../../api/attributeValue'; import { useAddAttributeValue } from '../../../api/attributeValue';
import { useFormikContext } from 'formik';
import { toast } from 'react-toastify';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
const AddcategoriesPage = () => { const AddcategoriesPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState() const { setObjectToEdit, objectToEdit } = usePageState()
const {mutate , isLoading,isSuccess,data } = useAddCategories() const {mutate , isLoading,isSuccess,data } = useAddCategories()
const {mutate:AddAttribute, isSuccess : isSuccessAttribute,data:AttributeData} = useAddAttribute() const {isSuccess : isSuccessAttribute,data:AttributeData, mutateAsync} = useAddAttribute()
const {mutate:AddAttributeValue,isSuccess : isSuccessAttributeValue} = useAddAttributeValue() const {mutate:AddAttributeValue,isSuccess : isSuccessAttributeValue} = useAddAttributeValue()
const [Attribute , setAttribute] = useState<any[]>([]) const [Attribute , setAttribute] = useState<any[]>([])
const [AttributeValues , setAttributeValues] = useState<any[]>([]) const [AttributeValues , setAttributeValues] = useState<any[]>([])
const formik = useFormikContext()
const handleSubmit = (values:any)=>{
setAttribute(values?.Attribute?.slice(1))
const CategoriesValues = {
name: {
en:values?.name_en,
ar:values?.name_ar,
de:values?.name_de
},
parent_id:values?.parent_id,
photo:values?.photo,
}
mutate(CategoriesValues)
const handleSubmit = (values:any)=>{
console.log(values,"values");
function isValid(){
values?.Attribute?.slice(1)?.forEach((item:any) => {
if (item && Object.keys(item).length > 0){
setAttribute((prevAddAttributeValue) => [...prevAddAttributeValue, item]);
}
});
setAttributeValues(values?.Attribute?.slice(1)?.map((item:any)=>{
if (item && Object.keys(item).length > 0){
return item?.AttributeValue
}
}))
const CategoriesValues = {
name: {
en:values?.name_en,
ar:values?.name_ar,
de:values?.name_de
},
parent_id:values?.parent_id,
photo:values?.photo,
}
mutate(CategoriesValues)
}
const validationResults: boolean[] = [];
let previousNames: any = {};
values?.Attribute?.slice(1)?.forEach((item: any, index: any) => {
if (item && Object.keys(item).length > 0) {
const itemName = t('name');
const itemNumber = index + 1;
// Check if the names are unique across items
const currentItemNames = {
name_ar: item?.name_ar,
name_en: item?.name_en,
name_de: item?.name_de,
};
if (
previousNames.name_ar === currentItemNames.name_ar ||
previousNames.name_en === currentItemNames.name_en ||
previousNames.name_de === currentItemNames.name_de
) {
toast.error(`${itemName} ${t('unique_error_names')}`);
validationResults.push(false);
}
previousNames = currentItemNames;
// Check for other validation rules
if (!item?.name_ar || !item?.name_en || !item?.name_de) {
toast.error(`${t('required_name')} ${itemNumber}`);
validationResults.push(false);
} else if (!item?.type) {
toast.error(`${t('required_type')} ${itemNumber}`);
validationResults.push(false);
} else if (item?.type === "image") {
if (Array.isArray(item.AttributeValue)) {
item?.AttributeValue.slice(1)?.forEach((attrItem: any, index: number) => {
if (attrItem && Object.keys(attrItem).length > 0) {
if (attrItem.image === null) {
toast.error(`${t('required_image')} ${index + 1}`);
validationResults.push(false);
} else if (!attrItem?.value_ar || !attrItem?.value_en || !attrItem?.value_de) {
toast.error(`${t('required_text')} ${index + 1}`);
validationResults.push(false);
} else {
validationResults.push(true);
}
}
});
}
} else if (item?.type === "color") {
if (Array.isArray(item.AttributeValue)) {
item?.AttributeValue.slice(1)?.forEach((attrItem: any, index: number) => {
if (attrItem && Object.keys(attrItem).length > 0) {
const hexColorRegex = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
if (attrItem && !hexColorRegex.test(attrItem?.value_en)) {
toast.error(`${t('required_color')} ${index + 1}`);
validationResults.push(false);
} else {
validationResults.push(true);
}
}
});
}
} else if (item?.type === "text") {
if (Array.isArray(item.AttributeValue)) {
item?.AttributeValue.slice(1)?.forEach((attrItem: any, index: number) => {
if (attrItem && Object.keys(attrItem).length > 0) {
if (attrItem && (!attrItem?.value_ar || !attrItem?.value_en || !attrItem?.value_de)) {
toast.error(` ${t('required_text')} ${index + 1}`);
validationResults.push(false);
} else {
validationResults.push(true);
}
}
});
}
} else {
validationResults.push(true);
}
}
});
if (validationResults.every((result) => result)) {
isValid();
}
} }
@ -53,10 +152,7 @@ const AddcategoriesPage = () => {
Attribute?.map((dataToSend:any , index:number)=>{ Attribute?.map((dataToSend:any , index:number)=>{
const Attribute = dataToSend const Attribute = dataToSend
setAttributeValues((prev) => ([
...prev,
...Attribute?.AttributeValue,
]));
const NewAttribute = { const NewAttribute = {
name:{ name:{
en:Attribute?.name_en, en:Attribute?.name_en,
@ -66,40 +162,68 @@ const AddcategoriesPage = () => {
type:Attribute?.type, type:Attribute?.type,
category_id:categoryId, category_id:categoryId,
} }
AddAttribute(NewAttribute) mutateAsync(NewAttribute).then((data)=>{
const AttributeId = (data as any )?.id ;
console.log(AttributeValues[0]?.slice(1),"AttributeValues");
AttributeValues[index]?.slice(1)?.map((dataToSend:any , index:number)=>{
const AttributeValue = dataToSend
const NewAttributeValues = {
value:{
en:AttributeValue?.value_en,
ar:AttributeValue?.value_ar,
de:AttributeValue?.value_de
},
image:AttributeValue?.main_photo,
attribute_id:AttributeId,
}
if (NewAttribute.type === "color") {
NewAttributeValues["value"] = {
en: AttributeValue?.value_en,
ar: AttributeValue?.value_en,
de: AttributeValue?.value_en
}
}
AddAttributeValue(NewAttributeValues)
})
})
}) })
} }
},[isSuccess]) },[isSuccess])
useEffect(()=>{ // useEffect(()=>{
if(isSuccessAttribute){ // if(isSuccessAttribute){
const AttributeId = (AttributeData as any )?.id ; // const AttributeId = (AttributeData as any )?.id ;
AttributeValues?.slice(1)?.map((dataToSend:any , index:number)=>{ // AttributeValues?.slice(1)?.map((dataToSend:any , index:number)=>{
// console.log(dataToSend,"dataToSend");
const AttributeValues = dataToSend // const AttributeValues = dataToSend
const NewAttributeValues = { // const NewAttributeValues = {
value:{ // value:{
en:AttributeValues?.value_en, // en:AttributeValues?.value_en,
ar:AttributeValues?.value_ar, // ar:AttributeValues?.value_ar,
de:AttributeValues?.value_de // de:AttributeValues?.value_de
}, // },
image:AttributeValues?.main_photo, // image:AttributeValues?.main_photo,
attribute_id:AttributeId, // attribute_id:AttributeId,
} // }
AddAttributeValue(NewAttributeValues) // AddAttributeValue(NewAttributeValues)
}) // })
} // }
},[isSuccessAttribute]) // },[isSuccessAttribute])
const {t} = useTranslation(); const {t} = useTranslation();
useNavigateOnSuccess(isSuccessAttributeValue , '/categories' ) useNavigateOnSuccess(isSuccess , '/categories' )
useEffect(() => { useEffect(() => {

View File

@ -25,11 +25,10 @@ export const AttributeTabs: React.FC<AttributeTabsProps> = ({ tabKey }) => {
const FormikName = (FormikFieldname: any) => values?.Attribute[tabKey]?.[FormikFieldname]; const FormikName = (FormikFieldname: any) => values?.Attribute[tabKey]?.[FormikFieldname];
console.log(values?.Attribute,"value");
return ( return (
<> <>
<h5>{t("Attributes")} {tabKey}</h5> <h5>{t("Attribute")} {tabKey}</h5>
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<FormItem <FormItem

View File

@ -13,8 +13,10 @@ export const FormItem: React.FC<FormItemProps> = ({ label, value, onChange ,type
return ( return (
<> <>
<Label className="tabstext">{label}</Label> <Label className="tabstext w-100">
<Input value={value} type={type} onChange={onChange} /> {label}
<Input className='w-100' value={value} type={type} onChange={onChange} />
</Label>
</> </>
); );
}; };

View File

@ -18,11 +18,9 @@ const SelectField = ({tabKey}: any) => {
const Data = [{label: "color",value :"color"},{label: "text",value :"text"},{label: "image",value :"image"}] const Data = [{label: "color",value :"color"},{label: "text",value :"text"},{label: "image",value :"image"}]
return ( return (
<div className='ValidationField'> <div className='ValidationField'>
<label className="text"> <label className="text w-100">
{t(`${"type"}`)} {t(`${"type"}`)}
</label> <Select
<Select
placeholder={t(`${"type"}`)} placeholder={t(`${"type"}`)}
options={Data} options={Data}
size="large" size="large"
@ -30,10 +28,10 @@ const SelectField = ({tabKey}: any) => {
defaultValue={FormikValue} defaultValue={FormikValue}
allowClear allowClear
onChange={onChange} onChange={onChange}
/> />
</label>
</div> </div>
) )
} }

View File

@ -6,14 +6,11 @@ import { toast } from 'react-toastify';
import { FormikValues, useFormikContext } from 'formik'; import { FormikValues, useFormikContext } from 'formik';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { AttributeTabs } from './AttributeTabs'; import { AttributeTabs } from './AttributeTabs';
import { AttributeTabs as AddAttributeTabs} from '../../Add/AttributeTab/AttributeTabs';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const initialItemShape: any = {
label: 'Attribute 1',
key: '1',
closable: true,
};
export const TabsContainer: React.FC = () => { export const TabsContainer: React.FC = () => {
const [activeKey, setActiveKey] = useState('1'); const [activeKey, setActiveKey] = useState('1');
const { setFieldValue } = useFormikContext(); const { setFieldValue } = useFormikContext();
@ -23,6 +20,12 @@ export const TabsContainer: React.FC = () => {
const [t] = useTranslation() 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)=>{ const varianCount = values?.Attribute?.slice(1)?.map((item:any,index:any)=>{
return { return {
label: `${t(`Attribute`)}`+ `${index+1}`, label: `${t(`Attribute`)}`+ `${index+1}`,
@ -32,42 +35,75 @@ export const TabsContainer: React.FC = () => {
})?? initialItemShape })?? initialItemShape
const [items, setItems] = useState(varianCount ?? [initialItemShape]); // Ensure items is always an array 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]);
console.log(values,"items");
const handleAdd = () => { const handleAdd = () => {
const newKey = `${items.length + 1}`;
setItems([...items, { key: newKey, label: `Attribute ${newKey}`, closable: true }]); const newKey = `${nextKey}`;
setItems([...items, { key: newKey, label: `${t(`Attribute`)} ${newKey}`, closable: true ,Add:true}]);
setActiveKey(newKey); setActiveKey(newKey);
}; };
const handleDuplicate = (targetKey: string) => { const handleDuplicate = (targetKey: string) => {
const targetItem = items.find((item:any) => item.key === targetKey); const targetItem = items.find((item:any) => item.key === targetKey);
if (targetItem) { if (targetItem) {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
const newItem = { ...targetItem, key: newKey, label: `Attribute ${newKey}` }; const newItem = { ...targetItem, key: newKey, label: `${t(`Attribute`)} ${newKey}`,Add:true };
setItems([...items, newItem]); setItems([...items, newItem]);
setActiveKey(newKey); setActiveKey(newKey);
setNextKey((prevKey : any) => prevKey + 1);
const originalValues = values?.Attribute?.[targetKey]; const originalValues = values?.Attribute?.[targetKey];
setFieldValue(`Attribute.${newKey}`, originalValues);
setFieldValue(`Attribute.${newKey}`, {...originalValues,id:null});
} }
}; };
const [removedAttribute, setRemovedAttribute] = useState<string[]>([]);
useEffect(() => {
setFieldValue(`removedAttribute`, removedAttribute);
}, [removedAttribute]);
const handleRemove = (targetKey: string) => { const handleRemove = (targetKey: string) => {
const newItems = items.filter((item:any) => item.key !== targetKey); const newItems = items.filter((item:any) => item.key !== targetKey);
if (newItems.length > 0) { const removedItem = values?.Attribute[targetKey] as any;
if (removedItem?.id) {
setRemovedAttribute((prevRemovedAttribute) => [...prevRemovedAttribute, removedItem.id]);
}
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1'; const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
setItems(newItems); setItems(newItems);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
setFieldValue(`Attribute.${targetKey}`, undefined); setFieldValue(`Attribute.${targetKey}`, undefined);
} else {
toast.error("Cannot close the last tab");
}
}; };
useEffect(() => { useEffect(() => {
@ -84,31 +120,27 @@ useEffect(() => {
const tabPosition = width > 1000 ? 'left' : 'top'; const tabPosition = width > 1000 ? 'left' : 'top';
return ( return (
<Tabs <>
type="editable-card"
onChange={setActiveKey} <Tabs
activeKey={activeKey} type="editable-card"
onEdit={(targetKey:any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))} onChange={setActiveKey}
tabPosition={tabPosition} activeKey={activeKey}
onEdit={(targetKey: any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))}
tabPosition={tabPosition}
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,
{items.map((item :any) =>{ closable: item.closable,
return ( }))}
>
<TabPane </Tabs>
key={item?.key} { items.length === 0 && (
tab={ <h6 className='AddNewTabText'>{t("Add New Attribute")}</h6>
<Space> )}
{t(`${item.label}`)} </>
<CopyOutlined onClick={() => handleDuplicate(item.key)} />
</Space>
}
closable={item.closable}
>
<AttributeTabs tabKey={item?.key} />
</TabPane>
)
})}
</Tabs>
); );
}; };

View File

@ -27,7 +27,7 @@ export const AttributeValueTabs: React.FC<AttributeValueTabsProps> = ({ parentKe
return ( return (
<> <>
<h5>{t("Values")} {tabKey}</h5> <h5>{t("Value")} {tabKey}</h5>
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<FormItem <FormItem

View File

@ -10,8 +10,8 @@ import { useFormikContext } from 'formik';
const File = ({ parentKey,tabKey}:any) => { const File = ({ parentKey,tabKey}:any) => {
const { t } = useTranslation(); const { t } = useTranslation();
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const name = `Attribute.[${parentKey}].AttributeValue[${tabKey}].${"main_photo"}`; const name = `Attribute.[${parentKey}].AttributeValue[${tabKey}].${"image"}`;
const imageUrl = formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["main_photo"] ? URL.createObjectURL(formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["main_photo"]) : "" ; const imageUrl = formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["image"] ? URL.createObjectURL(formik?.values?.Attribute?.[parentKey]?.AttributeValue?.[tabKey]?.["image"]) : "" ;
const fileList: UploadFile[] = [ const fileList: UploadFile[] = [
@ -34,7 +34,7 @@ const File = ({ parentKey,tabKey}:any) => {
return ( return (
<div className="ValidationField"> <div className="ValidationField">
<label className="text"> <label className="text">
{t(`main_photo`)} {t(`image`)}
</label> </label>
<Upload <Upload

View File

@ -12,8 +12,10 @@ interface FormItemProps {
export const FormItem: React.FC<FormItemProps> = ({ label, value, onChange ,type = "text"}) => { export const FormItem: React.FC<FormItemProps> = ({ label, value, onChange ,type = "text"}) => {
return ( return (
<> <>
<Label className="tabstext">{label}</Label> <Label className="tabstext w-100" >
<Input value={value} type={type} onChange={onChange} /> {label}
<Input className='w-100' value={value} type={type} onChange={onChange} />
</Label>
</> </>
); );
}; };

View File

@ -3,109 +3,140 @@ import React, { useEffect, useState } from 'react';
import { Tabs, Space } from 'antd'; import { Tabs, Space } from 'antd';
import { CopyOutlined } from '@ant-design/icons'; import { CopyOutlined } from '@ant-design/icons';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { FormikValues, useFormikContext } from 'formik'; import { FormikValues, useFormikContext } from 'formik';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { AttributeValueTabs } from './AttributeTabs'; import { AttributeValueTabs } from './AttributeTabs';
const { TabPane } = Tabs; import { AttributeValueTabs as AddAttributeValueTabs } from '../../Add/AttributeValueTab/AttributeTabs';
const initialItemShape: any = { export const TabsContainer = ({ parentKey }: any) => {
label: 'Value 1',
key: '1',
closable: true,
};
export const TabsContainer= ({parentKey}:any) => {
const [activeKey, setActiveKey] = useState('1'); const [activeKey, setActiveKey] = useState('1');
const [t] = useTranslation() const [t] = useTranslation()
const { setFieldValue } = useFormikContext(); const { setFieldValue } = useFormikContext();
const formikContext = useFormikContext<FormikValues>(); const formikContext = useFormikContext<FormikValues>();
const { values, handleChange } = formikContext; const { values, handleChange } = formikContext;
const [width, setWidth] = useState(window.innerWidth); const [width, setWidth] = useState(window.innerWidth);
const varianCount = values?.Attribute[parentKey]?.AttributeValue?.slice(1)?.map((item:any,index:any)=>{
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 { return {
label: `${t(`Value`)}`+ `${index+1}`, label: `${t(`Value`)}` + `${index + 1}`,
key: index+1, key: index + 1,
closable: true, closable: true,
} }
})?? initialItemShape }) ?? initialItemShape
const [items, setItems] = useState(Array.isArray(varianCount) ? varianCount : [initialItemShape]); // Ensure items is always an array 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 handleAdd = () => {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
setItems([...items, { key: newKey, label: `Value ${newKey}`, closable: true }]); setItems([...items, { key: newKey, label: `${t(`Value`)} ${newKey}`, closable: true,Add:true }]);
setActiveKey(newKey); setActiveKey(newKey);
}; };
const handleDuplicate = (targetKey: string) => { const handleDuplicate = (targetKey: string) => {
const targetItem = items.find((item:any) => item.key === targetKey); const targetItem = items.find((item: any) => item.key === targetKey);
if (targetItem) { if (targetItem) {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
const newItem = { ...targetItem, key: newKey, label: `Value ${newKey}` }; const newItem = { ...targetItem, key: newKey, label: `${t(`Value`)} ${newKey}`,Add:true };
setItems([...items, newItem]); setItems([...items, newItem]);
setActiveKey(newKey); setActiveKey(newKey);
setNextKey((prevKey : any) => prevKey + 1);
const originalValues = values?.Attribute?.[parentKey]?.AttributeValue?.[targetKey]; const originalValues = values?.Attribute?.[parentKey]?.AttributeValue?.[targetKey];
setFieldValue(`Attribute.${parentKey}.AttributeValue.${newKey}`, originalValues);
setFieldValue(`Attribute.${parentKey}.AttributeValue.${newKey}`, {...originalValues,id:null});
} }
}; };
const [removedAttributeValues, setRemovedAttributeValues] = useState<string[]>([]);
useEffect(() => {
setFieldValue(`removedAttributeValues`, removedAttributeValues);
}, [removedAttributeValues]);
const handleRemove = (targetKey: string) => { const handleRemove = (targetKey: string) => {
const newItems = items.filter((item:any) => item.key !== targetKey); const newItems = items?.filter((item: any) => item.key !== targetKey) as any;
if (newItems.length > 0) { const removedItem = values?.Attribute?.[parentKey]?.AttributeValue?.[targetKey] as any;
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1'; if (removedItem?.id) {
setItems(newItems); setRemovedAttributeValues((prevRemovedAttributeValues) => [...prevRemovedAttributeValues, removedItem.id]);
setActiveKey(newActiveKey);
setFieldValue(`Attribute.${parentKey}.AttributeValue.${targetKey}`, undefined);
} else {
toast.error("Cannot close the last tab");
} }
};
useEffect(() => { const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
const handleResize = () => { setItems(newItems);
setActiveKey(newActiveKey);
setFieldValue(`Attribute.${parentKey}.AttributeValue.${targetKey}`, undefined);
};
useEffect(() => {
const handleResize = () => {
setWidth(window.innerWidth); setWidth(window.innerWidth);
}; };
window.addEventListener('resize', handleResize); window.addEventListener('resize', handleResize);
return () => { return () => {
window.removeEventListener('resize', handleResize); window.removeEventListener('resize', handleResize);
}; };
}, []); }, []);
const tabPosition ='top';
const tabPosition = 'top';
return ( return (
<>
<Tabs <Tabs
type="editable-card" type="editable-card"
onChange={setActiveKey} onChange={setActiveKey}
activeKey={activeKey} activeKey={activeKey}
onEdit={(targetKey:any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))} onEdit={(targetKey: any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))}
tabPosition={tabPosition} tabPosition={tabPosition}
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,
}))
}
> >
{items.map((item :any) =>{
return (
<TabPane
key={item?.key}
tab={
<Space>
{t(`${item.label}`)}
<CopyOutlined onClick={() => handleDuplicate(item.key)} />
</Space>
}
closable={item.closable}
>
<AttributeValueTabs parentKey={parentKey} tabKey={item?.key} />
</TabPane>
)
})}
</Tabs> </Tabs>
{ items.length === 0 && (
<h6>{t("Add_New_value")}</h6>
)}
</>
); );
}; };

View File

@ -22,15 +22,17 @@ function Form() {
return ( return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<ValidationField name="name" /> <ValidationField name="name_ar" />
<ValidationField name="parent_id" type="Search" option={SelectData} searchBy={"search"} /> <ValidationField name="name_en" />
<ValidationField name="name_de" />
</Col> </Col>
<Col> <Col>
<ValidationField name="parent_id" type="Search" option={SelectData} searchBy={"search"} />
<ValidationField name="photo" type="File" /> <ValidationField name="photo" type="File" />
</Col> </Col>
</Row> </Row>
) )
} }

View File

@ -3,60 +3,474 @@ import { getInitialValues, getDataToSend } from '../formUtil'
import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs' import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'; import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
import { FaSadCry } from 'react-icons/fa'
import ViewPage from '../../../Layout/Dashboard/ViewPage'; import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate, Spin } from 'antd'; import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'; import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import LoadingPage from '../../../Layout/app/LoadingPage'; import LoadingPage from '../../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BsInfoCircle } from 'react-icons/bs';
import { useGetOneCategories, useUpdateCategories } from '../../../api/Categories'; import { useGetOneCategories, useUpdateCategories } from '../../../api/Categories';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess'; import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './Edit/Form';
import { changeShapeInfo } from '../../../utils/Array/changeShapeInfo';
import { TabsContainer } from './Edit/AttributeTab/TabsContainer'; import { TabsContainer } from './Edit/AttributeTab/TabsContainer';
import { useGetSingleAttribute } from '../../../api/attribute'; import { useAddAttribute, useGetSingleAttribute } from '../../../api/attribute';
import { useDeleteAttribute, useUpdateAttribute } from '../../../api/attribute';
import { useAddAttributeValue, useDeleteAttributeValue, useUpdateAttributeValue } from '../../../api/attributeValue';
import { toast } from 'react-toastify';
import Form from './Add/AddForm';
const EditPage = () => { const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState() const { setObjectToEdit, objectToEdit } = usePageState()
const {t} = useTranslation(); const { t } = useTranslation();
const { data ,isLoading } = useGetOneCategories() const { data, isLoading, isRefetching } = useGetOneCategories()
const {id} = useParams() const { id } = useParams()
const {data : Atrribute,isLoading : isLoadingAtrribute } = useGetSingleAttribute({ name:"category_id", id:id},{}) const { data: Atrribute, isLoading: isLoadingAtrribute, isRefetching: AttributeisRefetching } = useGetSingleAttribute({ name: "category_id", id: id }, {})
const {mutate ,isSuccess} = useUpdateCategories("post") const { mutate, isError, isSuccess } = useUpdateCategories()
const handleSubmit = (values:any)=>{ const { mutateAsync, isSuccess: isSuccessAddAttribute, data: AttributeData, isError: isErrorAddAttribute } = useAddAttribute()
const Imagetype = typeof values?.photo const { mutate: mutateAttributeValue, isSuccess: isSuccessAddAttributeValue, data: AttributeValueData, isError: isErrorAddAttributeValue } = useAddAttributeValue()
values['attribute'] = changeShapeInfo(values?.attribute) const { mutate: UpdateAttribute, isSuccess: isSuccessAttribute, isError: isErrorUpdateAttribute } = useUpdateAttribute("put")
if(Imagetype === "string") { const { mutate: UpdateAttributeValue, isSuccess: isSuccessAttributeValue, isError: isErrorUpdateAttributeValue } = useUpdateAttributeValue()
delete values['photo'] const { mutate: DeleteAttributeValue, isError: isErrorDeleteAttributeValue } = useDeleteAttributeValue()
const { mutate: DeleteAttribute, isError: isErrorDeleteAttribute } = useDeleteAttribute()
const [removedAttribute, setremovedAttribute] = useState<any[]>([])
const [removedAttributeValue, setremovedAttributeValue] = useState<any[]>([])
const [AddAttribute, setAddAttribute] = useState<any[]>([])
const [EditAttribute, setEditAttribute] = useState<any[]>([])
const [AddAttributeValue, setAddAttributeValue] = useState<any[]>([])
const [EditAttributeValue, setEditAttributeValue] = useState<any[]>([])
const [OldData, setOldData] = useState(Atrribute?.data)
const [OldDataValues, setOldDataValues] = useState([])
const handleSubmit = (values: any) => {
console.log(values,"values");
function isValid(){
const attributes = values?.Attribute?.slice(1);
setremovedAttribute(values?.removedAttribute)
setremovedAttributeValue(values?.removedAttributeValue)
if (attributes) {
attributes.forEach((item: any, index: number) => {
if (item.id && item.id !== null) {
setEditAttribute((prevEditAttribute) => [...prevEditAttribute, item]);
console.log(item, "item");
if (item?.AttributeValue) {
item.AttributeValue.slice(1).forEach((attrValueItem: any) => {
if (attrValueItem && Object.keys(attrValueItem).length > 0) { // Check if attrValueItem is defined and not empty
setEditAttributeValue((prevEditAttributeValue) => [...prevEditAttributeValue, [index, attrValueItem]]);
}
});
}
} else {
setAddAttribute((prevAddAttribute) => [...prevAddAttribute, item]);
if (item?.AttributeValue) {
item.AttributeValue.slice(1).forEach((attrValueItem: any) => {
if (attrValueItem && Object.keys(attrValueItem).length > 0) { // Check if attrValueItem is defined and not empty
setAddAttributeValue((prevEditAttributeValue) => [...prevEditAttributeValue, [index, attrValueItem]]);
}
});
}
}
});
}
const EditedCategory = {
name: {
en: values?.name_en,
ar: values?.name_ar,
de: values?.name_de
},
photo: values?.photo,
parent_id: values?.parent_id,
_method:"PUT"
} }
const Imagetype = typeof values?.photo
if (Imagetype === "string") {
delete EditedCategory['photo']
}
mutate(EditedCategory)
}
const validationResults: boolean[] = [];
let previousNames: any = {};
values?.Attribute?.slice(1)?.forEach((item: any, index: any) => {
if (item && Object.keys(item).length > 0) {
const itemName = t('name');
const itemNumber = index + 1;
const currentItemNames = {
name_ar: item?.name_ar,
name_en: item?.name_en,
name_de: item?.name_de,
};
if (
previousNames.name_ar === currentItemNames.name_ar ||
previousNames.name_en === currentItemNames.name_en ||
previousNames.name_de === currentItemNames.name_de
) {
toast.error(`${itemName} ${t('unique_error_names')}`);
validationResults.push(false);
}
previousNames = currentItemNames;
// Check for other validation rules
if (!item?.name_ar || !item?.name_en || !item?.name_de) {
toast.error(`${t('required_name')} ${itemNumber}`);
validationResults.push(false);
} else if (!item?.type) {
toast.error(`${t('required_type')} ${itemNumber}`);
validationResults.push(false);
} else if (item?.type === "image") {
if (Array.isArray(item.AttributeValue)) {
item?.AttributeValue.slice(1)?.forEach((attrItem: any, index: number) => {
if (attrItem && Object.keys(attrItem).length > 0) {
if (attrItem.image === null) {
toast.error(`${t('required_image')} ${index + 1}`);
validationResults.push(false);
} else if (!attrItem?.value_ar || !attrItem?.value_en || !attrItem?.value_de) {
toast.error(`${t('required_text')} ${index + 1}`);
validationResults.push(false);
} else {
validationResults.push(true);
}
}
});
}
} else if (item?.type === "color") {
if (Array.isArray(item.AttributeValue)) {
item?.AttributeValue.slice(1)?.forEach((attrItem: any, index: number) => {
if (attrItem && Object.keys(attrItem).length > 0) {
const hexColorRegex = /^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
if (attrItem && !hexColorRegex.test(attrItem?.value_en)) {
toast.error(`${t('required_color')} ${index + 1}`);
validationResults.push(false);
} else {
validationResults.push(true);
}
}
});
}
} else if (item?.type === "text") {
if (Array.isArray(item.AttributeValue)) {
item?.AttributeValue.slice(1)?.forEach((attrItem: any, index: number) => {
if (attrItem && Object.keys(attrItem).length > 0) {
if (attrItem && (!attrItem?.value_ar || !attrItem?.value_en || !attrItem?.value_de)) {
toast.error(` ${t('required_text')} ${index + 1}`);
validationResults.push(false);
} else {
validationResults.push(true);
}
}
});
}
} else {
validationResults.push(true);
}
}
});
if (validationResults.every((result) => result)) {
isValid();
}
mutate(values)
// return mutate(newData);
} }
useNavigateOnSuccess(isSuccess , '/categories')
function filterByIndex(number: number, array: [number, any][]): any[] {
return array.filter(([index, _]) => index === number).map(([_, item]) => item);
}
useEffect(() => { useEffect(() => {
if (isSuccess) {
const categoryId = id;
console.log(EditAttribute,"EditAttribute");
EditAttribute?.map((dataToSend: any, index: number) => {
console.log(index,"index");
const EditAttribute = dataToSend
const foundObject = OldData.find((item: any) => item.id === EditAttribute?.id) as any;
const UpdatedAttribute = {
name: {
en: EditAttribute?.name_en,
ar: EditAttribute?.name_ar,
de: EditAttribute?.name_de
},
type: EditAttribute?.type,
// category_id:categoryId,
}
if (foundObject) {
Object.keys(UpdatedAttribute).forEach((propName: any) => {
if (foundObject.hasOwnProperty(propName)) {
const foundValue = foundObject[propName];
//@ts-ignore
const editedValue = UpdatedAttribute[propName];
if (foundValue === editedValue) {
//@ts-ignore
delete UpdatedAttribute[propName];
}
}
})
if (foundObject.name &&
foundObject.name.en === UpdatedAttribute.name.en &&
foundObject.name.ar === UpdatedAttribute.name.ar &&
foundObject.name.de === UpdatedAttribute.name.de) {
//@ts-ignore
delete UpdatedAttribute.name;
}
Object.keys(UpdatedAttribute).forEach((key: any) => {
//@ts-ignore
if (UpdatedAttribute[key] === undefined) {
//@ts-ignore
delete UpdatedAttribute[key];
}
});
if (Object.keys(UpdatedAttribute).length > 0) {
//@ts-ignore
// UpdatedAttribute._method = "PUT";
//@ts-ignore
UpdatedAttribute.id = foundObject?.id;
console.log(UpdatedAttribute, "EditAttribute");
UpdateAttribute(UpdatedAttribute)
}
}
const result: [number, any][] = filterByIndex(index, EditAttributeValue);
console.log(result,"result");
result?.map((dataToSend: any) => {
if(dataToSend?.id && dataToSend.id !== null){
console.log(OldDataValues,"OldDataValues");
const foundObjectValue = (OldDataValues[index] as any).find((item: any) => item.id === dataToSend?.id) as any;
console.log(foundObjectValue,"foundObjectValue");
console.log(OldDataValues[index],"OldDataValues[index]");
const EditAttributeValue = dataToSend
console.log(EditAttributeValue);
const NewEditAttributeValue = {
id: EditAttributeValue?.id,
value: {
en: EditAttributeValue?.value_en,
ar: EditAttributeValue?.value_ar,
de: EditAttributeValue?.value_de
},
image: EditAttributeValue?.main_photo,
// attribute_id:EditAttribute?.id,
// id: EditAttributeValue?.id,
}
if (EditAttribute.type === "color") {
NewEditAttributeValue["value"] = {
en: EditAttributeValue?.value_en,
ar: EditAttributeValue?.value_en,
de: EditAttributeValue?.value_en
}
}
if (EditAttributeValue?.main_photo === "string") {
delete NewEditAttributeValue['image']
}
if(foundObjectValue){
console.log(foundObjectValue,"foundObjectValue");
Object.keys(NewEditAttributeValue).forEach((propName: any) => {
if (foundObjectValue.hasOwnProperty(propName)) {
const foundValue = foundObjectValue[propName];
//@ts-ignore
const editedValue = NewEditAttributeValue[propName];
if (foundValue === editedValue) {
//@ts-ignore
delete NewEditAttributeValue[propName];
}
}
})
Object.keys(NewEditAttributeValue).forEach((key: any) => {
//@ts-ignore
if (NewEditAttributeValue[key] === undefined) {
//@ts-ignore
delete NewEditAttributeValue[key];
}
});
if (foundObjectValue.value &&
foundObjectValue.value.en === NewEditAttributeValue.value.en &&
foundObjectValue.value.ar === NewEditAttributeValue.value.ar &&
foundObjectValue.value.de === NewEditAttributeValue.value.de) {
//@ts-ignore
delete NewEditAttributeValue.value;
}
console.log(foundObjectValue.value,"foundObjectValue.value");
console.log(NewEditAttributeValue.value,"NewEditAttributeValue.value");
if (Object.keys(NewEditAttributeValue).length > 0) {
//@ts-ignore
NewEditAttributeValue._method = "PUT";
//@ts-ignore
NewEditAttributeValue.id = foundObjectValue?.id;
console.log(NewEditAttributeValue, "EditAttribute");
UpdateAttributeValue(NewEditAttributeValue)
}
}
}
else{
console.log("mutateAttributeValue");
const EditAttributeValue = dataToSend
const NewEditAttributeValue = {
value: {
en: EditAttributeValue?.value_en,
ar: EditAttributeValue?.value_ar,
de: EditAttributeValue?.value_de
},
image: EditAttributeValue?.main_photo,
// attribute_id:EditAttribute?.id,
attribute_id: EditAttribute?.id,
}
if (EditAttribute.type === "color") {
NewEditAttributeValue["value"] = {
en: EditAttributeValue?.value_en,
ar: EditAttributeValue?.value_en,
de: EditAttributeValue?.value_en
}
}
mutateAttributeValue(NewEditAttributeValue)
}
})
}
)
console.log(removedAttribute,"removedAttribute");
removedAttribute?.map((item:any)=>{
DeleteAttribute({ id: item })
})
AddAttribute?.map((dataToSend: any, index: number) => {
const AddAttribute = dataToSend
const NewAddAttribute = {
name: {
en: AddAttribute?.name_en,
ar: AddAttribute?.name_ar,
de: AddAttribute?.name_de
},
type: AddAttribute?.type,
category_id: categoryId,
}
mutateAsync(NewAddAttribute).then((data: any) => {
const AttributeId = (data as any)?.id;
// console.log(AttributeValues[0]?.slice(1),"AttributeValues");
const result: [number, any][] = filterByIndex(0, AddAttributeValue);
result?.map((dataToSend: any, index: number) => {
const AddAttributeValue = dataToSend
const NewAddAttributeValue = {
value: {
en: AddAttributeValue?.value_en,
ar: AddAttributeValue?.value_ar,
de: AddAttributeValue?.value_de
},
image: AddAttributeValue?.main_photo,
attribute_id: AttributeId,
}
mutateAttributeValue(NewAddAttributeValue)
})
})
})
console.log(removedAttributeValue,"removedAttributeValue");
removedAttributeValue?.map((item:any)=>{
console.log(item,"item");
return DeleteAttributeValue({ id: item })
})
}
}, [isSuccess])
// useNavigateOnSuccess(isSuccess, '/categories')
useEffect(() => {
setObjectToEdit([data?.category, Atrribute?.data]);
setOldData(Atrribute?.data)
setOldDataValues(Atrribute?.data?.map((item:any)=>{
return item?.attribute_value
}))
console.log(OldDataValues,"OldDataValues");
setObjectToEdit([data?.category,Atrribute?.data]); }, [data?.category, Atrribute?.data]);
}, [data?.category,Atrribute?.data]);
const getValidationSchema = () => { const getValidationSchema = () => {
return null return null
}; };
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit }; const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit };
if (isLoadingAtrribute || isLoading || !objectToEdit || (Array.isArray(objectToEdit) && objectToEdit.some(item => item === undefined))) { if (AttributeisRefetching || isRefetching || isLoadingAtrribute || isLoading || !objectToEdit || (Array.isArray(objectToEdit) && objectToEdit.some(item => item === undefined))) {
return <Spin/> return <Spin />
} }
return ( return (
@ -65,19 +479,19 @@ const EditPage = () => {
<ViewPage {...ViewProps}> <ViewPage {...ViewProps}>
<Tabs> <Tabs>
<TabList> <TabList>
{/* <Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo")}</h6></div></Tab> */} <Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("BasicInfo")}</h6></div></Tab>
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("attributes")}</h6></div></Tab> <Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleDriverInfo'>{t("attributes")}</h6></div></Tab>
</TabList> </TabList>
{/*
<TabBody > <TabBody >
<div className=" mt-4"><Form /></div> <div className=" mt-4"><Form /></div>
</TabBody> */} </TabBody>
<TabBody > <TabBody >
<div className=" mt-4"><TabsContainer /></div> <div className=" mt-4"><TabsContainer /></div>
</TabBody> </TabBody>
</Tabs> </Tabs>
</ViewPage> </ViewPage>
: <LoadingPage />} : <LoadingPage />}

View File

@ -1,47 +1,54 @@
import * as Yup from "yup"; import * as Yup from "yup";
import { buildFormData } from "../../api/helper/buildFormData"; import { buildFormData } from "../../api/helper/buildFormData";
import { ImageBaseURL } from "../../api/config";
import { fetchImage } from "../../Hooks/imageUrlToFile";
import { useState } from "react";
interface formUtilCommon {
number: number,
value: number
}
interface ObjectToEdit extends formUtilCommon {
id?: number,
}
interface InitialValues extends ObjectToEdit {
}
interface ValidateSchema extends formUtilCommon {
}
export const getInitialValues = (objectToEdit: any | null = null): any => { export const getInitialValues = (objectToEdit: any | null = null): any => {
const Attribute = objectToEdit[1]?.map((item: any) => { const Attribute = objectToEdit[1]?.map((item: any) => {
const AttributeValue = item?.attribute_value?.map((item:any)=>({value:item?.value , image : item?.image} ) const AttributeValue = item?.attribute_value?.map((item:any)=>(
{
value_ar: item?.value["ar"],
value_en: item?.value["en"],
value_de: item?.value["de"],
id : item?.id,
image : item?.image,
Edited:false
} )
) )
return ( return (
{ {
name : item?.name, name_ar: item?.name["ar"],
name_en: item?.name["en"],
name_de: item?.name["de"],
type : item?.type, type : item?.type,
id : item?.id, id : item?.id,
icon : item?.icon, icon : item?.icon,
category_id : item?.category_id, category_id : item?.category_id,
AttributeValue : [{},...AttributeValue], AttributeValue : [{},...AttributeValue ?? {}],
Edited:false
} }
) )
}) })
const imageUrl = ImageBaseURL + objectToEdit[0]?.photo?.replace("public", "/storage")
return { return {
id: objectToEdit[0]?.id ?? 0, id: objectToEdit[0]?.id ?? 0,
name: objectToEdit[0]?.name ?? "", name_ar: objectToEdit[0]?.name["ar"],
name_en: objectToEdit[0]?.name["en"],
name_de: objectToEdit[0]?.name["de"],
parent_id: objectToEdit[0]?.parent_id ?? "", parent_id: objectToEdit[0]?.parent_id ?? "",
photo: objectToEdit[0]?.photo ?? '', photo: objectToEdit[0]?.photo ?? '',
Attribute: [{},...Attribute], Attribute: [{},...Attribute],
removedAttribute:[],
removedAttributeValue:[],
}; };
}; };
@ -52,7 +59,7 @@ export const getInitialValuesForAdd = (objectToEdit: any | null = null): any =>
name_de: '', name_de: '',
parent_id: null, parent_id: null,
photo: '', photo: '',
Attribute: [{},{AttributeValue:[{},{}]}], Attribute: [{}],
}; };
@ -63,17 +70,18 @@ export const getInitialValuesForAdd = (objectToEdit: any | null = null): any =>
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => { export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any> => {
// Validate input // Validate input
return Yup.object().shape({ return Yup.object().shape({
// name_ar: Yup.string().required('Required'), name_ar: Yup.string().required('Required'),
// name_en: Yup.string().required('Required'), name_en: Yup.string().required('Required'),
// name_de: Yup.string().required('Required'), name_de: Yup.string().required('Required'),
// parent_id: Yup.string().required('Required'), // parent_id: Yup.string().required('Required'),
// photo: Yup.string().required('Required'), photo: Yup.string().required('Required'),
}); });
}; };
export const getDataToSend = (values: any): FormData => { export const getDataToSend = (values: any): FormData => {
const data = { ...values }; const data = { ...values };

View File

@ -12,6 +12,8 @@ const useTableColumns :any = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const deleteMutation = useDeleteCategories() const deleteMutation = useDeleteCategories()
const navigate = useNavigate() const navigate = useNavigate()
const language = localStorage.getItem("language") ?? "en"
return useMemo( return useMemo(
() => [ () => [
@ -19,7 +21,7 @@ const useTableColumns :any = () => {
name: t("name"), name: t("name"),
sortable: false, sortable: false,
center: "true", center: "true",
cell: (row:any) => row?.name cell: (row:any) => row?.name[language]
}, },
{ {
name: t("image"), name: t("image"),

View File

@ -27,7 +27,7 @@ function Page() {
<DashHeader showAddButton={false} title={'coupon'}> <DashHeader showAddButton={false} title={'coupon'}>
<div className='RightSide d-flex gap-2 align-center '> <div className='RightSide d-flex gap-2 align-center '>
<SearchField /> <SearchField searchBy={"name"} />
<AddButton onClick={()=>navigate('/coupon/add')}></AddButton> <AddButton onClick={()=>navigate('/coupon/add')}></AddButton>
</div> </div>

View File

@ -18,11 +18,12 @@ function Form() {
const coupon_type_discount_flat = [{ lable: "general", value: "general" }] const coupon_type_discount_flat = [{ lable: "general", value: "general" }]
const discount_type = [{ lable: "percentage", value: "percentage" },{ lable: "flat", value: "flat" }] const discount_type = [{ lable: "percentage", value: "percentage" },{ lable: "flat", value: "flat" }]
const { data: CategoriesData } = useGetCategories() const { data: CategoriesData} = useGetCategories()
const { data: ProductData } = useGetProduct() const { data: ProductData } = useGetProduct()
const SelectCategoriesData = useFormatToSelect(CategoriesData?.categories) const SelectCategoriesData = useFormatToSelect(CategoriesData?.categories)
const SelectProductData = useFormatToSelect(ProductData?.BaseProducts) const SelectProductData = useFormatToSelect(ProductData?.BaseProducts)
return ( return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
@ -40,7 +41,7 @@ function Form() {
<ValidationField name="discount_type" type="Select" option={discount_type} /> <ValidationField name="discount_type" type="Select" option={discount_type} />
<ValidationField name="coupon_type" type="Select" option={values?.discount_type !== 'flat' ? coupon_type :coupon_type_discount_flat } /> <ValidationField name="coupon_type" type="Select" option={values?.discount_type !== 'flat' ? coupon_type :coupon_type_discount_flat } />
{/* <ValidationField name="itemable_type" label='coupon_item_type' type="Select" option={itemable_type} isDisabled={values?.coupon_type !== "specified"} isMulti/> */} {/* <ValidationField name="itemable_type" label='coupon_item_type' type="Select" option={itemable_type} isDisabled={values?.coupon_type !== "specified"} isMulti/> */}
<ValidationField name="product_attr" label='product_item' type="Search" option={SelectProductData} searchBy={"search"} isDisabled={values?.coupon_type !== "specified"}isMulti /> <ValidationField name="product_attr" label='product_item' type="Search" option={SelectProductData} searchBy={"name"} isDisabled={values?.coupon_type !== "specified"}isMulti />
<ValidationField name="category_attr" label='categories_item_name' type="Search" option={SelectCategoriesData} searchBy={"name"} isDisabled={values?.coupon_type !== "specified"}isMulti /> <ValidationField name="category_attr" label='categories_item_name' type="Search" option={SelectCategoriesData} searchBy={"name"} isDisabled={values?.coupon_type !== "specified"}isMulti />
<ValidationField name="status" type='Checkbox' label='status' /> <ValidationField name="status" type='Checkbox' label='status' />

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { getInitialValues, getValidationSchema, getDataToSend } from '../formUtil' import { getInitialValuesForAdd as getInitialValues, getValidationSchema, getDataToSend } from '../formUtil'
import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs' import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'; import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
@ -32,6 +32,7 @@ const category = values?.category_attr?.map((item: any) => {
values['items'] = [...products, ...category]; values['items'] = [...products, ...category];
console.log(values, "values"); console.log(values, "values");
mutate(values) mutate(values)

View File

@ -27,7 +27,7 @@ function Form() {
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col> <Col>
<ValidationField name="name" /> <ValidationField name="name" />
<ValidationField name="code" /> <ValidationField name="code" isDisabled />
<ValidationField name="active" label='active_from_to' type='DataRange' Format="YYYY/MM/DD" /> <ValidationField name="active" label='active_from_to' type='DataRange' Format="YYYY/MM/DD" />
<ValidationField name="maximum_number_of_uses" type='number' /> <ValidationField name="maximum_number_of_uses" type='number' />
<ValidationField name="maximum_number_of_uses_per_user" type='number' /> <ValidationField name="maximum_number_of_uses_per_user" type='number' />
@ -40,8 +40,8 @@ function Form() {
<ValidationField name="discount_type" type="Select" option={discount_type} /> <ValidationField name="discount_type" type="Select" option={discount_type} />
<ValidationField name="coupon_type" type="Select" option={values?.discount_type !== 'flat' ? coupon_type :coupon_type_discount_flat } /> <ValidationField name="coupon_type" type="Select" option={values?.discount_type !== 'flat' ? coupon_type :coupon_type_discount_flat } />
{/* <ValidationField name="itemable_type" label='coupon_item_type' type="Select" option={itemable_type} isDisabled={values?.coupon_type !== "specified"} isMulti/> */} {/* <ValidationField name="itemable_type" label='coupon_item_type' type="Select" option={itemable_type} isDisabled={values?.coupon_type !== "specified"} isMulti/> */}
<ValidationField name="product_attr" label='product_item' type="Search" option={SelectProductData} searchBy={"search"} isDisabled={values?.coupon_type !== "specified"}isMulti /> <ValidationField name="product_attr" label='product_item' type="Search" option={SelectProductData} searchBy={"name"} isDisabled={values?.coupon_type !== "specified"}isMulti />
<ValidationField name="category_attr" label='categories_item_name' type="Search" option={SelectCategoriesData} searchBy={"name"} isDisabled={values?.coupon_type !== "specified"}isMulti /> <ValidationField name="category_attr" label='categories_item' type="Search" option={SelectCategoriesData} searchBy={"name"} isDisabled={values?.coupon_type !== "specified"}isMulti />
<ValidationField name="status" type='Checkbox' label='status' /> <ValidationField name="status" type='Checkbox' label='status' />

View File

@ -1,11 +1,11 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import {getInitialValuesForAdd as getInitialValues, getDataToSend } from '../formUtil' import { getInitialValues, getDataToSend } from '../formUtil'
import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs' import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'; import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
import { FaSadCry } from 'react-icons/fa' import { FaSadCry } from 'react-icons/fa'
import ViewPage from '../../../Layout/Dashboard/ViewPage'; import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate } from 'antd'; import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'; import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import LoadingPage from '../../../Layout/app/LoadingPage'; import LoadingPage from '../../../Layout/app/LoadingPage';
@ -18,31 +18,40 @@ import Form from './EditForm';
const EditPage = () => { const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState() const { setObjectToEdit, objectToEdit } = usePageState()
const { t } = useTranslation(); const { t } = useTranslation();
const { data } = useGetOneCoupon() const { data,isLoading,isRefetching } = useGetOneCoupon()
const { mutate, isSuccess } = useUpdateCoupon("put") const { mutate, isSuccess } = useUpdateCoupon("put")
const FormatedData = data?.coupon;
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
values.active_at = values.active[0].format('YYYY-MM-DD HH:mm:ss.SSS')
values.active_to = values.active[1].format('YYYY-MM-DD HH:mm:ss.SSS')
values.status = values.active ? "active" : "inactive"
const products = values?.product_attr?.map((item: any) => { const products = values?.product_attr?.map((item: any) => {
return { "itemable_type": "product", "itemable_id": item }; return { "itemable_type": "product", "itemable_id": item };
})?.filter((item: any) => item.itemable_id !== "") || []; })?.filter((item: any) => item.itemable_id !== "") || [];
const category = values?.category_attr?.map((item: any) => { const category = values?.category_attr?.map((item: any) => {
return { "itemable_type": "category", "itemable_id": item }; return { "itemable_type": "category", "itemable_id": item };
})?.filter((item: any) => item.itemable_id !== "") || []; })?.filter((item: any) => item.itemable_id !== "") || [];
values['items'] = [...products, ...category]; // Create an object to hold the values to be mutated
const mutationData: any = {};
console.log(values, "values"); if (values?.name !== null) mutationData["name"] = values.name;
if (values?.status !== null) mutationData["status"] = values.status ? "active" : "inactive";
if (values?.minimum_total_to_order !== null) mutationData["minimum_total_to_order"] = values.minimum_total_to_order;
if (values?.maximum_number_of_uses_per_user !== null) mutationData["maximum_number_of_uses_per_user"] = values.maximum_number_of_uses_per_user;
if (values?.maximum_number_of_uses !== null) mutationData["maximum_number_of_uses"] = values.maximum_number_of_uses;
if (values?.coupon_value !== null) mutationData["coupon_value"] = values.coupon_value;
if (values?.coupon_type !== null) mutationData["coupon_type"] = values.coupon_type;
if (values?.discount_type !== null) mutationData["discount_type"] = values.discount_type;
if (values?.active !== null && values?.active.length === 2) {
mutationData["active_at"] = values.active[0].format('YYYY-MM-DD HH:mm:ss.SSS');
mutationData["active_to"] = values.active[1].format('YYYY-MM-DD HH:mm:ss.SSS');
}
if (products.length > 0 || category.length > 0) {
mutationData['items'] = [...products, ...category];
}
// Perform the mutation with the constructed mutationData object
mutate(mutationData);
}
mutate(values)
}
useNavigateOnSuccess(isSuccess, '/Coupon') useNavigateOnSuccess(isSuccess, '/Coupon')
@ -51,12 +60,16 @@ const EditPage = () => {
setObjectToEdit(data?.coupon); setObjectToEdit(data?.coupon);
}, [data]); }, [data?.coupon]);
const getValidationSchema = () => { const getValidationSchema = () => {
return null return null
}; };
if ( isLoading || !objectToEdit || isRefetching) {
return <Spin />
}
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit }; const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit };

View File

@ -27,30 +27,31 @@ export const getInitialValues = (objectToEdit: any | null = null): any => {
const products = [] as any; const products = [] as any;
const categories = [] as any; const categories = [] as any;
const language = localStorage.getItem("language") ?? "en"
// Map over the items array and push items into the appropriate array // Map over the items array and push items into the appropriate array
objectToEdit?.items?.forEach((item: any) => { objectToEdit?.items?.forEach((item: any) => {
if (item?.itemable_type === "product") { if (item?.itemable_type === "product") {
products.push({ value: item?.itemable?.name, label: item?.itemable?.name }); products.push({ value: item?.itemable?.id, label: item?.itemable?.name[language] });
} else if (item?.itemable_type === "category") { } else if (item?.itemable_type === "category") {
categories.push({ value: item?.itemable?.name, label: item?.itemable?.name }); categories.push({ value: item?.itemable?.id, label: item?.itemable?.name[language] });
} }
}); });
return { return {
id: objectToEdit?.id ?? 0, id: objectToEdit?.id ?? 0,
name: objectToEdit?.name ?? "", name: objectToEdit?.name ,
code: objectToEdit?.code ?? "", code: objectToEdit?.code ,
//@ts-ignore //@ts-ignore
active: objectToEdit?.active_to ? [dayjs(objectToEdit?.active_from), dayjs(objectToEdit?.active_to)] : "", active: objectToEdit?.active_to ? [dayjs(objectToEdit?.active_from), dayjs(objectToEdit?.active_to)] : "",
minimum_total_to_order: objectToEdit?.minimum_total_to_order ?? "", minimum_total_to_order: objectToEdit?.minimum_total_to_order ,
maximum_number_of_uses_per_user: objectToEdit?.maximum_number_of_uses_per_user ?? "", maximum_number_of_uses_per_user: objectToEdit?.maximum_number_of_uses_per_user ,
maximum_number_of_uses: objectToEdit?.maximum_number_of_uses ?? "", maximum_number_of_uses: objectToEdit?.maximum_number_of_uses ,
coupon_value: objectToEdit?.coupon_value ?? "", coupon_value: objectToEdit?.coupon_value ,
coupon_type: objectToEdit?.coupon_type ?? "", coupon_type: objectToEdit?.coupon_type ,
discount_type: objectToEdit?.discount_type ?? "", discount_type: objectToEdit?.discount_type ,
product_attr: products ?? "", product_attr: products ,
category_attr: categories ?? "", category_attr: categories ,
status: objectToEdit?.status ?? 0, status: objectToEdit?.status ?? 0,
@ -87,7 +88,6 @@ export const getValidationSchema = (editMode: boolean = false): Yup.Schema<any>
status: Yup.string().required('Required'), status: Yup.string().required('Required'),
active: Yup.mixed().required('Required'), active: Yup.mixed().required('Required'),
discount_type: Yup.string().required('Required'), discount_type: Yup.string().required('Required'),
coupon_type: Yup.string().required('Required'), coupon_type: Yup.string().required('Required'),
minimum_total_to_order: Yup.number().required('Required'), minimum_total_to_order: Yup.number().required('Required'),
maximum_number_of_uses: Yup.number().required('Required'), maximum_number_of_uses: Yup.number().required('Required'),

View File

@ -12,6 +12,8 @@ const useTableColumns :any = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const deleteMutation = useDeleteCoupon() const deleteMutation = useDeleteCoupon()
const navigate = useNavigate() const navigate = useNavigate()
const language = localStorage.getItem("language") ?? "en"
return useMemo( return useMemo(
() => [ () => [

View File

@ -23,7 +23,7 @@ function ProductsPage() {
<DashBody status={status as QueryStatusEnum} > <DashBody status={status as QueryStatusEnum} >
<DashHeader showAddButton={false} title={'products'}> <DashHeader showAddButton={false} title={'products'}>
<div className='RightSide d-flex gap-2 align-center '> <div className='RightSide d-flex gap-2 align-center '>
<SearchField/> <SearchField searchBy="name"/>
<AddButton onClick={()=>navigate('/products/add')}></AddButton> <AddButton onClick={()=>navigate('/products/add')}></AddButton>
</div> </div>

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import {getInitialValuesAdd as getInitialValues, getValidationSchema, getDataToSend } from '../formUtil' import { getInitialValuesAdd as getInitialValues, getValidationSchema, getDataToSend } from '../formUtil'
import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs' import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'; import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
@ -9,85 +9,130 @@ import { useTranslation } from 'react-i18next';
import { BsInfoCircle } from 'react-icons/bs'; import { BsInfoCircle } from 'react-icons/bs';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess'; import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import { useAddProduct, useAddProductVariation } from '../../../api/product'; import { useAddProduct, useAddProductVariation } from '../../../api/product';
import VarianInfo from './VarianInfo';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'; import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import AttributeInfo from './AttributeInfo'; import { TabsContainer } from './FormikTab/TabsContainer';
import { toast } from 'react-toastify';
// import AttributeInfo from './AttributeInfo';
const AddProductPage = () => { const AddProductPage = () => {
const { mutate, isLoading , data, isSuccess } = useAddProduct() const { mutate, isLoading, data, isSuccess } = useAddProduct()
const { mutate:AddVariation, isSuccess:SuccessVariation } = useAddProductVariation() const { mutate: AddVariation, isSuccess: SuccessVariation } = useAddProductVariation()
const [IsValed, setIsValed] = useState(false) const [IsValed, setIsValed] = useState(false)
const [infotaps , setInfoTaps] = useState<any[]>([]) const [infotaps, setInfoTaps] = useState<any[]>([])
const [Varibletaps , setVaribleTaps] = useState<any[]>([]) const [Varibletaps, setVaribleTaps] = useState<any[]>([])
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
function isValid() {
setInfoTaps(values?.info?.slice(1)?.map((taps: any) => {
return (changeShapeInfo(taps));
}));
setVaribleTaps(values?.variable?.slice(1))
mutate({
name: {
en: values?.name_en,
ar: values?.name_ar,
de: values?.name_de
},
category_id: 1
})
}
const validationResults: boolean[] = [];
values?.variable?.slice(1)?.forEach((item: any, index: any) => {
if (item && Object.keys(item).length > 0) { // Check if attrValueItem is defined and not empty
if (!item?.name_ar || !item?.name_en || !item?.name_de) {
toast.error(t('required_name') + ` ${index + 1}`);
validationResults.push(false);
}
else if (!item?.description_ar || !item?.description_en || !item?.description_de) {
toast.error(t('required_description') + ` ${index + 1}`);
validationResults.push(false);
} else if (item.main_photo === null || !item?.main_photo ) {
toast.error(t('required_main_photo') + ` ${index + 1}`);
validationResults.push(false);
}
else if (item.price === null || !item?.price) {
toast.error(t('required_price') + ` ${index + 1}`);
validationResults.push(false);
}
else {
validationResults.push(true);
}
}
});
if (validationResults.every((result) => result)) {
isValid();
}
setInfoTaps(values?.info?.slice(1)?.map((taps:any) => {
return (changeShapeInfo(taps));
}));
setVaribleTaps(values?.variable?.slice(1))
mutate({
name:{
en:values?.name_en,
ar:values?.name_ar,
de:values?.name_de
},
category_id:1
})
} }
useEffect(()=>{ useEffect(() => {
if(isSuccess){ if (isSuccess) {
const baseProductId = (data as any )?.id ; const baseProductId = (data as any)?.id;
console.log(infotaps); console.log(infotaps);
console.log(Varibletaps); console.log(Varibletaps);
Varibletaps?.map((dataToSend:any , index:number)=>{
const varible = dataToSend Varibletaps?.map((dataToSend: any, index: number) => {
const info = infotaps[index]
const jsonString = JSON.stringify(info); const varible = dataToSend
const info = varible?.info
const convertedArray = info.reduce((acc:any, obj:any) => {
acc[obj.Description] = obj.key;
return acc;
}, {});
const jsonString = JSON.stringify(convertedArray);
const Newproduct = { const Newproduct = {
name:{ name: {
en:varible?.name_en, en: varible?.name_en,
ar:varible?.name_ar, ar: varible?.name_ar,
de:varible?.name_de de: varible?.name_de
}, },
description:{ description: {
en:varible?.description_en, en: varible?.description_en,
ar:varible?.description_ar, ar: varible?.description_ar,
de:varible?.description_de de: varible?.description_de
}, },
quantity:varible?.quantity, quantity: varible?.quantity,
main_photo:varible?.main_photo, main_photo: varible?.main_photo,
images:varible?.images, images: varible?.images,
info : jsonString, info: jsonString,
product_attributes:[ price : varible?.price,
{attribute_value_id: 1, attribute_id: 1}
],
base_product_id:baseProductId product_attributes: varible?.attribute?.map((item: any, index: any) => {
return { attribute_value_id: item?.value, attribute_id: item?.id }
}),
base_product_id: baseProductId
} }
console.log(Newproduct); console.log(Newproduct);
AddVariation(Newproduct) AddVariation(Newproduct)
}) })
} }
},[isSuccess]) }, [isSuccess])
const { setObjectToEdit, objectToEdit } = usePageState() const { setObjectToEdit, objectToEdit } = usePageState()
useEffect(() => { useEffect(() => {
setObjectToEdit([]); setObjectToEdit([]);
}, []); }, []);
@ -104,26 +149,26 @@ const AddProductPage = () => {
<div className='ViewPage'> <div className='ViewPage'>
<ViewPage {...ViewProps}> <ViewPage {...ViewProps}>
<Tabs> <Tabs>
<TabList> <TabList>
<Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleInfo'>{t("Base_info")} </h6></div></Tab> <Tab><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><MdLanguage size={20} /></span> <h6 className='SingleInfo'>{t("Base_info")} </h6></div></Tab>
<Tab ><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><BsInfoCircle size={20} /></span> <h6 className='SingleInfo'>{t("VarianInfo")}</h6></div></Tab> <Tab ><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><BsInfoCircle size={20} /></span> <h6 className='SingleInfo'>{t("VarianInfo")}</h6></div></Tab>
{/* <Tab ><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><BsInfoCircle size={20} /></span> <h6 className='SingleInfo'>{t("AttributeInfo")}</h6></div></Tab> */} {/* <Tab ><div className='SignleDriverContainer'><span className='SignleDriverInfoIcon'><BsInfoCircle size={20} /></span> <h6 className='SingleInfo'>{t("AttributeInfo")}</h6></div></Tab> */}
</TabList> </TabList>
<TabBody > <TabBody >
<div className=" mt-4"><BasicInfo setIsValed={setIsValed} IsValed={IsValed} /></div> <div className=" mt-4"><BasicInfo setIsValed={setIsValed} IsValed={IsValed} /></div>
</TabBody> </TabBody>
<TabBody > <TabBody >
<div className=" mt-4"><VarianInfo /></div> <div className=" mt-4"><TabsContainer /></div>
</TabBody> </TabBody>
<TabBody > <TabBody >
{/* <div className=" mt-4"><AttributeInfo /></div> */} {/* <div className=" mt-4"><AttributeInfo /></div> */}
</TabBody> </TabBody>
</Tabs> </Tabs>
</ViewPage> </ViewPage>
@ -136,17 +181,17 @@ const AddProductPage = () => {
export default AddProductPage export default AddProductPage
function changeShapeInfo(originalObject:any){ function changeShapeInfo(originalObject: any) {
const transformedObject:any = {}; const transformedObject: any = {};
for (const key in originalObject) { for (const key in originalObject) {
if (originalObject.hasOwnProperty(key)) { if (originalObject.hasOwnProperty(key)) {
const index = key.split('.')[0]; // Extract index from key const index = key.split('.')[0]; // Extract index from key
const attribute = key.split('.')[1]; // Extract attribute from key const attribute = key.split('.')[1]; // Extract attribute from key
transformedObject[originalObject[`${index}.key`]] = originalObject[`${index}.Description`]; transformedObject[originalObject[`${index}.key`]] = originalObject[`${index}.Description`];
}
} }
}
return transformedObject return transformedObject
} }

View File

@ -1,37 +0,0 @@
import React from 'react';
import { useFormikContext } from 'formik';
import ValidationField from '../../../Components/ValidationField/ValidationField';
import { useGetSingleAttribute } from '../../../api/attribute';
const Attribute = () => {
const { values, setFieldValue } = useFormikContext<any>();
const { data: attributeData } = useGetSingleAttribute({ name: "product_id", id: values?.id });
const handleAttributeChange = (name: string, value: any) => {
setFieldValue(`attribute[${name}]`, value);
};
return (
attributeData?.data?.map((item: any) => {
const options = item?.attribute_value?.map((attr: any) => ({
label: attr?.value,
value: attr?.attribute_id
}));
return (
<ValidationField
key={item?.name}
name={`attribute[${item?.name}]`}
label={item?.name}
placeholder={item?.name}
type="Select"
option={options}
onChange={(value: any) => handleAttributeChange(item?.name, value)}
/>
);
})
);
};
export default Attribute;

View File

@ -1,34 +0,0 @@
import React, { useEffect, useState } from 'react'
import { Col, Row } from 'reactstrap'
import ValidationField from '../../../Components/ValidationField/ValidationField'
import { useTranslation } from 'react-i18next';
import { useFormikContext } from 'formik';
import { toast } from 'react-toastify';
import { useGetCategories } from '../../../api/Categories';
import useFormatToSelect from '../../../Hooks/useFormatToSelect';
const AttributeInfo = ({ setIsValed, IsValed }: any) => {
const [t] = useTranslation();
const formikContext = useFormikContext();
const Selectdata = [
{ label: "color", value:"color"}]
return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col>
<ValidationField name="name_ar" />
<ValidationField name="name_en" />
</Col>
<Col>
<ValidationField name="name_de" />
<ValidationField name="type" type="Select" label='type' placeholder='type' option={Selectdata} />
</Col>
</Row>
)
}
export default AttributeInfo

View File

@ -12,8 +12,14 @@ const BasicInfo = ({ setIsValed, IsValed }: any) => {
const formikContext = useFormikContext(); const formikContext = useFormikContext();
const { values, isValid } = formikContext; const { values, isValid } = formikContext;
const { data } = useGetCategories() const { data } = useGetCategories()
const SelectData = useFormatToSelect(data?.categories) const language = localStorage.getItem("language") ?? "en"
const SelectData = data?.categories?.map((item:any)=>(
{
label : item?.name[language],
value : item?.id
}
))
useEffect(() => { useEffect(() => {
const { name_ar, name_en, name_de, main_photo, category_id } = values as any; const { name_ar, name_en, name_de, main_photo, category_id } = values as any;

View File

@ -1,45 +0,0 @@
import React, { useEffect, useState } from 'react'
import { Col, Row } from 'reactstrap'
import ValidationField from '../../../../Components/ValidationField/ValidationField'
import { useTranslation } from 'react-i18next';
import { useFormikContext } from 'formik';
import { toast } from 'react-toastify';
import { useGetCategories } from '../../../../api/Categories';
import useFormatToSelect from '../../../../Hooks/useFormatToSelect';
const BasicInfo = ({ setIsValed, IsValed }: any) => {
const [t] = useTranslation();
const formikContext = useFormikContext();
const { values, isValid } = formikContext;
const { data } = useGetCategories()
const SelectData = useFormatToSelect(data?.categories)
useEffect(() => {
const { name_ar, name_en, name_de, main_photo, category_id } = values as any;
if (name_ar && name_en && name_de && main_photo && category_id && IsValed === false) {
toast.success(t("view_information_filed_fill_sucsessfully"));
setIsValed(true)
} else {
// console.log(isValid, "isValid");
}
}, [values]);
return (
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col>
<ValidationField name="name" />
</Col>
<Col>
<ValidationField name="category_id" type="Search" label='category' placeholder='category' option={SelectData} searchBy={"name"} />
</Col>
</Row>
)
}
export default BasicInfo

View File

@ -1,36 +0,0 @@
import React from 'react';
import { useFormikContext } from 'formik';
import ValidationField from '../../../../../../Components/ValidationField/ValidationField';
import { useGetSingleAttribute } from '../../../../../../api/attribute';
const Attribute = ({data,tabKey}:any) => {
const { values, setFieldValue } = useFormikContext<any>();
const handleAttributeChange = (name: string, value: any) => {
setFieldValue(`variable.${tabKey}.attribute"[${name}]`, value);
};
return (
data?.map((item: any) => {
const options = item?.attribute_value?.map((attr: any) => ({
label: attr?.value,
value: attr?.attribute_id
}));
return (
<ValidationField
key={item?.name}
name={`attribute[${item?.name}]`}
label={item?.name}
placeholder={item?.name}
type="Select"
option={options}
onChange={(value: any) => handleAttributeChange(item?.name, value)}
/>
);
})
);
};
export default Attribute;

View File

@ -1,64 +0,0 @@
import { Button, Upload, UploadFile } from 'antd'
import { UploadOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { useFormikContext } from 'formik';
import { ImageBaseURL } from '../../../../../../api/config';
const File = ({ tabKey}:any) => {
const { t } = useTranslation();
const formik = useFormikContext<any>();
const name = `variable[${tabKey}].${"main_photo"}`;
const imageUrl = formik?.values?.variable[tabKey]?.main_photo ? ImageBaseURL + formik?.values?.variable[tabKey]?.main_photo : "" ;
console.log(imageUrl);
const fileList: UploadFile[] = [
{
uid: '-1',
name: formik?.values?.variable[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

View File

@ -1,50 +0,0 @@
import { Button, Upload, UploadFile } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { useFormikContext } from 'formik';
import { BaseURL_IMAGE } from '../../../../../../api/config';
const MaltyFile = ({ tabKey }: any) => {
const { t } = useTranslation();
const formik = useFormikContext<any>();
const name = `variable[${tabKey}].Images`;
const imageFiles = formik.values?.variable?.[tabKey]?.Images || [];
const defaultFileList = imageFiles?.map((file: any, index: number) => ({
uid: `-${index}`,
name: file?.name, // Use a default name if file.name is undefined
status: 'done',
url: file ? URL.createObjectURL(file) : BaseURL_IMAGE + file?.path?.replace("public", "/storage"),
thumbUrl: file ?URL.createObjectURL(file):"",
}));
const FilehandleChange = ({ fileList }: { fileList: any }) => {
formik.setFieldValue(name, fileList.map((file: any) => file?.originFileObj));
};
const customRequest = async ({ onSuccess }: any) => {
onSuccess();
};
return (
<div className="ValidationField">
<label className="text">
{t(`Images`)}
</label>
<Upload
listType="picture"
defaultFileList={defaultFileList}
onChange={FilehandleChange}
customRequest={customRequest}
className="w-100"
maxCount={10}
>
<Button className="w-100" icon={<UploadOutlined />}>
{t("upload_image")}
</Button>
</Upload>
</div>
);
}
export default MaltyFile;

View File

@ -1,116 +0,0 @@
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';
import { objectToArray } from '../../../../../../utils/Array/ArrayToObjectFormik';
import { useTranslation } from 'react-i18next';
const ObjectField = ({tabKey}:any) => {
const [form] = Form.useForm();
const formik = useFormikContext<any>();
const [FieldItems, setFieldItems] = useState<any>(formik?.values?.info[tabKey])
const [t] = useTranslation()
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFieldItems((prevState:any) =>{
formik.setFieldValue(`info.${tabKey}`, {
...prevState,
[name]: value
});
return ({
...prevState,
[name]: value
})
} )
};
useEffect(() => {
if (formik?.values?.info[tabKey]) {
const defaultValues = formik.values.info[tabKey];
console.log(objectToArray( formik?.values?.info[tabKey]));
form.setFieldsValue({
items: [{ list:objectToArray( formik?.values?.info[tabKey])}]
});
}
else {
form.setFieldsValue({
items: [{ list: [{ key: '', Description: '' }] },], });
}
}, []); // Update when tabKey or info[tabKey] changes
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 }}>
{t("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, 'key']}>
<Input
placeholder={t("key")}
onChange={handleChange} // Assign onChange handler
name={`${subField.name}.key`} // Ensure proper name for dynamic state update
/>
</Form.Item>
<Form.Item noStyle name={[subField.name, 'Description']}>
<Input
placeholder={t("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>
{t("+ Add Another Item")}
</Button>
</div>
)}
</Form.List>
</Form.Item>
</div>
))}
</div>
)}
</Form.List>
</Form>
);
};
export default ObjectField

View File

@ -1,60 +0,0 @@
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

@ -1,41 +0,0 @@
import { Form, Select } from 'antd'
import { useFormikContext } from 'formik';
import React from 'react'
import { useTranslation } from 'react-i18next';
const SelectField = ({tabKey,option,name,id,label}: any) => {
const { t } = useTranslation();
const formik = useFormikContext<any>();
const Formikname = `variable[${tabKey}].${name}`;
const FormikValue = formik?.values?.variable[tabKey]?.[name];
const onChange = (value:any) => {
formik.setFieldValue(Formikname,[ {
attribute_value_id:value,
attribute_id:id
}])
console.log(value);
};
return (
<div className='ValidationField'>
<label className="text">
{t(`${label}`)}
</label>
<Select
placeholder={t(`${label}`)}
options={option}
size="large"
className={` w-100`}
defaultValue={FormikValue?.attribute_value_id}
allowClear
onChange={onChange}
/>
</div>
)
}
export default React.memo(SelectField);

View File

@ -1,20 +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">{label}</Label>
<Input value={value} type={type} onChange={onChange} />
</>
);
};

View File

@ -1,13 +0,0 @@
// TabItem.tsx
import React from 'react';
import { VariableTabs } from './VariableTabs';
interface TabItemProps {
UKey: any;
}
export const TabItem: React.FC<TabItemProps> = ({ UKey }) => {
return (
<VariableTabs tabKey={UKey} />
);
};

View File

@ -1,116 +0,0 @@
// TabsContainer.tsx
import React, { useEffect, useState } from 'react';
import { Tabs, Space } from 'antd';
import { CopyOutlined } from '@ant-design/icons';
import { TabItem } from './TabItem';
import { toast } from 'react-toastify';
import { FormikContext, FormikValues, useFormikContext } from 'formik';
import { useTranslation } from 'react-i18next';
const { TabPane } = Tabs;
const initialItemShape: any = {
label: 'variable 1',
key: '1',
closable: true,
};
export const TabsContainer: React.FC = () => {
const [activeKey, setActiveKey] = useState('1');
// const [items, setItems] = useState<TabItem[]>([]);
const [t] = useTranslation()
const { setFieldValue } = useFormikContext();
const formikContext = useFormikContext<FormikValues>();
const { values, handleChange } = formikContext;
const [width, setWidth] = useState(window.innerWidth);
const varianCount = values?.variable?.slice(1).map((item:any,index:any)=>{
return {
label: `${t(`variable`)}`+ `${index+1}`,
key: index+1,
closable: true,
}
})
const [items, setItems] = useState(varianCount);
const handleAdd = () => {
const newKey = `${items.length + 1}`;
setItems([...items, { key: newKey, label: `variable ${newKey}`, closable: true }]);
setActiveKey(newKey);
};
const handleDuplicate = (targetKey: string) => {
const targetItem = items.find((item:any) => item.key === targetKey);
if (targetItem) {
const newKey = `${items.length + 1}`;
const newItem = { ...targetItem, key: newKey, label: `variable ${newKey}` };
setItems([...items, newItem]);
setActiveKey(newKey);
const originalValues = values?.variable?.[targetKey];
setFieldValue(`variable.${newKey}`, originalValues);
const originalInfo = values?.info?.[targetKey];
console.log(originalInfo);
setFieldValue(`info.${newKey}`, originalInfo);
}
};
const handleRemove = (targetKey: string) => {
const newItems = items.filter((item:any) => item.key !== targetKey);
if (newItems.length > 0) {
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
setItems(newItems);
setActiveKey(newActiveKey);
} else {
toast.error("Cannot close the last tab");
}
};
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}
>
{items.map((item :any) =>{
return (
<TabPane
key={item?.key}
tab={
<Space>
{t(`${item.label}`)}
<CopyOutlined onClick={() => handleDuplicate(item.key)} />
</Space>
}
closable={item.closable}
>
<TabItem UKey={item?.key} />
</TabPane>
)
})}
</Tabs>
);
};

View File

@ -1,71 +0,0 @@
// VariableTabs.tsx
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Col, Row } from 'reactstrap';
import { FormItem } from './FormItem';
import { useFormikContext, FormikValues } from 'formik';
import File from './Field/File';
import MaltyFile from './Field/FileImage';
import Select from './Field/Select';
import ObjectField from './Field/Object';
import Atteibute from './Field/Atteibute';
interface VariableTabsProps {
tabKey: string;
}
export const VariableTabs: React.FC<VariableTabsProps> = ({ tabKey }) => {
const { t } = useTranslation();
const formikContext = useFormikContext<FormikValues>();
const { values, handleChange } = formikContext;
const handleFieldChange = (fieldName: string) => (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement> | any
) => {
handleChange(`variable.${tabKey}.${fieldName}`)(e); // Prepend "variable"
};
const FormikName = (FormikFieldname: any) => values?.variable?.[tabKey]?.[FormikFieldname];
return (
<>
<h5>variables {tabKey}</h5>
<Row xs={1} sm={1} md={1} lg={2} xl={2}>
<Col>
<FormItem
label={t(`name`)}
value={FormikName("name")}
onChange={handleFieldChange('name')}
/>
{values?.other_attributes &&
<Atteibute data={values?.other_attributes} tabKey={tabKey} />
}
<ObjectField tabKey={tabKey}/>
</Col>
<Col>
<FormItem
label={t(`description`)}
value={FormikName("description")}
onChange={handleFieldChange('description')}
/>
<FormItem
label={t(`price`)}
value={FormikName("price")}
onChange={handleFieldChange('price')}
type="number"
/>
<File tabKey={tabKey}/>
<MaltyFile tabKey={tabKey}/>
</Col>
</Row>
</>
);
};

View File

@ -1,13 +0,0 @@
import React, { useState } from 'react'
import { TabsContainer } from './FormikTab/TabsContainer'
const VarianInfo = () => {
return (
<div className='VarianInfo'>
<TabsContainer/>
</div>
)
}
export default VarianInfo

View File

@ -4,100 +4,289 @@ import { Tab, TabList, TabPanel as TabBody, Tabs } from 'react-tabs'
import 'react-tabs/style/react-tabs.css'; import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
import ViewPage from '../../../Layout/Dashboard/ViewPage'; import ViewPage from '../../../Layout/Dashboard/ViewPage';
import BasicInfo from './Edit/BasicInfo';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'; import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import LoadingPage from '../../../Layout/app/LoadingPage'; import LoadingPage from '../../../Layout/app/LoadingPage';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BsInfoCircle } from 'react-icons/bs'; import { BsInfoCircle } from 'react-icons/bs';
import { useGetOneProduct, useUpdateProduct, useUpdateProductVariation } from '../../../api/product'; import { useAddProductVariation, useDeleteProductVariation, useGetOneProduct, useUpdateProduct, useUpdateProductVariation } from '../../../api/product';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import VarianInfo from './Edit/VarianInfo';
import { changeShapeInfo } from '../../../utils/Array/changeShapeInfo'; import { changeShapeInfo } from '../../../utils/Array/changeShapeInfo';
import { Spin } from 'antd'; import { Spin } from 'antd';
import BasicInfo from './BasicInfo';
import { TabsContainer } from './FormikTab/TabsContainer';
import { toast } from 'react-toastify';
const ViewProduct = () => { const ViewProduct = () => {
const { setObjectToEdit, objectToEdit } = usePageState() const { setObjectToEdit, objectToEdit } = usePageState()
const { t } = useTranslation(); const { t } = useTranslation();
const { id } = useParams() const { id } = useParams()
const { data , isLoading,isRefetching} = useGetOneProduct({ id: id }) const { data, isLoading, isRefetching } = useGetOneProduct({ id: id })
const [Data, setData] = useState([])
const { mutate, isSuccess } = useUpdateProduct() const [OldData, setOldData] = useState(data?.data?.products)
const { mutate: AddVariation, isSuccess: SuccessVariation } = useUpdateProductVariation() const { mutate, isSuccess } = useUpdateProduct('put')
const [infotaps, setInfoTaps] = useState<any[]>([]) const { mutate: UpdateVariation, isSuccess: UpdetedSuccessVariation } = useUpdateProductVariation()
const { mutate: AddVariation, isSuccess: AddedSuccessVariation, data: ProductVariationData } = useAddProductVariation()
const { mutate: DeleteVariation } = useDeleteProductVariation()
const [removedVariant, setremovedVariant] = useState<any[]>([])
const [Variant, setVariant] = useState<any>([])
const [InfoTaps, setInfoTaps] = useState<any>([])
const [Varibletaps, setVaribleTaps] = useState<any[]>([])
const handleSubmit = (values: any) => { const handleSubmit = (values: any) => {
// Update removedVarianteValues state
console.log(values, "values");
function isValid() {
setremovedVariant(values?.removedVariant);
const variables = values?.variable?.slice(1);
if (variables) {
variables.forEach((item: any, index: number) => {
setVariant((prevEditAttribute: any) => [...prevEditAttribute, item]);
})
};
const newData = {
name: {
en: values?.name_en,
ar: values?.name_ar,
de: values?.name_de
},
category_id: values?.category_id
};
// Uncomment this line to perform the mutation
mutate(newData);
}
const validationResults: boolean[] = [];
values?.variable?.slice(1)?.forEach((item: any, index: any) => {
if (item && Object.keys(item).length > 0) { // Check if attrValueItem is defined and not empty
if (!item?.name_ar || !item?.name_en || !item?.name_de) {
toast.error(t('required_name') + ` ${index + 1}`);
validationResults.push(false);
}
else if (!item?.description_ar || !item?.description_en || !item?.description_de) {
toast.error(t('required_description') + ` ${index + 1}`);
validationResults.push(false);
} else if (item.main_photo === null || !item?.main_photo ) {
toast.error(t('required_main_photo') + ` ${index + 1}`);
validationResults.push(false);
}
else if (item.price === null || !item?.price) {
toast.error(t('required_price') + ` ${index + 1}`);
validationResults.push(false);
}
else {
validationResults.push(true);
}
}
});
setInfoTaps(values?.info?.slice(1)?.map((taps: any) => {
return (changeShapeInfo(taps));
}));
setVaribleTaps(values?.variable?.slice(1))
mutate({ if (validationResults.every((result) => result)) {
name: values?.name, isValid();
category_id: 1 }
})
};
}
useEffect(() => { useEffect(() => {
if (isSuccess) { if (isSuccess) {
const baseProductId = (data as any)?.id; const baseProductId = id;
console.log(infotaps);
console.log(Varibletaps);
Varibletaps?.map((dataToSend: any, index: number) => {
Variant?.map((dataToSend: any, index: number) => {
console.log(dataToSend, "dataToSend");
const varible = dataToSend const varible = dataToSend
const info = infotaps[index]
const jsonString = JSON.stringify(info); if (varible?.id && varible?.id !== null) {
const foundObject = OldData.find((item: any) => item.id === varible?.id) as any;
const Newproduct : any = { const info = varible?.info
name: varible?.name, console.log(info, "info");
description: varible?.description,
quantity: varible?.quantity, const convertedArray = info.reduce((acc:any, obj:any) => {
info: jsonString, acc[obj.Description] = obj.key;
product_attributes: [ return acc;
{ attribute_value_id: 1, attribute_id: 1 } }, {});
], const jsonString = JSON.stringify(convertedArray);
base_product_id: baseProductId console.log(jsonString, "jsonStringinfo");
const Editedproduct = {
name: {
en: varible?.name_en,
ar: varible?.name_ar,
de: varible?.name_de
},
description: {
en: varible?.description_en,
ar: varible?.description_ar,
de: varible?.description_de
},
quantity: varible?.quantity,
main_photo: varible?.main_photo,
images: varible?.images,
info: jsonString,
price: varible?.price,
product_attributes: varible?.attribute?.map((item: any, index: any) => {
return { attribute_value_id: item?.value, attribute_id: item?.id }
}),
}
if (foundObject) {
Object.keys(Editedproduct).forEach((propName: any) => {
if (foundObject.hasOwnProperty(propName)) {
const foundValue = foundObject[propName];
//@ts-ignore
const editedValue = Editedproduct[propName];
if (foundValue === editedValue) {
//@ts-ignore
delete Editedproduct[propName];
}
}
});
if (foundObject.name &&
foundObject.name.en === Editedproduct.name.en &&
foundObject.name.ar === Editedproduct.name.ar &&
foundObject.name.de === Editedproduct.name.de) {
//@ts-ignore
delete Editedproduct.name;
}
if (foundObject.description &&
foundObject.description.en === Editedproduct.description.en &&
foundObject.description.ar === Editedproduct.description.ar &&
foundObject.description.de === Editedproduct.description.de) {
//@ts-ignore
delete Editedproduct.description;
}
Object.keys(Editedproduct).forEach((key: any) => {
// Check if the property value is undefined
//@ts-ignore
if (Editedproduct[key] === undefined) {
// Remove the property
//@ts-ignore
delete Editedproduct[key];
}
});
if (convertedArray && foundObject.info) {
const editedInfoKeys = Object.keys(convertedArray);
const foundInfoKeys = Object.keys(foundObject.info);
console.log(editedInfoKeys,"editedInfoKeys");
console.log(foundInfoKeys,"foundInfoKeys");
// Check if the number of keys is the same
if (editedInfoKeys.length === foundInfoKeys.length) {
// Check if all keys and their corresponding values are the same
const keysAreEqual = editedInfoKeys.every((key: any) => {
//@ts-ignore
console.log(convertedArray[key] ,"convertedArray[key] ");
console.log(foundObject.info[key],"foundObject.info[key]");
return convertedArray[key] === foundObject.info[key];
});
if (keysAreEqual) {
// Remove the info property from Editedproduct
//@ts-ignore
delete Editedproduct.info;
}
}
}
if (Object.keys(Editedproduct).length > 0) {
//@ts-ignore
Editedproduct._method = "PUT";
//@ts-ignore
Editedproduct.id = foundObject?.id;
console.log(Editedproduct, "Editedproduct");
UpdateVariation(Editedproduct)
}
}
} else {
const info = varible?.info
const convertedArray = info?.reduce((acc:any, obj:any) => {
acc[obj.Description] = obj.key;
return acc;
}, {});
const jsonString = JSON.stringify(convertedArray);
const Newproduct = {
name: {
en: varible?.name_en,
ar: varible?.name_ar,
de: varible?.name_de
},
description: {
en: varible?.description_en,
ar: varible?.description_ar,
de: varible?.description_de
},
quantity: varible?.quantity,
main_photo: varible?.main_photo,
images: varible?.images,
info: jsonString,
price: varible?.price,
base_product_id: id,
product_attributes: varible?.attribute?.map((item: any, index: any) => {
return { attribute_value_id: item?.value, attribute_id: item?.id }
}),
}
AddVariation(Newproduct)
} }
if (data?.product?.images !== varible?.images) {
Newproduct.images = varible?.images ;
}
if (data?.product?.main_photo?.replace("public", "/storage") !== varible?.main_photo) {
Newproduct.main_photo = varible?.main_photo ;
console.log(data?.product?.main_photo?.replace("public", "/storage"));
}
AddVariation(Newproduct)
}) })
console.log(removedVariant);
removedVariant?.map((item: any) => {
return DeleteVariation({ id: item })
})
} }
}, [isSuccess]) }, [isSuccess])
useNavigateOnSuccess(isSuccess, '/products') // useNavigateOnSuccess(UpdetedSuccessVariation || AddedSuccessVariation, '/products')
useEffect(() => { useEffect(() => {
// refetch() // refetch()
setObjectToEdit(data?.data); setObjectToEdit(data?.data);
}, [data,id,isRefetching]); setOldData(data?.data?.products)
}, [data, id, isRefetching]);
const getValidationSchema = () => { const getValidationSchema = () => {
return null return null
}; };
if(isRefetching){ if (isRefetching) {
return <Spin/> return <Spin />
} }
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit }; const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit };
@ -119,7 +308,7 @@ const ViewProduct = () => {
<div className=" mt-4"><BasicInfo /></div> <div className=" mt-4"><BasicInfo /></div>
</TabBody> </TabBody>
<TabBody > <TabBody >
<div className=" mt-4"> {isLoading ? <Spin/> : <VarianInfo />} </div> <div className=" mt-4"> {isLoading ? <Spin /> : <TabsContainer />} </div>
</TabBody> </TabBody>
</Tabs> </Tabs>

View File

@ -2,33 +2,58 @@ import React from 'react';
import { useFormikContext } from 'formik'; import { useFormikContext } from 'formik';
import ValidationField from '../../../../../Components/ValidationField/ValidationField'; import ValidationField from '../../../../../Components/ValidationField/ValidationField';
import { useGetSingleAttribute } from '../../../../../api/attribute'; import { useGetSingleAttribute } from '../../../../../api/attribute';
import { Select } from 'antd';
import { useTranslation } from 'react-i18next';
const Attribute = ({tabKey}:any) => { const Attribute = ({ tabKey }: any) => {
const { values, setFieldValue } = useFormikContext<any>(); const { values, setFieldValue } = useFormikContext<any>();
const language = localStorage.getItem("language") ?? "en";
const [t] = useTranslation()
const { data: attributeData } = useGetSingleAttribute({ name: "category_id", id: values?.category_id }); const { data: attributeData } = useGetSingleAttribute({ name: "category_id", id: values?.category_id });
const handleAttributeChange = (name: string, value: any) => { const handleAttributeChange = (value: any, option: any) => {
setFieldValue(`variable.${tabKey}.attribute"[${name}]`, value); setFieldValue(`variable[${tabKey}].attribute`, option);
}; };
return ( return (
attributeData?.data?.map((item: any) => { attributeData?.data?.map((item: any) => {
const options = item?.attribute_value?.map((attr: any) => ({ const uniqueOptionsMap = new Map();
label: attr?.value, item?.attribute_value.forEach((attr: any) => {
value: attr?.attribute_id if (!uniqueOptionsMap.has(attr.value[language])) {
uniqueOptionsMap.set(attr.value[language], { attribute_id: attr.attribute_id, id: attr.id });
}
});
const options = Array.from(uniqueOptionsMap.entries()).map(([label, value]) => ({
label,
value: value.attribute_id, // Change value to attribute_id
id: value.id, // Include id in the option
})); }));
return ( return (
<ValidationField <div className='ValidationField'>
key={item?.name}
name={`attribute[${item?.name}]`} <label htmlFor={item?.name[language]} className="text">
label={item?.name} {t(`${item?.name[language]}`)}
placeholder={item?.name}
type="Select" <Select
option={options} placeholder={t(`${item?.name[language]}`)}
onChange={(value: any) => handleAttributeChange(item?.name, value)} options={options}
/> size="large"
className={`w-100`}
defaultValue={values?.variable[tabKey]?.attribute}
allowClear
mode={"multiple" }
onChange={handleAttributeChange}
/>
</label>
</div>
); );
}) })
); );

View File

@ -11,17 +11,17 @@ import { ImageBaseURL } from '../../../../../api/config';
const File = ({ tabKey}:any) => { const File = ({ tabKey}:any) => {
const { t } = useTranslation(); const { t } = useTranslation();
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const name = `variable[${tabKey}].${"main_photo"}`; const name = `variable[${tabKey}].${"main_photo"}`;
const imageUrl = formik?.values?.variable[tabKey]?.main_photo ? URL.createObjectURL(formik?.values?.variable[tabKey]?.main_photo) : "" ; let FormikName = formik.values?.variable[tabKey]?.main_photo;
const imageUrl = FormikName ? ImageBaseURL + FormikName : '';
const fileList: UploadFile[] = [ const fileList: UploadFile[] = [
{ {
uid: '-1', uid: '-1',
name: formik?.values?.variable[tabKey]?.main_photo?.name ?? "", name: '',
status: 'done', status: 'done',
url: imageUrl , url: imageUrl?.replace("public", "/storage"),
thumbUrl: imageUrl , thumbUrl: imageUrl?.replace("public", "/storage")
} }
]; ];
const FilehandleChange = (value:any) => { const FilehandleChange = (value:any) => {

View File

@ -1,25 +1,34 @@
import { Button, Upload, UploadFile } from 'antd'; import { Button, Upload } from 'antd';
import { UploadOutlined } from '@ant-design/icons'; import { UploadOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useFormikContext } from 'formik'; import { useFormikContext } from 'formik';
import { ImageBaseURL } from '../../../../../api/config';
const MaltyFile = ({ tabKey }: any) => { const MaltyFile = ({ tabKey }: any) => {
const { t } = useTranslation(); const { t } = useTranslation();
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const name = `variable[${tabKey}].images`; const name = `variable[${tabKey}].${"images"}`;
const imageFiles = formik.values?.variable?.[tabKey]?.images || []; // Construct imageUrl and fileList for each file
const defaultFileList = imageFiles?.map((file: any, index: number) => ({ const files = formik.values?.variable[tabKey]?.images || [];
uid: `-${index}`, const fileItems = files.map((file: any, index: number) => {
name: file?.name, // Use a default name if file.name is undefined const imageUrl = file ? ImageBaseURL + file : '';
status: 'done', return {
url: file ? URL?.createObjectURL(file) : "", uid: `-${index}`,
thumbUrl: file ?URL?.createObjectURL(file):"", name: file?.name || '',
})); status: 'done',
url: imageUrl?.replace("public", "/storage"),
thumbUrl: imageUrl?.replace("public", "/storage")
};
});
const FilehandleChange = ({ fileList }: { fileList: any }) => { const FilehandleChange = ({ fileList }: { fileList: any }) => {
formik.setFieldValue(name, fileList.map((file: any) => file?.originFileObj)); console.log(fileList);
};
formik.setFieldValue(
name,
fileList.map((file: any) => (file?.originFileObj ? file.originFileObj : file.url))
); };
const customRequest = async ({ onSuccess }: any) => { const customRequest = async ({ onSuccess }: any) => {
onSuccess(); onSuccess();
@ -32,7 +41,7 @@ const MaltyFile = ({ tabKey }: any) => {
</label> </label>
<Upload <Upload
listType="picture" listType="picture"
defaultFileList={defaultFileList} defaultFileList={fileItems}
onChange={FilehandleChange} onChange={FilehandleChange}
customRequest={customRequest} customRequest={customRequest}
className="w-100" className="w-100"
@ -46,4 +55,4 @@ const MaltyFile = ({ tabKey }: any) => {
); );
} }
export default MaltyFile; export default MaltyFile

View File

@ -1,52 +1,41 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
import { Button, Card, Form, Input, Space, Typography } from 'antd'; import { Button, Form, Input, Space, Typography } from 'antd';
import { useFormikContext } from 'formik'; import { useFormikContext } from 'formik';
import { objectToArray } from '../../../../../utils/Array/ArrayToObjectFormik';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
const ObjectField = ({tabKey}:any) => { const ObjectField = ({ tabKey }: any) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const formik = useFormikContext<any>(); const formik = useFormikContext<any>();
const [FieldItems, setFieldItems] = useState<any>(formik?.values?.info[tabKey]) const [FieldItems, setFieldItems] = useState<any>([]);
const [t] = useTranslation() const [t] = useTranslation();
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const initialValues = formik?.values?.variable[tabKey]?.info;
const { name, value } = e.target;
setFieldItems((prevState:any) =>{ const handleChange = (index: number, fieldKey: string, value: string) => {
const updatedItems = [...FieldItems];
formik.setFieldValue(`info.${tabKey}`, { updatedItems[index][fieldKey] = value;
...prevState, setFieldItems(updatedItems);
[name]: value formik.setFieldValue(`variable.${tabKey}.info`, updatedItems);
});
return ({
...prevState,
[name]: value
})
} )
}; };
useEffect(() => { useEffect(() => {
if (initialValues) {
if (formik?.values?.info[tabKey]) { setFieldItems([...initialValues]);
const defaultValues = formik.values.info[tabKey]; } else {
setFieldItems([{ Description: '', key: '' }]);
console.log(objectToArray( formik?.values?.info[tabKey]));
form.setFieldsValue({
items: [{ list:objectToArray( formik?.values?.info[tabKey])}]
});
} }
else { }, [tabKey]); // Update when tabKey or info[tabKey] changes
form.setFieldsValue({
items: [{ list: [{ key: '', Description: '' }] },], }); const removeItem = (index: number) => {
} const updatedItems = [...FieldItems];
}, []); // Update when tabKey or info[tabKey] changes updatedItems.splice(index, 1);
setFieldItems(updatedItems);
formik.setFieldValue(`variable.${tabKey}.info`, updatedItems);
};
useEffect(() => {
console.log(initialValues);
}, [initialValues])
return ( return (
<Form <Form
@ -57,60 +46,34 @@ const ObjectField = ({tabKey}:any) => {
style={{ width: '100%' }} // Set width to 100% style={{ width: '100%' }} // Set width to 100%
autoComplete="off" autoComplete="off"
> >
<Form.List name="items"> <Typography.Text strong className='Information'>
{(fields, { add, remove }) => ( {t("Information")}
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}> </Typography.Text>
{fields.map((field, index) => ( {FieldItems.map((item: any, index: number) => (
<div key={field.key}> <Space key={index} style={{ marginBottom: 16 }}>
<Typography.Text strong style={{ marginBottom: 8 }}>
{t("Information")} <Form.Item>
</Typography.Text> <Input
placeholder={t("key")}
{/* Nested Form.List for sub-items */} value={item.key}
<Form.Item> onChange={(e) => handleChange(index, 'key', e.target.value)}
<Form.List name={[field.name, 'list']}> />
{(subFields, subOpt) => ( </Form.Item>
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}> <Form.Item>
{subFields.map((subField) => ( <Input
<Space key={subField.key}> placeholder={t("Description")}
<Form.Item noStyle name={[subField.name, 'key']}> value={item.Description}
<Input onChange={(e) => handleChange(index, 'Description', e.target.value)}
placeholder={t("key")} />
</Form.Item>
onChange={handleChange} // Assign onChange handler <CloseOutlined onClick={() => removeItem(index)} />
name={`${subField.name}.key`} // Ensure proper name for dynamic state update </Space>
/> ))}
</Form.Item> <Button type="dashed" onClick={() => setFieldItems([...FieldItems, { Description: '', key: '' }])} block>
<Form.Item noStyle name={[subField.name, 'Description']}> {t("+ Add Another Item")}
<Input </Button>
placeholder={t("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>
{t("+ Add Another Item")}
</Button>
</div>
)}
</Form.List>
</Form.Item>
</div>
))}
</div>
)}
</Form.List>
</Form> </Form>
); );
}; };
export default ObjectField export default ObjectField;

View File

@ -1,60 +0,0 @@
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

@ -1,41 +0,0 @@
import { Form, Select } from 'antd'
import { useFormikContext } from 'formik';
import React from 'react'
import { useTranslation } from 'react-i18next';
const SelectField = ({tabKey,option,name,id,label}: any) => {
const { t } = useTranslation();
const formik = useFormikContext<any>();
const Formikname = `variable[${tabKey}].${name}`;
const FormikValue = formik?.values?.variable[tabKey]?.[name];
const onChange = (value:any) => {
formik.setFieldValue(Formikname,[ {
attribute_value_id:value,
attribute_id:id
}])
console.log(value);
};
return (
<div className='ValidationField'>
<label className="text">
{t(`${label}`)}
</label>
<Select
placeholder={t(`${label}`)}
options={option}
size="large"
className={` w-100`}
defaultValue={FormikValue?.attribute_value_id}
allowClear
onChange={onChange}
/>
</div>
)
}
export default React.memo(SelectField);

View File

@ -1,13 +0,0 @@
// TabItem.tsx
import React from 'react';
import { VariableTabs } from './VariableTabs';
interface TabItemProps {
UKey: any;
}
export const TabItem: React.FC<TabItemProps> = ({ UKey }) => {
return (
<VariableTabs tabKey={UKey} />
);
};

View File

@ -2,76 +2,105 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Tabs, Space } from 'antd'; import { Tabs, Space } from 'antd';
import { CopyOutlined } from '@ant-design/icons'; import { CopyOutlined } from '@ant-design/icons';
import { TabItem } from './TabItem';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { FormikValues, useFormikContext } from 'formik'; import { FormikValues, useFormikContext } from 'formik';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useProductVarianState } from '../../../../lib/state mangment/Pages/Products'; import { useProductVarianState } from '../../../../lib/state mangment/Pages/Products';
import { VariableTabs } from './VariableTabs';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const initialItemShape: any = {
label: 'variable 1', export const TabsContainer: React.FC = () => {
const [activeKey, setActiveKey] = useState('1');
const [t] = useTranslation()
const initialItemShape: any = {
label: `${t(`variant`)} 1`,
key: '1', key: '1',
closable: true, closable: true,
}; };
export const TabsContainer: React.FC = () => {
const [activeKey, setActiveKey] = useState('1');
// const [items, setItems] = useState<TabItem[]>([]);
const [items, setItems] = useState([initialItemShape]);
const { setFieldValue } = useFormikContext();
const formikContext = useFormikContext<FormikValues>(); const formikContext = useFormikContext<FormikValues>();
const { values, handleChange } = formikContext; const { setFieldValue } = useFormikContext();
const [width, setWidth] = useState(window.innerWidth); const { values, handleChange } = formikContext;
// const {setTapItems,TapItems,TapItemValues,setTapItemValues} = useProductVarianState(state => state) const varianCount = values?.variable?.slice(1)?.map((item:any,index:any)=>{
// useEffect(() => { return {
// setTapItems(items) label: `${t(`variant`)}`+ `${index+1}`,
// }, [items]) key: index+1,
// useEffect(() => { closable: true,
// setTapItemValues(values?.variable) }
// }, [values?.variable]) })?? initialItemShape
const [items, setItems] = useState(varianCount ?? [initialItemShape]); // Ensure items is always an array
const [width, setWidth] = useState(window.innerWidth);
const [t] = useTranslation() 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 handleAdd = () => {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
setItems([...items, { key: newKey, label: `variable ${newKey}`, closable: true }]); setItems([...items, { key: newKey, label: `${t(`variant`)} ${newKey}`, closable: true }]);
setActiveKey(newKey); setActiveKey(newKey);
}; };
const handleDuplicate = (targetKey: string) => { const handleDuplicate = (targetKey: string) => {
const targetItem = items.find((item) => item.key === targetKey); const targetItem = items.find((item:any) => item.key === targetKey);
if (targetItem) { if (targetItem) {
const newKey = `${items.length + 1}`; const newKey = `${nextKey}`;
const newItem = { ...targetItem, key: newKey, label: `variable ${newKey}` }; const newItem = { ...targetItem, key: newKey, label: `${t(`variant`)} ${newKey}` };
setItems([...items, newItem]); setItems([...items, newItem]);
setActiveKey(newKey); setActiveKey(newKey);
const originalValues = values?.variable?.[targetKey]; const originalValues = values?.variable?.[targetKey];
setFieldValue(`variable.${newKey}`, originalValues); setFieldValue(`variable.${newKey}`, {...originalValues,id:null});
const originalInfo = values?.info?.[targetKey]; const originalInfo = values?.info?.[targetKey];
console.log(originalInfo);
setFieldValue(`info.${newKey}`, originalInfo); setFieldValue(`info.${newKey}`, originalInfo);
const originalvariable = values?.variable[targetKey]?.variable;
setFieldValue(`variable.${newKey}.variable`, originalvariable);
} }
}; };
const [removedVariant, setremovedVariant] = useState<string[]>([]);
useEffect(() => {
setFieldValue(`removedVariant`, removedVariant);
}, [removedVariant]);
const handleRemove = (targetKey: string) => { const handleRemove = (targetKey: string) => {
const newItems = items.filter((item) => item.key !== targetKey); const newItems = items.filter((item:any) => item.key !== targetKey);
if (newItems.length > 0) { const removedItem = values?.variable[targetKey] as any;
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1'; if (removedItem?.id) {
setremovedVariant((prevRemovedvariable) => [...prevRemovedvariable, removedItem.id]);
}
const newActiveKey = newItems.length ? newItems[newItems.length - 1].key : '1';
setItems(newItems); setItems(newItems);
setActiveKey(newActiveKey); setActiveKey(newActiveKey);
setFieldValue(`variable.${targetKey}`, undefined); setFieldValue(`variable.${targetKey}`, undefined);
setFieldValue(`info.${targetKey}`, undefined); setFieldValue(`info.${targetKey}`, undefined);
} else {
toast.error("Cannot close the last tab");
}
}; };
useEffect(() => { useEffect(() => {
@ -87,32 +116,30 @@ useEffect(() => {
}, []); }, []);
const tabPosition = width > 1000 ? 'left' : 'top'; const tabPosition = width > 1000 ? 'left' : 'top';
return ( return (
<Tabs <>
type="editable-card" <Tabs
onChange={setActiveKey} type="editable-card"
activeKey={activeKey} onChange={setActiveKey}
onEdit={(targetKey:any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))} activeKey={activeKey}
tabPosition={tabPosition} onEdit={(targetKey: any, action) => (action === 'add' ? handleAdd() : handleRemove(targetKey))}
tabPosition={tabPosition}
> items={
{items.map((item :any) =>{ items.map((item: any) => ({
return ( label: <Space>{t(`${item.label}`)} <CopyOutlined onClick={() => handleDuplicate(item.key)} /></Space>,
children: <VariableTabs tabKey={item.key} />,
key: item.key,
closable: item.closable,
}))
}
>
<TabPane </Tabs>
key={item?.key} { items.length === 0 && (
tab={ <h6 className='AddNewTabText'>{t("Add New Variant")}</h6>
<Space>
{t(`${item.label}`)} )}
<CopyOutlined onClick={() => handleDuplicate(item.key)} /> </>
</Space> );
}
closable={item.closable}
>
<TabItem UKey={item?.key} />
</TabPane>
)
})}
</Tabs>
);
}; };

View File

@ -7,6 +7,7 @@ import File from './Field/File';
import MaltyFile from './Field/FileImage'; import MaltyFile from './Field/FileImage';
import ObjectField from './Field/Object'; import ObjectField from './Field/Object';
import Atteibute from './Field/Atteibute'; import Atteibute from './Field/Atteibute';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
interface VariableTabsProps { interface VariableTabsProps {
@ -59,6 +60,7 @@ export const VariableTabs: React.FC<VariableTabsProps> = ({ tabKey }) => {
{values?.category_id && {values?.category_id &&
<Atteibute tabKey={tabKey} /> <Atteibute tabKey={tabKey} />
} }
<ObjectField tabKey={tabKey} /> <ObjectField tabKey={tabKey} />
</Col> </Col>
<Col> <Col>

View File

@ -1,13 +0,0 @@
import React, { useState } from 'react'
import { TabsContainer } from './FormikTab/TabsContainer'
const VarianInfo = () => {
return (
<div className='VarianInfo'>
<TabsContainer/>
</div>
)
}
export default VarianInfo

View File

@ -1,50 +1,63 @@
import * as Yup from "yup"; import * as Yup from "yup";
import { ImageBaseURL } from "../../api/config";
export const getInitialValues = (objectToEdit: any | null = null) => { export const getInitialValues = (objectToEdit: any) => {
const product = Array.isArray(objectToEdit?.product) ? objectToEdit?.product.map((item: any) => ({ if (!objectToEdit || !objectToEdit.products) {
name: item?.name, return {};
description: item?.description, }
images: item?.images, const products = objectToEdit?.products.map((item: any) => {
main_photo: item?.main_photo, if (!item || !item.info) {
price: item?.price, return {};
quantity: item?.quantity,
product_attributes: item?.product_attributes,
})) : (
{
...objectToEdit?.product,
main_photo: objectToEdit?.product?.main_photo?.replace("public", "/storage"),
} }
); const formattedData = Object.entries(item?.info).map(([key, value]) => ({
console.log(product, "product"); [`Description`]: key,
[`key`]: value,
}));
return ({
name_ar: item?.name["ar"],
name_en: item?.name["en"],
name_de: item?.name["de"],
description_ar: item?.description["ar"],
description_en: item?.description["en"],
description_de: item?.description["de"],
images: item?.images,
main_photo: item?.main_photo,
price: item?.price,
quantity: item?.quantity,
products_attributes: item?.products_attributes,
id:item?.id,
info:formattedData
})
})
const productInfo = objectToEdit?.product?.info || {}; // Ensure product.info exists and initialize as an empty object if it doesn't const productsInfo = objectToEdit?.products?.info || {};
const formattedData = Object.entries(productInfo).map(([key, value], index) => ({ const formattedData = Object.entries(productsInfo).map(([key, value], index) => ({
[`${index}.Description`]: key, [`${index}.Description`]: key,
[`${index}.key`]: value, [`${index}.key`]: value,
})); }));
const info = [undefined, ...formattedData];
return { return {
id: objectToEdit?.id ?? 0, id:objectToEdit?.id,
name: objectToEdit?.name ?? "", name: objectToEdit?.name ?? "",
name_ar: objectToEdit?.name?.ar ?? '', name_ar: objectToEdit?.name?.ar ?? '',
name_en: objectToEdit?.name?.en ?? '', name_en: objectToEdit?.name?.en ?? '',
name_de: objectToEdit?.name?.de ?? '', name_de: objectToEdit?.name?.de ?? '',
description: objectToEdit?.description ?? '', description_ar: objectToEdit?.description?.ar ?? '',
price: objectToEdit?.price ?? "", description_en: objectToEdit?.description?.en ?? '',
images: objectToEdit?.images ?? "", description_de: objectToEdit?.description?.de ?? '',
attribute: objectToEdit?.attribute ?? "", // attribute: objectToEdit?.attribute ?? "",
category_id: objectToEdit?.category?.id ?? "", category_id: objectToEdit?.category?.id ?? "",
variable: [{}, product ?? {}], price: objectToEdit?.price ?? "",
variable: [{}, ...products],
info: [undefined, ...formattedData] ?? [], info: [undefined, ...formattedData] ?? [],
removedVariant:[],
} }
}; };
@ -55,14 +68,15 @@ export const getInitialValuesAdd = (objectToEdit: any | null = null) => {
name: "", name: "",
name_ar:'', name_ar:'',
name_en: '', name_en: '',
name_de: '', name_de: '',
description: '', description_ar:'',
price: "", description_en: '',
images: "", description_de: '',
attribute: "", price: "",
category_id: "", category_id: "",
variable: [], variable: [],
info: [], info: [],
} }
}; };
@ -73,6 +87,7 @@ export const getValidationSchema = (editMode: boolean = false) => {
name_en: Yup.string().required('Required'), name_en: Yup.string().required('Required'),
name_de: Yup.string().required('Required'), name_de: Yup.string().required('Required'),
category_id: Yup.string().required('Required'), category_id: Yup.string().required('Required'),
}); });

View File

@ -25,6 +25,7 @@ const useTableColumns :any = () => {
toggleMutation.mutate({id:row?.id,new_status:status}) toggleMutation.mutate({id:row?.id,new_status:status})
} }
const language = localStorage.getItem("language") ?? "en"
return useMemo( return useMemo(
() => [ () => [
@ -32,7 +33,7 @@ const useTableColumns :any = () => {
name: t("name"), name: t("name"),
sortable: false, sortable: false,
center: true, center: true,
selector:(row:any) => row?.name, selector:(row:any) => row?.name?.[language],
}, },
{ {
@ -48,7 +49,7 @@ const useTableColumns :any = () => {
sortable: false, sortable: false,
center: true, center: true,
cell: (row:any) => ( cell: (row:any) => (
row?.category?.name row?.category?.name?.[language]
), ),
}, },

View File

@ -15,7 +15,6 @@ function Page() {
const column =useTableColumns() const column =useTableColumns()
const {data ,status } = useGetSlider() const {data ,status } = useGetSlider()
console.log(data);
const [t] = useTranslation() const [t] = useTranslation()
const navigate = useNavigate() const navigate = useNavigate()
const totalRows = data?.meta?.total; const totalRows = data?.meta?.total;
@ -25,7 +24,7 @@ function Page() {
<DashBody status={status as QueryStatusEnum} > <DashBody status={status as QueryStatusEnum} >
<DashHeader showAddButton={false} title={'slider'}> <DashHeader showAddButton={false} title={'slider'}>
<div className='RightSide d-flex gap-2 align-center '> <div className='RightSide d-flex gap-2 align-center '>
<SearchField /> <SearchField searchBy={"title"} />
<AddButton onClick={()=>navigate('/slider/add')}></AddButton> <AddButton onClick={()=>navigate('/slider/add')}></AddButton>
</div> </div>

View File

@ -21,12 +21,14 @@ function Form() {
<Col> <Col>
<ValidationField name="state" type='Select' option={stateSelect} /> <ValidationField name="state" type='Select' option={stateSelect} />
<ValidationField name="delivery_link" />
</Col> </Col>
<Col> <Col>
<ValidationField name="admin_note" /> <ValidationField name="admin_note" />
<ValidationField name="deliviration_estimated_time" Format="YYYY-MM-DD HH:MM:SS" type='Date' />
</Col> </Col>

View File

@ -5,7 +5,7 @@ import 'react-tabs/style/react-tabs.css';
import { MdLanguage } from 'react-icons/md' import { MdLanguage } from 'react-icons/md'
import { FaSadCry } from 'react-icons/fa' import { FaSadCry } from 'react-icons/fa'
import ViewPage from '../../../Layout/Dashboard/ViewPage'; import ViewPage from '../../../Layout/Dashboard/ViewPage';
import { Rate } from 'antd'; import { Rate, Spin } from 'antd';
import { usePageState } from '../../../lib/state mangment/LayoutPagestate'; import { usePageState } from '../../../lib/state mangment/LayoutPagestate';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import LoadingPage from '../../../Layout/app/LoadingPage'; import LoadingPage from '../../../Layout/app/LoadingPage';
@ -14,37 +14,24 @@ import { BsInfoCircle } from 'react-icons/bs';
import { useGetOneSlider, useUpdateSlider } from '../../../api/Slider'; import { useGetOneSlider, useUpdateSlider } from '../../../api/Slider';
import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess'; import useNavigateOnSuccess from '../../../Hooks/useNavigateOnSuccess';
import Form from './EditForm'; import Form from './EditForm';
import { useGetOneOrder } from '../../../api/order'; import { useGetOneOrder, useUpdateOrder } from '../../../api/order';
const EditPage = () => { const EditPage = () => {
const { setObjectToEdit, objectToEdit } = usePageState() const { setObjectToEdit, objectToEdit } = usePageState()
const {t} = useTranslation(); const {t} = useTranslation();
const {mutate ,isSuccess} = useUpdateSlider() const {mutate ,isSuccess} = useUpdateOrder("put")
const { id } = useParams(); const { id } = useParams();
const { data, isLoading } = useGetOneOrder({id: id }) const { data, isLoading } = useGetOneOrder({id: id })
const FormatedData = data?.data ;
const handleSubmit = (values:any)=>{ const handleSubmit = (values:any)=>{
return mutate(values);
const newData = {} as any;
for (const key in FormatedData) {
if (values[key] !== FormatedData[key]) {
newData[key] = values[key];
}
}
return mutate(newData);
} }
useNavigateOnSuccess(isSuccess , '/order') useNavigateOnSuccess(isSuccess , '/order')
useEffect(() => { useEffect(() => {
console.log(data);
setObjectToEdit(data?.data); setObjectToEdit(data?.data);
@ -57,6 +44,9 @@ const EditPage = () => {
const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit }; const ViewProps = { getInitialValues, getValidationSchema, getDataToSend, handleSubmit };
if ( isLoading || !objectToEdit) {
return <Spin />
}
return ( return (

View File

@ -20,13 +20,15 @@ interface ValidateSchema extends formUtilCommon{
} }
export const getInitialValues = (objectToEdit: any | null = null): any => { export const getInitialValues = (objectToEdit: any | null = null): any => {
console.log(objectToEdit,"objectToEdit"); // console.log(objectToEdit,"objectToEdit");
return { return {
id: objectToEdit?.id ?? 0, id: objectToEdit?.id ?? 0,
state:objectToEdit?.state ?? "", state:objectToEdit?.state ?? "",
admin_note: objectToEdit?.admin_note ?? '', admin_note: objectToEdit?.admin_note ?? '',
deliviration_estimated_time:objectToEdit?.deliviration_estimated_time ??"",
delivery_link:objectToEdit?.delivery_link ??"",
}; };
}; };

View File

@ -30,7 +30,7 @@ const OrderPage = () => {
<DashBody status={status as QueryStatusEnum} > <DashBody status={status as QueryStatusEnum} >
<DashHeader title="orders" showAddButton={false}> <DashHeader title="orders" showAddButton={false}>
<div className='RightSide d-flex gap-2 align-center '> <div className='RightSide d-flex gap-2 align-center '>
<SearchField /> <SearchField searchBy="username" />
</div> </div>
</DashHeader> </DashHeader>
<LyTable <LyTable

View File

@ -15,6 +15,8 @@ const useTableColumns = () => {
const [t] = useTranslation(); const [t] = useTranslation();
const navigate = useNavigate() const navigate = useNavigate()
const deleteMutation = useDeleteOrder() const deleteMutation = useDeleteOrder()
const language = localStorage.getItem("language") ?? "en"
let column = [ let column = [
{ {
@ -39,7 +41,7 @@ const useTableColumns = () => {
name: t("name"), name: t("name"),
sortable: false, sortable: false,
center:true, center:true,
selector:(row:any) => row?.user?.name, selector:(row:any) => row?.user?.name[language],
}, },
{ {

View File

@ -4,6 +4,8 @@ import ColumnsImage from '../../../Components/Columns/ColumnsImage';
import { mapTranslatedProperties } from '../../../utils/language/mapTranslatedProperties'; import { mapTranslatedProperties } from '../../../utils/language/mapTranslatedProperties';
export default function useTableColumns() { export default function useTableColumns() {
const [t] = useTranslation(); const [t] = useTranslation();
const language = localStorage.getItem("language") ?? "en"
return [ return [
{ {
name: t("id"), name: t("id"),
@ -16,7 +18,7 @@ export default function useTableColumns() {
name: `${t('name')}`, name: `${t('name')}`,
sortable: true, sortable: true,
center: true, center: true,
cell:(row) => row.name cell:(row) => row.name[language]
}, },
{ {

View File

@ -505,4 +505,43 @@ padding: 10px 40px;
.SearchField{ .SearchField{
display: none; display: none;
} }
} }
.AddNewTabText{
text-wrap: nowrap !important;
margin-left: 60px;
transform: translateY(-30px);
}
/* Dynamic form complex */
#dynamic_form_complex{
margin-bottom:5px;
}
/* Ant space gap col small */
#dynamic_form_complex .ant-space-gap-col-small{
margin-bottom:-9px !important;
transform:translatex(0px) translatey(0px);
}
/* Ant space item */
#dynamic_form_complex .ant-space-gap-col-small .ant-space-item{
margin-bottom:6px;
}
/* Span Tag */
#dynamic_form_complex .ant-space-item span{
transform: translatex(-13px) translatey(-12px);
}
#dynamic_form_complex .ant-space-gap-col-small {
width: 100%;
}
.Information{
margin-block: 20px;
}
:where(.css-dev-only-do-not-override-6j9yrn).ant-form{
overflow-x: hidden;
}

View File

@ -90,4 +90,12 @@
.VarianInfo .ant-tabs-editable .ant-tabs-nav{ .VarianInfo .ant-tabs-editable .ant-tabs-nav{
margin-left:12px; margin-left:12px;
} }
}
.react-tabs .react-tabs__tab-panel--selected .mt-4 .d-flex .ant-tabs-left{
width:100% !important;
}
:where(.css-dev-only-do-not-override-6j9yrn).ant-tabs {
width:100% !important;
} }

View File

@ -21,6 +21,6 @@ export const useGetCategories = (params?:any) => useGetQueryPagination(KEY, API.
export const useGetOneCategories = () => useGetOneQuery(KEY, API.GET_ALL); export const useGetOneCategories = () => useGetOneQuery(KEY, API.GET_ALL);
export const useAddCategories = () => useAddMutation(KEY, API.ADD); export const useAddCategories = () => useAddMutation(KEY, API.ADD);
export const useUpdateCategories = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,method); export const useUpdateCategories = (method?:any) => useUpdateMutationPost(KEY, API.UPDATE,true,method);
export const useDeleteCategories = () =>useDeleteMutation(KEY, API.DELETE); export const useDeleteCategories = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -20,6 +20,6 @@ export const useGetCoupon = (params?:any) => useGetQueryPagination(KEY, API.GET_
export const useGetOneCoupon = () => useGetOneQuery(KEY, API.GET_ALL); export const useGetOneCoupon = () => useGetOneQuery(KEY, API.GET_ALL);
export const useAddCoupon = () => useAddMutation(KEY, API.ADD); export const useAddCoupon = () => useAddMutation(KEY, API.ADD);
export const useUpdateCoupon = (method?:any) => useUpdateMutation(KEY, API.UPDATE,method); export const useUpdateCoupon = (method:any) => useUpdateMutation(KEY, API.UPDATE,true,method);
export const useDeleteCoupon = () =>useDeleteMutation(KEY, API.DELETE); export const useDeleteCoupon = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -6,6 +6,7 @@ import useGetOneQuery from "./helper/useGetOneQuery";
import useGetQuery from "./helper/useGetQuery" 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";
const API = { const API = {
ADD: `attribute`, ADD: `attribute`,
@ -16,6 +17,7 @@ const API = {
}; };
const KEY = "ATTRIBUTE" const KEY = "ATTRIBUTE"
const KEY2 = "ATTRIBUTEValue"
export const useGetAttribute = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params); export const useGetAttribute = (params?:any) => useGetQueryPagination(KEY, API.GET_ALL,params);
@ -24,7 +26,7 @@ export const useGetSingleAttribute = (params?:any,options?:any) => useGetSingleQ
export const useAddAttribute = () => useAddMutation(KEY, API.ADD); export const useAddAttribute = () => useAddMutation(KEY, API.ADD);
export const useUpdateAttribute = () => useUpdateMutation(KEY, API.UPDATE); export const useUpdateAttribute = (method:any) => useUpdateMutationById(KEY, API.UPDATE,false,method);
export const useUpdateAttributeStatus = () => useUpdateMutation(KEY, API.UPDATE); export const useUpdateAttributeStatus = () => useUpdateMutation(KEY, API.UPDATE,false);
export const useDeleteAttribute = () =>useDeleteMutation(KEY, API.DELETE); export const useDeleteAttribute = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -6,6 +6,7 @@ import useGetOneQuery from "./helper/useGetOneQuery";
import useGetQuery from "./helper/useGetQuery" 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";
const API = { const API = {
ADD: `attributeValue`, ADD: `attributeValue`,
@ -24,7 +25,7 @@ export const useGetSingleAttributeValue = (params?:any) => useGetSingleQuery(KEY
export const useAddAttributeValue = () => useAddMutation(KEY, API.ADD); export const useAddAttributeValue = () => useAddMutation(KEY, API.ADD);
export const useUpdateAttributeValue = () => useUpdateMutation(KEY, API.UPDATE); export const useUpdateAttributeValue = () => useUpdateMutationById(KEY, API.UPDATE);
export const useUpdateAttributeValueStatus = () => useUpdateMutation(KEY, API.UPDATE); export const useUpdateAttributeValueStatus = () => useUpdateMutation(KEY, API.UPDATE);
export const useDeleteAttributeValue = () =>useDeleteMutation(KEY, API.DELETE); export const useDeleteAttributeValue = () =>useDeleteMutation(KEY, API.DELETE);

View File

@ -1,55 +0,0 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
exports.__esModule = true;
exports.useUpdateMyAccount = exports.getDataToSend = exports.useDeleteAccount = exports.useChangePassword = exports.useUpdateAccount = exports.useAddAccount = exports.useUpdateWallet = exports.useGetWallet = exports.useGetAccounts = void 0;
var RoleConfige_1 = require("../config/RoleConfige");
var buildFormData_1 = require("./helper/buildFormData");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetQuery_1 = require("./helper/useGetQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
GET: "/api/admin/account/all",
GET_ALL_PER: "/api/admin/role/all-permissions",
GET_ALL_ROLE: "/api/admin/role/all",
ADD: "/api/admin/account/create",
GETWALLET: "/api/admin/account/get-wallet",
UPDATEWALLET: "/api/admin/account/add-to-wallet",
UPDATE: "/api/admin/account/update",
DELETE: "/api/admin/account/delete",
UPDATE_MY_ACCOUNT: "/api/admin/account/update-my-account",
UPDATE_PASSWORD: "/api/admin/account/change-password"
};
var KEY = "ADMINS";
var MY_ACCOUNT = "MY_ACCOUNT";
exports.useGetAccounts = function () { return useGetQuery_1["default"](MY_ACCOUNT, API.GET); };
exports.useGetWallet = function () { return useGetQuery_1["default"]("WALLET", API.GETWALLET); };
exports.useUpdateWallet = function () { return useAddMutation_1["default"]("WALLET", API.UPDATEWALLET); };
exports.useAddAccount = function () { return useAddMutation_1["default"](MY_ACCOUNT, API.ADD); };
exports.useUpdateAccount = function () { return useUpdateMutation_1["default"](MY_ACCOUNT, API.UPDATE); };
exports.useChangePassword = function () { return useUpdateMutation_1["default"](MY_ACCOUNT, API.UPDATE_PASSWORD); };
exports.useDeleteAccount = function () { return useDeleteMutation_1["default"](MY_ACCOUNT, API.DELETE); };
exports.getDataToSend = function (values, editMode, objectToEdit) {
var formData = new FormData();
var objectToSend = __assign(__assign({}, values), (editMode && { account_id: objectToEdit.id }));
if (editMode) {
delete objectToSend["password"];
delete objectToSend["password_confirmation"];
}
if (values.role !== RoleConfige_1.VENDOR) {
delete objectToSend["shop_id"];
}
buildFormData_1.buildFormData(formData, objectToSend);
return formData;
};
exports.useUpdateMyAccount = function () { return useUpdateMutation_1["default"](MY_ACCOUNT, API.UPDATE_MY_ACCOUNT); };

View File

@ -1,20 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteCategories = exports.useUpdateCategories = exports.useAddCategories = exports.useGetOneCategories = exports.useGetCategories = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useUpdateMutationPut_1 = require("./helper/useUpdateMutationPut");
var API = {
ADD: "category",
GET_ALL: "category",
DELETE: "category",
UPDATE: "category"
};
var KEY = "CATEGORIES";
exports.useGetCategories = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneCategories = function () { return useGetOneQuery_1["default"](KEY, API.GET_ALL); };
exports.useAddCategories = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateCategories = function (method) { return useUpdateMutationPut_1["default"](KEY, API.UPDATE, method); };
exports.useDeleteCategories = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

View File

@ -1,20 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteCoupon = exports.useUpdateCoupon = exports.useAddCoupon = exports.useGetOneCoupon = exports.useGetCoupon = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "coupon",
GET_ALL: "coupon",
DELETE: "coupon",
UPDATE: "coupon"
};
var KEY = "COUPON";
exports.useGetCoupon = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneCoupon = function () { return useGetOneQuery_1["default"](KEY, API.GET_ALL); };
exports.useAddCoupon = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateCoupon = function (method) { return useUpdateMutation_1["default"](KEY, API.UPDATE, method); };
exports.useDeleteCoupon = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

View File

@ -1,20 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteSlider = exports.useUpdateSlider = exports.useAddSlider = exports.useGetOneSlider = exports.useGetSlider = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "slider",
GET_ALL: "slider",
DELETE: "slider",
UPDATE: "slider"
};
var KEY = "SLIDER";
exports.useGetSlider = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneSlider = function () { return useGetOneQuery_1["default"](KEY, API.GET_ALL); };
exports.useAddSlider = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateSlider = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useDeleteSlider = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

View File

@ -1,18 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteAppSetting = exports.useUpdateAppSetting = exports.useAddAppSetting = exports.useGetAppSetting = void 0;
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetQuery_1 = require("./helper/useGetQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "/api/admin/app-setting/create",
GET: "/api/admin/app-setting/all",
UPDATE: "api/admin/app-setting/update",
DELETE: "/api/admin/app-setting/delete"
};
var KEY = "APPSETTING";
exports.useGetAppSetting = function (params) { return useGetQuery_1["default"](KEY, API.GET, params); };
exports.useAddAppSetting = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateAppSetting = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useDeleteAppSetting = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

View File

@ -1,23 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteAttribute = exports.useUpdateAttributeStatus = exports.useUpdateAttribute = exports.useAddAttribute = exports.useGetSingleAttribute = exports.useGetOneAttribute = exports.useGetAttribute = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useGetSingleQuery_1 = require("./helper/useGetSingleQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "attribute",
GET_ALL: "attribute",
DELETE: "attribute",
UPDATE: "attribute"
};
var KEY = "ATTRIBUTE";
exports.useGetAttribute = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneAttribute = function (params) { return useGetOneQuery_1["default"](KEY, API.GET_ALL, params); };
exports.useGetSingleAttribute = function (params) { return useGetSingleQuery_1["default"](KEY, API.GET_ALL, params); };
exports.useAddAttribute = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateAttribute = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useUpdateAttributeStatus = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useDeleteAttribute = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

10
src/api/dist/auth.js vendored
View File

@ -1,10 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useLoginAdmin = void 0;
var useAddMutation_1 = require("./helper/useAddMutation");
var KEY = "AUTH";
var API = {
LOGIN: "admin/login",
LOGOUT: "/api/admin/logout"
};
exports.useLoginAdmin = function () { return useAddMutation_1["default"](KEY, API.LOGIN); };

View File

@ -1,12 +0,0 @@
"use strict";
exports.__esModule = true;
exports.USER_KEY = exports.TOKEN_KEY = exports.BaseURL_IMAGE = exports.ImageBaseURL = exports.BaseURL = void 0;
// export const BaseURL = `https://etaxiapi.rayantaxi.com/`;
// export const BaseURL = `https://etaxi.Point.net/`;
exports.BaseURL = "https://hijabi-back-dev.point-dev.net/api/";
exports.ImageBaseURL = "https://hijabi-back-dev.point-dev.net";
// export const BaseURL = `http://192.168.1.14:8000/`;
exports.BaseURL_IMAGE = exports.BaseURL.slice(0, -1);
var PROJECT_NAME = "Hijab";
exports.TOKEN_KEY = PROJECT_NAME + "_TOKEN";
exports.USER_KEY = PROJECT_NAME + "_USER";

24
src/api/dist/order.js vendored
View File

@ -1,24 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeliveredOrder = exports.useDeliverOrder = exports.useCancelOrder = exports.useAcceptOrder = exports.useDeleteOrder = exports.useUpdateOrder = exports.useAddOrder = exports.useGetOneOrder = exports.useGetOrder = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "order",
GET_ALL: "order",
DELETE: "order",
UPDATE: "order"
};
var KEY = "Order";
exports.useGetOrder = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneOrder = function (params) { return useGetOneQuery_1["default"](KEY, API.GET_ALL, params); };
exports.useAddOrder = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateOrder = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useDeleteOrder = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };
exports.useAcceptOrder = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useCancelOrder = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useDeliverOrder = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useDeliveredOrder = function () { return useAddMutation_1["default"](KEY, API.ADD); };

View File

@ -1,26 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteProduct = exports.useUpdateProductStatus = exports.useUpdateProductVariation = exports.useUpdateProduct = exports.useAddProductVariation = exports.useAddProduct = exports.useGetOneProduct = exports.useGetProduct = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "baseProduct",
GET_ALL: "baseProduct",
DELETE: "baseProduct",
UPDATE: "baseProduct",
ADD_VAR: "product",
UPDATE_VAR: "product"
};
var KEY = "Product";
var ONEKEY = "OneProduct";
exports.useGetProduct = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneProduct = function (params) { return useGetOneQuery_1["default"](ONEKEY, API.GET_ALL, params); };
exports.useAddProduct = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useAddProductVariation = function () { return useAddMutation_1["default"](KEY, API.ADD_VAR); };
exports.useUpdateProduct = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useUpdateProductVariation = function () { return useUpdateMutation_1["default"](KEY, API.ADD_VAR); };
exports.useUpdateProductStatus = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useDeleteProduct = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

20
src/api/dist/users.js vendored
View File

@ -1,20 +0,0 @@
"use strict";
exports.__esModule = true;
exports.useDeleteUsers = exports.useUpdateUsers = exports.useAddUsers = exports.useGetOneUser = exports.useGetUsers = void 0;
var ueGetPagination_1 = require("./helper/ueGetPagination");
var useAddMutation_1 = require("./helper/useAddMutation");
var useDeleteMutation_1 = require("./helper/useDeleteMutation");
var useGetOneQuery_1 = require("./helper/useGetOneQuery");
var useUpdateMutation_1 = require("./helper/useUpdateMutation");
var API = {
ADD: "user",
GET_ALL: "user",
DELETE: "user",
UPDATE: "user"
};
var KEY = "User";
exports.useGetUsers = function (params) { return ueGetPagination_1["default"](KEY, API.GET_ALL, params); };
exports.useGetOneUser = function (params) { return useGetOneQuery_1["default"](KEY, API.GET_ALL, params); };
exports.useAddUsers = function () { return useAddMutation_1["default"](KEY, API.ADD); };
exports.useUpdateUsers = function () { return useUpdateMutation_1["default"](KEY, API.UPDATE); };
exports.useDeleteUsers = function () { return useDeleteMutation_1["default"](KEY, API.DELETE); };

View File

@ -1,40 +0,0 @@
"use strict";
exports.__esModule = true;
var axios_1 = require("axios");
var AxiosBuilder = /** @class */ (function () {
function AxiosBuilder() {
this.baseURL = '';
this.headers = {};
this.timeout = 60000; // Request failed with 60 second
this.withCreds = false;
this.responseType = 'json';
}
// Custom Another Props with Your Position
AxiosBuilder.prototype.withBaseURL = function (baseURL) {
this.baseURL = baseURL;
return this;
};
AxiosBuilder.prototype.withHeaders = function (headers) {
this.headers = headers;
return this;
};
AxiosBuilder.prototype.withTimeout = function (timeout) {
this.timeout = timeout;
return this;
};
AxiosBuilder.prototype.withResponseType = function (responseType) {
this.responseType = responseType;
return this;
};
AxiosBuilder.prototype.build = function () {
var config = {
baseURL: this.baseURL,
headers: this.headers,
timeout: this.timeout,
responseType: this.responseType
};
return axios_1["default"].create(config);
};
return AxiosBuilder;
}());
exports["default"] = AxiosBuilder;

View File

@ -1,61 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var react_query_1 = require("react-query");
var useAxios_1 = require("./useAxios");
function useGetQuery(key, url, params) {
var _this = this;
var axios = useAxios_1["default"]();
return react_query_1.useQuery(key, function () { return __awaiter(_this, void 0, void 0, function () {
var response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, axios.get(params ? url + params : url, params)];
case 1:
response = _a.sent();
return [2 /*return*/, response.data.data];
}
});
}); }, {
onError: function (error) {
console.error('An error occurred:', error);
},
refetchOnWindowFocus: false
});
}
exports["default"] = useGetQuery;

View File

@ -1,17 +0,0 @@
"use strict";
exports.__esModule = true;
exports.buildFormData = void 0;
exports.buildFormData = function (formData, data, parentKey) {
if (data &&
typeof data === "object" &&
!(data instanceof Date) &&
!(data instanceof File)) {
Object.keys(data).forEach(function (key) {
exports.buildFormData(formData, data[key], parentKey ? parentKey + "[" + key + "]" : key);
});
}
else {
var value = data == null ? "" : data;
formData.append(parentKey, value);
}
};

View File

@ -1,84 +0,0 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var react_query_1 = require("react-query");
var useAxios_1 = require("./useAxios");
var react_router_dom_1 = require("react-router-dom");
var AuthState_1 = require("../../lib/state mangment/AuthState");
function useGetQueryPagination(KEY, Api, params, options) {
var _this = this;
var _a;
if (params === void 0) { params = {}; }
if (options === void 0) { options = {}; }
var axios = useAxios_1["default"]();
var location = react_router_dom_1.useLocation();
var pagination = (location === null || location === void 0 ? void 0 : location.search) || '';
// console.log(params);
var logout = AuthState_1["default"]().logout;
var language = (_a = localStorage.getItem("language")) !== null && _a !== void 0 ? _a : "en";
var navigate = react_router_dom_1.useNavigate();
return react_query_1.useQuery([KEY, pagination], function () { return __awaiter(_this, void 0, void 0, function () {
var response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, axios.get(Api + pagination, { params: params })];
case 1:
response = _a.sent();
return [2 /*return*/, response.data];
}
});
}); }, __assign({ onError: function (error) {
if (error.response.status == 401 || error.response.status == 403) {
logout();
navigate("/auth");
}
}, refetchOnWindowFocus: false }, options));
}
exports["default"] = useGetQueryPagination;
// export const useGetDynamic = (Api: string) => useGetQueryPagination(Api);

View File

@ -1,74 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var react_query_1 = require("react-query");
var react_toastify_1 = require("react-toastify");
var useAxios_1 = require("./useAxios");
var react_i18next_1 = require("react-i18next");
function useAddMutation(key, url) {
var _this = this;
var axios = useAxios_1["default"]();
var t = react_i18next_1.useTranslation()[0];
var queryClient = react_query_1.useQueryClient();
return react_query_1.useMutation(function (dataToSend) { return __awaiter(_this, void 0, void 0, function () {
var data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, axios.post(url, dataToSend, {
headers: {
'Content-Type': 'multipart/form-data'
}
})];
case 1:
data = (_a.sent()).data;
return [2 /*return*/, data];
}
});
}); }, {
onSuccess: function (data) {
queryClient.invalidateQueries([key]);
react_toastify_1.toast.success(data.message || t("Add Successful"));
},
onError: function (error) {
var _a, _b;
var message = ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || t("failed_to_add_data");
react_toastify_1.toast.error(message);
}
});
}
exports["default"] = useAddMutation;

View File

@ -1,18 +0,0 @@
"use strict";
exports.__esModule = true;
var config_1 = require("../config");
var AuthState_1 = require("../../lib/state mangment/AuthState");
var AxiosBuilder_1 = require("./AxiosBuilder");
function useAxios() {
var _a = AuthState_1["default"](), isAuthenticated = _a.isAuthenticated, token = _a.token;
var buildAxios = new AxiosBuilder_1["default"]().
withBaseURL(config_1.BaseURL)
.withResponseType('json')
.withTimeout(120000)
.withHeaders({ "Content-Type": "application/json" });
if (isAuthenticated) {
buildAxios.withHeaders({ Authorization: 'Bearer ' + token });
}
return (buildAxios.build());
}
exports["default"] = useAxios;

View File

@ -1,79 +0,0 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var react_query_1 = require("react-query");
var react_toastify_1 = require("react-toastify");
var useAxios_1 = require("./useAxios");
var react_i18next_1 = require("react-i18next");
function useDeleteMutation(key, url) {
var _this = this;
var axios = useAxios_1["default"]();
var queryClient = react_query_1.useQueryClient();
var t = react_i18next_1.useTranslation().t;
return react_query_1.useMutation(function (_a) {
var dataToSend = _a.dataToSend, id = _a.id;
return __awaiter(_this, void 0, void 0, function () {
var data;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, axios["delete"](url + "/" + id)];
case 1:
data = (_b.sent()).data;
return [2 /*return*/, __assign(__assign({}, data), { id: id, dataToSend: dataToSend })];
}
});
});
}, {
onSuccess: function (data) {
queryClient.invalidateQueries(key);
react_toastify_1.toast.success(t('deleted_successfully'));
}
});
}
exports["default"] = useDeleteMutation;

View File

@ -1,81 +0,0 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var react_query_1 = require("react-query");
var useAxios_1 = require("./useAxios");
var AuthState_1 = require("../../lib/state mangment/AuthState");
var react_router_dom_1 = require("react-router-dom");
function useGetOneQuery(key, url, params, options) {
var _this = this;
var _a;
if (params === void 0) { params = {}; }
if (options === void 0) { options = {}; }
var axios = useAxios_1["default"]();
var logout = AuthState_1["default"]().logout;
var language = (_a = localStorage.getItem("language")) !== null && _a !== void 0 ? _a : "en";
var navigate = react_router_dom_1.useNavigate();
var id = react_router_dom_1.useParams().id;
return react_query_1.useQuery([id, key], function () { return __awaiter(_this, void 0, void 0, function () {
var response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, axios.get(url + "/" + id + ("?lang=" + language))];
case 1:
response = _a.sent();
return [2 /*return*/, response.data];
}
});
}); }, __assign({ onError: function (error) {
if (error.response.status == 401 || error.response.status == 403) {
logout();
navigate("/auth");
}
}, refetchOnWindowFocus: false }, options));
}
exports["default"] = useGetOneQuery;

View File

@ -1,81 +0,0 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
var react_query_1 = require("react-query");
var useAxios_1 = require("./useAxios");
var AuthState_1 = require("../../lib/state mangment/AuthState");
var react_router_dom_1 = require("react-router-dom");
function useGetQuery(key, url, params, options) {
var _this = this;
if (params === void 0) { params = {}; }
if (options === void 0) { options = {}; }
var axios = useAxios_1["default"]();
var logout = AuthState_1["default"]().logout;
var navigate = react_router_dom_1.useNavigate();
return react_query_1.useQuery(params ? [key, params] : key, function () { return __awaiter(_this, void 0, void 0, function () {
var response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, axios.get(url, { params: params })];
case 1:
response = _a.sent();
return [2 /*return*/, response.data.data];
}
});
}); }, __assign({ onError: function (error) {
console.log('====================================');
console.log(error.response.status);
console.log('====================================');
if (error.response.status == 401 || error.response.status == 403) {
logout();
navigate("/auth");
}
}, refetchOnWindowFocus: false }, options));
}
exports["default"] = useGetQuery;

Some files were not shown because too many files have changed in this diff Show More