This commit is contained in:
parent
a5bf267763
commit
b246410e11
|
@ -1,5 +1,7 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import KeyValuePair from "./KeyValuePair";
|
||||
import KeyValuePair2 from "./KeyValuePair2";
|
||||
|
||||
import JsonEditor from "./Editors";
|
||||
import { FaPaperPlane } from "react-icons/fa6";
|
||||
import { IoMdDownload } from "react-icons/io";
|
||||
|
@ -19,6 +21,7 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
|||
const [headers, setHeaders] = useState(
|
||||
content?.header ?? [{ key: "", value: "" }]
|
||||
);
|
||||
const [formData, setformData] = useState(content?.form_data ?? [{ key: "", value: "" }]);
|
||||
const [jsonBody, setJsonBody] = useState(content ?? {});
|
||||
const [activeTab, setActiveTab] = useState("query-params");
|
||||
|
||||
|
@ -39,27 +42,72 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
|||
setHeaders([...headers, { key: "", value: "" }]);
|
||||
setisSaved(false);
|
||||
};
|
||||
const handleAddFormData = () => {
|
||||
setformData([...formData, { key: "", value: "" }]);
|
||||
setisSaved(false);
|
||||
};
|
||||
|
||||
// const handleSubmit = (e: React.FormEvent) => {
|
||||
// e.preventDefault();
|
||||
// const params = queryParams.reduce((acc, { key, value }) => {
|
||||
// if (key) acc[key] = value;
|
||||
// return acc;
|
||||
// }, {} as Record<string, string>);
|
||||
|
||||
// const headerObj = headers.reduce((acc, { key, value }) => {
|
||||
// if (key) acc[key] = value;
|
||||
// return acc;
|
||||
// }, {} as Record<string, string>);
|
||||
|
||||
// onSubmit({
|
||||
// method,
|
||||
// url,
|
||||
// params,
|
||||
// headers: headerObj,
|
||||
// data: jsonBody,
|
||||
// });
|
||||
// };
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
// Reduce query parameters and headers to objects
|
||||
const params = queryParams.reduce((acc, { key, value }) => {
|
||||
if (key) acc[key] = value;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
|
||||
const headerObj = headers.reduce((acc, { key, value }) => {
|
||||
if (key) acc[key] = value;
|
||||
return acc;
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
|
||||
// If formData is not empty, convert it to FormData
|
||||
let data: Record<string, any> | FormData;
|
||||
if (formData.length > 0) {
|
||||
data = new FormData();
|
||||
formData.forEach(({ key, value }) => {
|
||||
if (key) {
|
||||
if (value instanceof File) {
|
||||
data.append(key, value); // Append file
|
||||
} else {
|
||||
data.append(key, value); // Append text
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
data = jsonBody; // If formData is empty, use jsonBody
|
||||
}
|
||||
|
||||
// Call onSubmit with the appropriate data
|
||||
onSubmit({
|
||||
method,
|
||||
url,
|
||||
params,
|
||||
headers: headerObj,
|
||||
data: jsonBody,
|
||||
data,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const handleRequestEditorChange = (value: string) => {
|
||||
setJsonBody(value);
|
||||
|
@ -188,6 +236,19 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
|||
JSON
|
||||
</button>
|
||||
</li>
|
||||
<li className="nav-item p-2" role="presentation">
|
||||
<button
|
||||
className={`nav-link ${
|
||||
activeTab === "form"
|
||||
? "text-[black] border-solid border-[black]"
|
||||
: "text-[grey]"
|
||||
}`}
|
||||
id="form-tab"
|
||||
onClick={() => setActiveTab("form")}
|
||||
>
|
||||
Form
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div className="tab-content p-3 border-top-0 border">
|
||||
|
@ -256,6 +317,32 @@ const Form: React.FC<FormProps> = ({ onSubmit, content, setisRefresh }) => {
|
|||
/>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === "form" && (
|
||||
<div
|
||||
className="tab-pane fade show active h-auto overflow-hidden"
|
||||
id="json"
|
||||
role="tabpanel"
|
||||
aria-labelledby="json-tab"
|
||||
>
|
||||
{formData.map((header, index) => (
|
||||
<KeyValuePair2
|
||||
key={index}
|
||||
index={index}
|
||||
pair={header}
|
||||
setPairs={setformData}
|
||||
pairs={formData}
|
||||
setisSaved={setisSaved}
|
||||
/>
|
||||
))}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleAddFormData}
|
||||
className="mt-2 btn btn-outline-success border-solid border-[green] text-[green]"
|
||||
>
|
||||
Add Form
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
import React, { useState } from "react";
|
||||
import { FaCloudUploadAlt } from "react-icons/fa";
|
||||
import { FaArrowDown, FaXmark } from "react-icons/fa6";
|
||||
|
||||
interface KeyValuePairProps {
|
||||
index: number;
|
||||
pair: { key: string; value: string | File[]; type: "text" | "[]" };
|
||||
setPairs: React.Dispatch<
|
||||
React.SetStateAction<
|
||||
{ key: string; value: string | File[]; type: "text" | "file" }[]
|
||||
>
|
||||
>;
|
||||
pairs: { key: string; value: string | File[]; type: "text" | "file" }[];
|
||||
setisSaved: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
const KeyValuePair: React.FC<KeyValuePairProps> = ({
|
||||
index,
|
||||
pair,
|
||||
setPairs,
|
||||
pairs,
|
||||
setisSaved,
|
||||
}) => {
|
||||
const [type, settype] = useState("text");
|
||||
const handleKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newPairs = [...pairs];
|
||||
newPairs[index] = { ...newPairs[index], key: e.target.value };
|
||||
setPairs(newPairs);
|
||||
setisSaved(false);
|
||||
};
|
||||
|
||||
const handleValueChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newPairs = [...pairs];
|
||||
if (type === "text") {
|
||||
newPairs[index] = { ...newPairs[index], value: e.target.value };
|
||||
} else if (type === "file" && e.target.files) {
|
||||
const files = Array.from(e.target.files); // Support multiple files
|
||||
newPairs[index] = { ...newPairs[index], value: files };
|
||||
}
|
||||
setPairs(newPairs);
|
||||
setisSaved(false);
|
||||
};
|
||||
|
||||
const handleTypeChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const newPairs = [...pairs];
|
||||
settype(e.target.value);
|
||||
newPairs[index] = {
|
||||
...newPairs[index],
|
||||
type: e.target.value,
|
||||
value: "",
|
||||
};
|
||||
setPairs(newPairs);
|
||||
setisSaved(false);
|
||||
};
|
||||
const handleRemoveFile = (fileToRemove: File) => {
|
||||
const newPairs = [...pairs];
|
||||
const updatedFiles = (newPairs[index].value as File[]).filter(
|
||||
(file) => file !== fileToRemove
|
||||
);
|
||||
newPairs[index] = { ...newPairs[index], value: updatedFiles };
|
||||
setPairs(newPairs);
|
||||
setisSaved(false);
|
||||
};
|
||||
const handleRemove = () => {
|
||||
const newPairs = pairs.filter((_, i) => i !== index);
|
||||
setPairs(newPairs);
|
||||
setisSaved(false);
|
||||
};
|
||||
|
||||
const handleFileClick = () => {
|
||||
const fileInput = document.getElementById(`file-input-${index}`);
|
||||
if (fileInput) {
|
||||
fileInput.click();
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="flex items-center mb-2 w-full justify-between">
|
||||
<input
|
||||
type="text"
|
||||
className="form-input flex-grow mr-2 max-w-[200px]"
|
||||
placeholder="Key"
|
||||
value={pair.key}
|
||||
onChange={handleKeyChange}
|
||||
/>
|
||||
|
||||
<select
|
||||
className="form-select flex w-[100px] mr-2"
|
||||
value={pair.type}
|
||||
onChange={handleTypeChange}
|
||||
>
|
||||
<option value="text">Text</option>
|
||||
<option value="file">File</option>
|
||||
</select>
|
||||
|
||||
{type === "text" ? (
|
||||
<input
|
||||
type="text"
|
||||
className="form-input flex-grow mr-2"
|
||||
placeholder="Value"
|
||||
value={pair.value as string}
|
||||
onChange={handleValueChange}
|
||||
/>
|
||||
) : (
|
||||
<div className="flex items-center min-w-[150px]">
|
||||
<input
|
||||
type="file"
|
||||
id={`file-input-${index}`}
|
||||
className="hidden"
|
||||
onChange={handleValueChange}
|
||||
multiple={true} // Updated to boolean for JSX
|
||||
/>
|
||||
<label htmlFor={`file-input-${index}`}>
|
||||
<button
|
||||
onClick={handleFileClick}
|
||||
type="button"
|
||||
className="btn p-2 flex items-center"
|
||||
>
|
||||
<FaCloudUploadAlt />
|
||||
</button>
|
||||
</label>
|
||||
{Array.isArray(pair.value) && pair.value.length > 0 && (
|
||||
<div className="flex flex-wrap ml-2">
|
||||
{pair.value.map((file, idx) => (
|
||||
<div key={idx} className="flex items-center mb-1 border-[#eee] border px-1 rounded-md ">
|
||||
<span className="mr-2 text-[13px]">{file.name}</span>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-danger text-red-400 border-none shadow-none p-1 "
|
||||
onClick={() => handleRemoveFile(file)}
|
||||
>
|
||||
<FaXmark/>
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-danger text-red-400 border-red-400 p-1 px-3 ml-2"
|
||||
onClick={handleRemove}
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default KeyValuePair;
|
Loading…
Reference in New Issue