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
159 lines (130 loc) • 6.35 kB
JSX
import { useTrail, animated } from 'react-spring';
import { AtomSpinner } from 'react-epic-spinners';
import {schemaToCardMapping} from '../Schemas/SchemaMapping'; // Ensure the path is correct
import {useState, useEffect} from "react"
import MultiPageForm from "../../Forms/MultiPageForm";
import DefaultCard from "leumas-react-cards"
import { MdChevronLeft, MdChevronRight, MdEdit, MdDelete } from 'react-icons/md';
import { useNavigate } from 'react-router-dom';
import ToggleStatus from "./ToggleStatus"
import {useTheme} from "../../Theme/ThemeContext"
export const ItemRenderer = ({ model, renderData, setMode, setIcon, token, baseLink = "/dashboard" }) => {
const { theme } = useTheme();
const bgColor = theme === 'dark' ? 'bg-black' : 'bg-white';
const [items, setItems] = useState([]);
const [isFormVisible, setIsFormVisible] = useState(false);
const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(3); // Adjust this number based on your preference
const lastItemIndex = currentPage * itemsPerPage;
const firstItemIndex = lastItemIndex - itemsPerPage;
const currentItems = items.slice(firstItemIndex, lastItemIndex);
const navigate = useNavigate();
const handleCardClick = (itemId) => {
navigate(`${baseLink}/${itemId}`);
};
console.log("Model " , model)
// Dynamically get the Card, Form, Tool, and Icon components based on the model
const Card = schemaToCardMapping[model]?.card;
const Form = schemaToCardMapping[model]?.form;
const Tool = schemaToCardMapping[model]?.tool;
const Icon = schemaToCardMapping[model]?.icon;
// const categoryModel = model && model.categories && model?.categories[index] ? model?.categories[index] : model;
const toggleFormVisibility = () => {
setIsFormVisible(!isFormVisible);
};
useEffect(() => {
setItems(renderData);
}, [renderData]);
useEffect(() => {
// Pass the Icon back to the parent when the model changes
setIcon(Icon);
}, [Icon, setIcon]);
const geometryBackground = "";
const depthStyle = "shadow-2xl rounded-lg";
const label3DStyle = "text-2xl shadow-3d font-bold";
const sunkenEffect = "shadow-inner border border-gray-300 rounded-lg";
const trail = useTrail(currentItems?.length || 0, {
from: { transform: 'translate3d(-100%,0,0)', opacity: 0 },
to: { transform: 'translate3d(0%,0,0)', opacity: 1 },
});
return (
<div className="p-4">
{/* Grid Section with Paginated Items */}
<div className={`${depthStyle} p-4 mb-4`}>
<h2 className={`${label3DStyle} mb-4`}>My {model || "collection(s)"}s</h2>
{currentItems && Array.isArray(currentItems) && currentItems.length > 0 ? (
<div className={`${sunkenEffect} grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 auto-rows-fr p-2`}>
{trail.map((props, index) => (
<animated.div style={props} key={currentItems[index]._id} className="relative">
<div onClick={() => handleCardClick(currentItems[index]._id)} className="cursor-pointer">
{Card
? <Card model={model} item={currentItems[index]} setMode={setMode} />
: <DefaultCard model={model} item={currentItems[index]} setMode={setMode} />
}
</div>
<div className={`absolute bottom-0 left-0 right-0 flex justify-center items-center gap-4 p-2 border rounded-b-lg ${bgColor}`}>
<ToggleStatus />
<button
className="p-1 bg-blue-400 rounded-full hover:bg-gray-300"
onClick={() => handleEdit(currentItems[index]._id)}
aria-label="Edit Item"
>
<MdEdit size="24" />
</button>
<button
className="p-1 bg-red-200 rounded-full hover:bg-gray-300"
onClick={() => handleDelete(currentItems[index]._id)}
aria-label="Delete Item"
>
<MdDelete size="24" />
</button>
</div>
</animated.div>
))}
</div>
) : (
<div className="text-center flex items-center justify-between h-full w-full flex-col gap-4">
Sorry, we couldn't find any data in our backend
Try Creating one or pressing the fetch button once more, after selecting your type
<AtomSpinner color="red" />
</div>
)}
</div>
{/* Pagination Controls */}
<div className="flex justify-center items-center mt-4">
<button
onClick={() => setCurrentPage(currentPage - 1)}
disabled={currentPage === 1}
className="p-2 bg-red-200 rounded-full disabled:bg-red-400 mr-4"
aria-label="Previous Page"
>
<MdChevronLeft size="24" />
</button>
{/* Items count or current page indicator can go here if needed */}
<button
onClick={() => setCurrentPage(currentPage + 1)}
disabled={currentPage === Math.ceil(items.length / itemsPerPage)}
className="p-2 bg-blue-200 rounded-full disabled:bg-blue-400 ml-4"
aria-label="Next Page"
>
<MdChevronRight size="24" />
</button>
</div>
{/* MultiPageForm Area */}
<div className={`${depthStyle} p-4`}>
<h2 className={`${label3DStyle} mb-4`}>Create New</h2>
<button className={`w-full rounded-lg p-2 text-[8px] border hover:scale-105`} onClick={toggleFormVisibility} >
{isFormVisible ? "Close Form" : "Open Form"}
</button>
{isFormVisible && (
<MultiPageForm
pages={Form}
model={model}
endpoint={'LeumasAPI'}
token={token}
/>
)}
</div>
</div>
);
};