leumas-universal-crud-react
Version:
Leumas Universal CRUD to a dynamic Endpoint, Setup your own Dynamic Endpoint and Use Leumas API to send to your MONGO clusters
473 lines (405 loc) • 13.1 kB
JSX
import {
LeumasBaseStyle,
InputStyles,
PasswordStyles,
EmailStyles,
NumberStyles,
DateStyles,
TextareaStyles,
SelectStyles,
SelectOptionStylexs,
MultiSelectStyles,
CheckboxStyles,
AiModelsStyles,
SliderStyles,
NonChangeableTextStyles,
FileUploadStyles,
ImageUploadStyles,
} from "../styles/baseStyles"
import AceEditorWrapper from "../Editors/ACE/AceEditor"
import AceSplitEditorWrapper from "../Editors/ACE/AceSplitEditorWrapper"
import BarcodeGenerator from "../Generators/BarcodeGenerator";
import SerialCodeGenerator from "../Generators/SerialCodeGenerator";
import MetaMaskButton from "leumas-metamask-quickpay"
// import UploaderToCloudinary from "../../helpers/UploaderToCloudinary";
function renderInputField({
inputField,
formValues,
handleInputChange,
handleFileChange,
styledInput,
aiModels = [],
setSearchTerm,
selectedItemId,
handleImageUpload,
handleFileUpload,
handleFolderUpload,
handleCheckboxChange,
}) {
switch (inputField.type) {
case 'password':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Enter Password"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type={"password"}
name={inputField.name}
placeholder={inputField.placeholder}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
/>
</>
);
case 'email':
return (<>
<label className="mx-2"><strong>{inputField?.label || "Enter Email" }</strong></label>
<div className="relative">
<div className="absolute inset-y-0 start-0 flex items-center ps-3.5 pointer-events-none">
<svg className="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 16">
<path d="m10.036 8.278 9.258-7.79A1.979 1.979 0 0 0 18 0H2A1.987 1.987 0 0 0 .641.541l9.395 7.737Z"/>
<path d="M11.241 9.817c-.36.275-.801.425-1.255.427-.428 0-.845-.138-1.187-.395L0 2.6V14a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2.5l-8.759 7.317Z"/>
</svg>
</div>
<input
className={`bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full ps-10 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500`}
type={inputField.type}
name={inputField.name}
placeholder={inputField.placeholder}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
/>
</div>
</>
);
case 'text':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Text Input" }</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type={inputField.type}
name={inputField.name}
placeholder={inputField.placeholder}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
/>
</>
);
case 'number':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Enter Number"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type={"number"}
name={inputField.name}
placeholder={inputField.placeholder}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
/>
</>
);
case 'date':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Date of Birth" }</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type={inputField.type}
name={inputField.name}
placeholder={inputField.placeholder}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
/>
</>
);
case 'textarea':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Enter Text" }</strong></label>
<textarea
className={`${LeumasBaseStyle} w-full max-h-64 min-h-32 p-4`}
name={inputField.name}
placeholder={inputField.placeholder}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
/>
</>
);
case 'metamask':
return (
<>
<label className="mx-2"><strong>Metamask Wallet</strong></label>
<MetaMaskButton
onDataChange={(address) => {
handleInputChange({
target: { name: inputField.name, value: address }
});
}}
/>
</>
);
case 'select':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Select Input"}</strong></label>
<select
className={`${LeumasBaseStyle} w-full`}
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
>
<option value="" disabled>{inputField.placeholder}</option>
{inputField.options.map((option, optIdx) => (
// Assuming `option` is a string, use it for both the value and the label
<option key={optIdx} value={option}>
{option}
</option>
))}
</select>
</>
);
case 'multiSelect':
return (
<>
<label className="mx-2"><strong>{inputField?.name || "Multi Select" }</strong></label>
<select
className={`${LeumasBaseStyle} w-full`}
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
multiple
>
<option className="bg-blue-400 text-white" value="">{inputField.placeholder}</option>
{inputField.options.map((option, optIdx) => (
<option className="bg-blue-400 text-white" key={optIdx} value={option}>
{option}
</option>
))}
</select>
</>
);
case 'checkbox':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Checkbox"}</strong></label>
<div className="flex items-center py-2 justify-start px-4">
<label className="inline-flex items-center cursor-pointer">
<input
className="sr-only peer" // Hide the checkbox visually but keep it accessible
type="checkbox"
name={inputField.name}
checked={formValues[inputField.name] || false} // Ensures the checkbox reflects its current state
onChange={handleCheckboxChange} // Handle changes to toggle the checkbox
/>
<span className="w-5 h-5 inline-flex justify-center items-center mr-2 rounded border border-gray-300 peer-checked:bg-blue-600 peer-checked:border-blue-600 peer-focus:ring peer-focus:ring-blue-500 peer-focus:ring-opacity-50 transition duration-150 ease-in-out">
<svg className="w-4 h-4 text-white hidden peer-checked:block" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 13l4 4L19 7"></path></svg>
</span>
{inputField.question || "True or False"}
</label>
</div>
</>
);
case 'AiModels':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Leumas AI Models" }</strong></label>
<select
className={`${LeumasBaseStyle} w-full`}
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
>
<option value="">{inputField.placeholder}</option>
{aiModels.map((model, idx) => (
<option className="bg-blue-400 text-white" key={idx} value={model.name}>
{model.name}
</option>
))}
</select>
</>
);
case 'slider':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Slider"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type="range"
name={inputField.name}
min={inputField.min || '0'}
max={inputField.max || '100'}
// Ensure the value is set to the midpoint between min and max if not already defined in formValues
value={formValues[inputField.name] || (Number(inputField.min || 0) + Number(inputField.max || 100)) / 2}
onChange={handleInputChange}
/>
<div className="flex items-center justify-between w-full shadow-lg p-2 border rounded-lg px-4">
<p><strong>MIN : </strong>{inputField?.min || 0}</p>
{/* Calculate and display the value as the midpoint between min and max or from formValues */}
<p><strong>Value: </strong>{formValues[inputField.name] || (Number(inputField.min || 0) + Number(inputField.max || 100)) / 2}</p>
<p><strong>MAX : </strong>{inputField?.max || 100}</p>
</div>
</>
);
case 'hidden':
return (
<input
className={`${LeumasBaseStyle} w-full`}
type="hidden"
name={inputField.name}
defaultValue={inputField.value}
value={inputField.value}
/>
);
case 'owner':
return (
<input
className={`${LeumasBaseStyle} w-full`}
type="hidden"
name={inputField.name}
value={inputField.value} // Assuming this is the user ID
/>
);
case 'nonChangeableText':
return (
<>
<label className="mx-2"><strong>{inputField?.label || "Non Changeable Text"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full bg-gray-500 p-2`}
readOnly
name={inputField.name}
value={inputField.value} // Assuming this is the user ID
/>
</>
);
case 'fileUpload':
return (
<>
<label><strong>{inputField?.label || "Upload File"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type="file"
name={inputField.name}
accept={inputField.accept || "*"} // Allows dynamic declaration of accepted files
onChange={handleFileUpload}
/>
{formValues[inputField.name] && (
<div className="mt-2">
<p>File uploaded successfully.</p>
</div>
)}
</>
);
case 'folderUpload':
return (
<>
<label><strong>{inputField?.label || "Upload Folder"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type="file"
name={inputField.name}
accept={inputField.accept || "*"}
webkitdirectory="true"
directory="true"
onChange={handleFolderUpload}
/>
{/* Display the number of files and file details after folder upload */}
{formValues[inputField.name] && (
<div className="mt-4">
<h3 className="font-bold text-lg mb-2">Uploaded Folder:</h3>
<p className="mb-4">Total Files: {formValues[inputField.name].filesCount}</p>
<ul className="w-full max-h-[300px] overflow-y-scroll border border-gray-200 rounded-lg shadow-md space-y-2 p-4">
{formValues[inputField.name].files.map((file, index) => (
<li key={index} className="border border-blue-800 rounded-md p-2 shadow-sm">
<p><strong>Name:</strong> {file.name}</p>
<p><strong>Size:</strong> {file.size} bytes</p>
<p><strong>Type:</strong> {file.type}</p>
</li>
))}
</ul>
</div>
)}
</>
);
case 'imageUpload':
return (
<>
<label><strong>{inputField?.label || "Upload Image"}</strong></label>
<input
className={`${LeumasBaseStyle} w-full`}
type="file"
name={inputField.name}
accept="image/*"
onChange={handleImageUpload}
/>
<label><strong>Uploaded Image</strong></label>
{/* Use the state value for the image's blob URL as the src attribute */}
{formValues[inputField.name] && <img src={formValues[inputField.name]} alt="Uploaded" style={{ maxWidth: '100%', maxHeight: '400px' }} />}
</>
);
case 'code':
return (
<AceEditorWrapper
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
// Additional Ace Editor props can go here...
/>
);
case 'splitCode':
return (
<AceSplitEditorWrapper
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
// Additional Split Editor props can go here...
/>
);
case 'serialCodeGenerator':
return (
<SerialCodeGenerator
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
// Additional Split Editor props can go here...
/>
);
case 'barcodeGenerator':
return (
<BarcodeGenerator
name={inputField.name}
value={formValues[inputField.name] || ''}
onChange={handleInputChange}
id={selectedItemId}
// Additional Split Editor props can go here...
/>
);
default:
return null;
}
}
export default renderInputField;
// case 'voice':
// return (
// <MicComponent
// name={inputField.name}
// onChange={handleInputChange}
// // Additional microphone component props can go here...
// />
// );
// case 'image':
// return (
// <UploaderToCloudinary
// onUpload={(url) => {
// handleInputChange({
// target: { name: inputField.name, value: url }
// });
// }}
// className={`${LeumasBaseStyle} w-full`}
// type="file"
// name={inputField.name}
// accept={inputField.type === 'image' ? "image/*" : "*"}
// onChange={handleInputChange}
// />
// );