fix add product modal

This commit is contained in:
Moaz Dawalibi 2024-08-03 15:17:06 +03:00
parent ed0d7d3a5d
commit a7d4b29eef
13 changed files with 210 additions and 147 deletions

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"cSpell.words": [
"formik"
]
}

View File

@ -1,10 +1,11 @@
import React from "react"; import React from "react";
import "./ValidationField.scss"; import "./ValidationField.scss";
import { Date, Time, File, DataRange, SelectField, Default, CheckboxField } from './View'; import { Date, Time, File, DataRange, SelectField, Default, CheckboxField } from './View';
import MaltyFile from "./View/MaltyFile";
export interface ValidationFieldProps { export interface ValidationFieldProps {
name: string; name: string;
type?: "text" | "Select" | "DataRange" | "Date" | "Time" | "File" | "number" | "Checkbox" | "password"; type?: "text" | "Select" | "DataRange" | "Date" | "Time" | "File" | "number" | "Checkbox" | "password" |"MaltyFile";
placeholder?: string; placeholder?: string;
label?: string; label?: string;
className?: string; className?: string;
@ -31,6 +32,8 @@ const ValidationField = (props: ValidationFieldProps) => {
return <Time {...props} />; return <Time {...props} />;
case "File": case "File":
return <File {...props} />; return <File {...props} />;
case "MaltyFile":
return <MaltyFile {...props} />;
case "Checkbox": case "Checkbox":
return <CheckboxField {...props} />; return <CheckboxField {...props} />;
default: default:

View File

@ -22,6 +22,7 @@ const Default = ({ name, label, placeholder, isDisabled, onChange, props }: any)
placeholder={t(`${placeholder ? placeholder : name}`)} placeholder={t(`${placeholder ? placeholder : name}`)}
name={name} name={name}
disabled={isDisabled} disabled={isDisabled}
// onChange={onChange ? onChange : handleChange} // onChange={onChange ? onChange : handleChange}
/> />
</Form.Item> </Form.Item>

View File

@ -19,6 +19,7 @@ const MaltyFile = ({
const fileList = useMemo(() => { const fileList = useMemo(() => {
return imageUrl return imageUrl
? imageUrl.map((file: any, index: number) => { ? imageUrl.map((file: any, index: number) => {
return file instanceof File return file instanceof File
? { ? {
uid: index, uid: index,
@ -34,7 +35,7 @@ const MaltyFile = ({
url: file?.url || "", url: file?.url || "",
thumbUrl: file?.url || "", thumbUrl: file?.url || "",
}; };
}) })
: []; : [];
}, [imageUrl]); // Dependency array ensures it recalculates only when imageUrl changes }, [imageUrl]); // Dependency array ensures it recalculates only when imageUrl changes
@ -58,7 +59,7 @@ const MaltyFile = ({
return ( return (
<div className="ValidationField upload_image_button"> <div className="ValidationField upload_image_button">
<label htmlFor={name} className="text"> <label htmlFor={name} className="text">
{t(`input.${label || name}`)} {t(`${label || name}`)}
</label> </label>
<Upload <Upload
@ -75,7 +76,7 @@ const MaltyFile = ({
className={isError ? "isError w-100" : "w-100"} className={isError ? "isError w-100" : "w-100"}
icon={<FaUpload />} icon={<FaUpload />}
> >
{t(`input.` + placeholder) ?? t("input.upload_image")} {t(placeholder) ?? t("upload_image")}
</Button> </Button>
<div className="Error_color">{isError ? "required" : ""}</div> <div className="Error_color">{isError ? "required" : ""}</div>
</Upload> </Upload>

View File

@ -17,7 +17,6 @@
console.log(values); console.log(values);
const dataToSend = getDataToSend(values) const dataToSend = getDataToSend(values)
mutate(dataToSend) mutate(dataToSend)
// Submit Value // Submit Value
} }

View File

@ -12,8 +12,8 @@ function EditProductModal() {
const {status, mutate} = useUpdateProduct(); const {status, mutate} = useUpdateProduct();
const handleSubmit = (value:InitialValues)=>{ const handleSubmit = (value:InitialValues)=>{
const dataToSend = getDataToSend({...value})
console.log(value); console.log(value);
const dataToSend = getDataToSend({...value})
mutate(dataToSend) mutate(dataToSend)
} }

View File

@ -5,11 +5,8 @@ import ValidationField from '../../Components/ValidationField/ValidationField';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useGetCategory } from '../../api/category'; import { useGetCategory } from '../../api/category';
import { objectToKeyValueArray } from '../../utils/ConvertObjToArr'; import { objectToKeyValueArray } from '../../utils/ConvertObjToArr';
import { Collection, Param } from './formUtil';
interface Param {
key: string;
value: string;
}
interface FormValues { interface FormValues {
attachments: any; attachments: any;
@ -18,6 +15,7 @@ interface FormValues {
model: string; model: string;
image: string; image: string;
params: Param[]; params: Param[];
collections: Collection[]
} }
function FormProduct() { function FormProduct() {
@ -29,112 +27,127 @@ function FormProduct() {
value: e.id, value: e.id,
label: e?.name, label: e?.name,
})); }));
// console.log(formik.values.params);
const paramsArray = objectToKeyValueArray(formik.values.params)
// console.log(formik.values.params);
return ( return (
<> <>
<Row xs={1} sm={1} md={1} lg={2} xl={2}> <Row xs={1} sm={1} md={1} lg={3} xl={3}>
<Col> <Col>
<ValidationField name="name" type="text" label="Name" placeholder="placeholder" /> <ValidationField name="name" type="text" label="Name" placeholder="placeholder" />
<ValidationField name="description" type="text" label="description" placeholder="placeholder" /> <ValidationField name="description" type="text" label="description" placeholder="placeholder" />
<ValidationField name="model" type="text" label="Model" placeholder="placeholder" /> <ValidationField name="model" type="text" label="Model" placeholder="placeholder" />
<ValidationField name="file" type="File" label="Image" placeholder="placeholder" /> <ValidationField name="file" type="File" label="Image" placeholder="placeholder" />
<ValidationField name="category_id" type="Select" label="Category" option={CategoryOption} placeholder="placeholder" /> <ValidationField name="category_id" type="Select" label="Category" option={CategoryOption} placeholder="placeholder" />
</Col> <ValidationField name="attachments" type="MaltyFile" label="Attachments inputs" placeholder="Attachments" />
<Col> </Col>
<FieldArray name="params">
{({ push, remove }) => ( <Col>
<div> <FieldArray name="params">
{Array.isArray(formik.values.params) && formik.values.params.map((param, index) => ( {({ push, remove }) => (
<div key={index}> <div>
<ValidationField {Array.isArray(formik.values.params) && formik.values.params.map((param, index) => (
name={`params.${index}.key`} <div key={index}>
type="text" <ValidationField
label={`Param Key ${index + 1}`} name={`params.${index}.key`}
placeholder="Key" type="text"
/> label={`Param Key ${index + 1}`}
<ValidationField placeholder="Key"
name={`params.${index}.value`} />
type="text" <ValidationField
label={`Param Value ${index + 1}`} name={`params.${index}.value`}
placeholder="Value" type="text"
/> label={`Param Value ${index + 1}`}
<Button type="button" className='remove_button' color='danger' onClick={() => remove(index)}>{t("Remove")}</Button> placeholder="Value"
</div> />
))} <div className='flex_between'>
<Button <Button type="button" className='remove_button' color='danger' onClick={() => remove(index)}>{t("Remove")}</Button>
type="button" <Button
className="add_button" type="button"
color='primary' className="add_button"
onClick={() => push({ key: '', value: '' })} color='primary'
> onClick={() => push({ key: '', value: '' })}
{t("Add Param")} >
</Button> {t("Add Param")}
</div> </Button>
)} </div>
</FieldArray> </div>
</Col> ))}
</Row>
<Row>
{/* collection */}
<Col className='border'>
{/* <FieldArray name="">
{({ push, remove }) => (
<div>
{formik.values.params.map((param, index) => (
<div key={index}>
<ValidationField
name={`params.${index}.key`}
type="text"
label={`Param Key ${index + 1}`}
placeholder="Key"
/>
<ValidationField
name={`params.${index}.value`}
type="text"
label={`Param Value ${index + 1}`}
placeholder="Value"
/>
<Button type="button" className='remove_button' color='danger' onClick={() => remove(index)}>{t("Remove")}</Button>
</div> </div>
))} )}
<Button type="button" className="add_button" color='primary' onClick={() => push({ key: '', value: '' })}>{t("Add Param")}</Button> </FieldArray>
</div> </Col>
)}
</FieldArray> */}
{/* collection */}
{/* attachements array */} <Col>
<FieldArray name="attachments"> <FieldArray name="collections">
{({ push, remove }) => ( {({ push, remove }) => (
<div> <div>
{formik.values.attachments.map((attachment: any, index: number) => ( {Array.isArray(formik.values.collections) && formik.values.collections?.map((collection, index) => (
<div key={index}> <div key={index}>
{/* <ValidationField <ValidationField
name={`attachments[${index}].id`} name={`collections.${index}.name`}
type="text" type="text"
label={`Attachment ID ${index + 1}`} label={`Collection Name ${index + 1}`}
placeholder="Attachment ID" placeholder="Collection Name"
/> */} />
<ValidationField <FieldArray name={`collections.${index}.collectionParams`}>
name={`attachments[${index}].attachment`} {({ push: pushParam, remove: removeParam }) => (
type="File" <div>
label={`Attachment URL ${index + 1}`} {Array.isArray(collection?.collectionParams) && collection?.collectionParams?.map((param, paramIndex) => (
placeholder="Attachment URL" <div key={paramIndex}>
/> <ValidationField
<Button type="button" className='remove_button' color='danger' onClick={() => remove(index)}>{t("Remove")}</Button> name={`collections.${index}.collectionParams.${paramIndex}.key`}
</div> type="text"
))} label={`Param Key ${paramIndex + 1}`}
<Button type="button" className="add_button" color='primary' onClick={() => push({ id: null, attachment: '' })}>{t("Add Attachment")}</Button> placeholder="Key"
</div> />
)} <ValidationField
</FieldArray> name={`collections.${index}.collectionParams.${paramIndex}.value`}
type="text"
label={`Param Value ${paramIndex + 1}`}
placeholder="Value"
/>
<div className='flex_evenly'>
<Button type="button" className='remove_button remove_sub_color' color='danger' onClick={() => removeParam(paramIndex)}>
{t("Remove Param")}
</Button>
<Button
type="button"
className="add_button add_sub_color"
color='primary'
onClick={() => pushParam({ key: '', value: '' })}
>
{t("Add Param")}
</Button>
</div>
</div>
))}
</div>
)}
</FieldArray>
<div className='flex_between'>
<Button type="button" className='remove_button' color='danger' onClick={() => remove(index)}>
{t("Remove Collection")}
</Button>
<Button
type="button"
className="add_button"
color='primary'
onClick={() => push({ name: '', collectionParams: [{ key: '', value: '' }] })}
>
{t("Add Collection")}
</Button>
</div>
</div>
))}
</div>
)}
</FieldArray>
</Col> </Col>
</Row> </Row>
</> </>
); )
} }
export default FormProduct;
export default FormProduct

View File

@ -1,5 +1,4 @@
import React from 'react'
import DashBody from '../../Layout/Dashboard/DashBody' import DashBody from '../../Layout/Dashboard/DashBody'
import DashHeader from '../../Layout/Dashboard/DashHeader' import DashHeader from '../../Layout/Dashboard/DashHeader'
import LyTable from '../../Layout/Dashboard/LyTable' import LyTable from '../../Layout/Dashboard/LyTable'

View File

@ -1,8 +1,8 @@
import * as Yup from 'yup'; import * as Yup from 'yup';
import { buildFormData } from '../../api/helper/buildFormData'; import { buildFormData } from '../../api/helper/buildFormData';
import { objectToKeyValueArray } from '../../utils/ConvertObjToArr'; import { collectionObjectToArray, objectToKeyValueArray } from '../../utils/ConvertObjToArr';
interface Param { export interface Param {
key: string; key: string;
value: string; value: string;
} }
@ -11,16 +11,16 @@ interface Category {
name: string | null; name: string | null;
} }
interface Collection { export interface Collection {
name: string; name: string;
collectionParam: { collectionParams: {
key: string; key: string;
value: string;
}; };
} }
interface Attachment { interface Attachment {
id: number | null; id: number | null;
// type: string;
attachment: string; attachment: string;
} }
@ -33,23 +33,30 @@ interface FormUtilCommon {
category?: Category; category?: Category;
params?: Param[]; params?: Param[];
collections?: Collection[]; collections?: Collection[];
attachments?: Attachment[]; // Add attachments here attachment?: Attachment[]; // Add attachments here
} }
interface ObjectToEdit extends FormUtilCommon { interface ObjectToEdit extends FormUtilCommon {
id?: number | null; id?: number | null;
} }
export interface InitialValues extends ObjectToEdit { export interface InitialValues extends ObjectToEdit {
} }
interface ValidateSchema extends FormUtilCommon {} interface ValidateSchema extends FormUtilCommon { }
export const getInitialValues = (objectToEdit: ObjectToEdit | null = null): any => { export const getInitialValues = (objectToEdit: ObjectToEdit | null = null): any => {
const params = objectToEdit?.params ? objectToKeyValueArray(objectToEdit.params) : [{ key: '', value: '' }]; const params = objectToEdit?.params ? objectToKeyValueArray(objectToEdit.params) : [{ key: '', value: '' }];
const collections = objectToEdit?.collections || []; const collection = objectToEdit?.collections ? objectToKeyValueArray(objectToEdit.collections) : [{ name: '', collectionParams: [{ key: '', value: '' }]} ];
const attachments = objectToEdit?.attachments ? objectToEdit.attachments.map(attachment => attachment.attachment ?? []):[] // { name: '', collectionParams: [{ key: '', value: '' }] };
const attachments = objectToEdit?.attachment ? objectToEdit.attachment.map(attachment => {
return {
url: attachment.attachment ?? ""
}
}) : []
return { return {
id: objectToEdit?.id ?? null, id: objectToEdit?.id ?? null,
@ -59,12 +66,12 @@ export const getInitialValues = (objectToEdit: ObjectToEdit | null = null): any
model: objectToEdit?.model ?? '', model: objectToEdit?.model ?? '',
file: objectToEdit?.file ?? '', file: objectToEdit?.file ?? '',
params: params, params: params,
collections: collections, collections: collection,
attachments: attachments, // Set the attachments here attachments: attachments, // Set the attachments here
}; };
} }
export const getValidationSchema = (editMode: boolean = false): Yup.Schema<ValidateSchema> => { export const getValidationSchema = (editMode: boolean = false): any => {
return Yup.object().shape({ return Yup.object().shape({
name: Yup.string().required('required'), name: Yup.string().required('required'),
category_id: Yup.number().nullable().required('required'), category_id: Yup.number().nullable().required('required'),
@ -77,12 +84,25 @@ export const getValidationSchema = (editMode: boolean = false): Yup.Schema<Valid
value: Yup.string().required('Value is required'), value: Yup.string().required('Value is required'),
}) })
).default([]), ).default([]),
collections: Yup.array().of(
Yup.object().shape({
name: Yup.string().required('Collection Name is required'),
collectionParams: Yup.array().of(
Yup.object().shape({
key: Yup.string().required('Key is required'),
value: Yup.string().required('Value is required'),
})
).required('At least one parameter is required').min(1, 'At least one parameter is required'), // Ensure at least one parameter
})
).optional(), // Allow collections to be optional
}); });
}; };
export const getDataToSend = (values: any): any => { export const getDataToSend = (values: any): any => {
const data = { ...values }; const data = { ...values };
if(data?.id){ console.log(values);
if (data?.id) {
data["_method"] = "PUT" data["_method"] = "PUT"
} }
@ -91,14 +111,12 @@ export const getDataToSend = (values: any): any => {
data.params = []; data.params = [];
} }
// if (data.attachments && Array.isArray(data.attachments)) { if (typeof data['file'] == 'string') delete data['file']
// data.attachments = data.attachments.map(({att}:any ) => att.attachment);
// }
// const formData = new FormData();
// buildFormData(formData, data);
// return formData;
if(typeof data['file'] == 'string') delete data['file']
// Return the data object directly // Return the data object directly
if (!Array.isArray(data.collections)) {
data.collections = [];
}
return data; return data;
}; };

View File

@ -61,7 +61,7 @@ const useTableColumns :any = () => {
<Actions <Actions
// importnat to return the row in on Edit Function to store in objectToEdit That Upper in Edit Modal // importnat to return the row in on Edit Function to store in objectToEdit That Upper in Edit Modal
onEdit={() => row} // onEdit={() => navigate('/')}
objectToEdit={row} objectToEdit={row}
showEdit={true} showEdit={true}
showView={false} showView={false}

View File

@ -98,3 +98,24 @@ svg {
margin-right: 10px; margin-right: 10px;
border-top: 2px solid gray; border-top: 2px solid gray;
} }
.param_field{
display: none !important;
width: 40% !important;
}
.flex_between{
display: flex;align-items: center;justify-content: space-around;
}
.flex_evenly{
display: flex;align-items: center;justify-content: space-evenly;
margin-bottom: 5px;
}
.add_sub_color{
background: rgba(3, 79, 210, 0.699) !important;
border-color: rgba(3, 79, 210, 0.699) !important;
}
.remove_sub_color{
background: rgba(255, 0, 0, 0.704) !important;
border-color: rgba(255, 0, 0, 0.704) !important;
}

View File

@ -1,5 +1,5 @@
export const BaseURL = `http://192.168.1.102:8000/`; export const BaseURL = `http://127.0.0.1:8000/`;
export const BaseURL_IMAGE = ''; export const BaseURL_IMAGE = '';

View File

@ -1,6 +1,6 @@
export function objectToKeyValueArray(obj: { [key: string]: any } | null | undefined): Array<{ key: string; value: any }> { export function objectToKeyValueArray(obj: { [key: string]: any } | null | undefined): Array<{ key: string; value: any }> {
if(!obj){ if (!obj) {
return [{key:'',value:''}] return [{ key: '', value: '' }]
} }
return Object.entries(obj).map(([key, value]) => ({ return Object.entries(obj).map(([key, value]) => ({
key, key,
@ -8,13 +8,16 @@ export function objectToKeyValueArray(obj: { [key: string]: any } | null | undef
})); }));
} }
// // Example usage: export function collectionObjectToArray(collection: { name: string; collectionParams: { key: string; value: string } } | null | undefined): Array<{ name: string; collectionParams: { key: string; value: string } }> {
// const inputObject = { if (!collection) {
// "wesam": "alabdeh", return [{ name: '', collectionParams: { key: '', value: '' } }];
// "ahmad": "alabdeh" }
// };
// const resultArray = objectToKeyValueArray(inputObject);
// console.log(resultArray);
// Output: [ { wesam: 'alabdeh' }, { ahmad: 'alabdeh' } ]
return [{
name: collection.name,
collectionParams: {
key: collection.collectionParams.key,
value: collection.collectionParams.value,
},
}];
}