fix jsp pein de truc en vrais
This commit is contained in:
parent
18b7052259
commit
2868efcda4
1642
package-lock.json
generated
1642
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,12 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Form, Input, InputNumber, Button, Select } from "antd";
|
||||
import { Form, Input, InputNumber, Button, Select, DatePicker } from "antd";
|
||||
import axios from "axios";
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Option } = Select;
|
||||
const dateFormat = "YYYY-MM-DD";
|
||||
|
||||
export const FormCreateItem = () => {
|
||||
export const FormCreateItem = ({ onClose }) => {
|
||||
const [form] = Form.useForm();
|
||||
const [rooms, setRooms] = useState([]);
|
||||
|
||||
@ -31,6 +32,8 @@ export const FormCreateItem = () => {
|
||||
values,
|
||||
);
|
||||
console.log(response.data);
|
||||
// Fermer la fenêtre modale après soumission réussie
|
||||
onClose();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@ -58,7 +61,7 @@ export const FormCreateItem = () => {
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
<Form.Item label="Purchase Date" name="purchaseDate">
|
||||
<Input />
|
||||
<DatePicker format={dateFormat} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" name="description">
|
||||
<TextArea rows={4} />
|
||||
|
@ -3,113 +3,125 @@ import { Form, Input, InputNumber, Button, Select, DatePicker } from "antd";
|
||||
import axios from "axios";
|
||||
import { getRooms } from "../../api/room";
|
||||
import { getItem } from "../../api/item";
|
||||
import moment from 'moment';
|
||||
import moment from "moment";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
|
||||
function formatItem(itemObj) {
|
||||
const {_id,brand,model,room,price,purchaseDate,description,categories,createdAt,updatedAt,__v,link} = itemObj
|
||||
const formattedPurchaseDate = typeof purchaseDate === 'string' ? new Date(purchaseDate) : purchaseDate;
|
||||
const {
|
||||
_id,
|
||||
brand,
|
||||
model,
|
||||
room,
|
||||
price,
|
||||
purchaseDate,
|
||||
description,
|
||||
categories,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
__v,
|
||||
link,
|
||||
} = itemObj;
|
||||
const formattedPurchaseDate =
|
||||
typeof purchaseDate === "string" ? new Date(purchaseDate) : purchaseDate;
|
||||
|
||||
return {
|
||||
_id,
|
||||
brand,
|
||||
model,
|
||||
room,
|
||||
price,
|
||||
purchaseDate: formattedPurchaseDate,
|
||||
description,
|
||||
categories,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
__v,
|
||||
link
|
||||
};
|
||||
return {
|
||||
_id,
|
||||
brand,
|
||||
model,
|
||||
room,
|
||||
price,
|
||||
purchaseDate: formattedPurchaseDate,
|
||||
description,
|
||||
categories,
|
||||
createdAt,
|
||||
updatedAt,
|
||||
__v,
|
||||
link,
|
||||
};
|
||||
}
|
||||
|
||||
export const FormUpdateItem = ({ itemId }) => {
|
||||
const [form] = Form.useForm();
|
||||
const [rooms, setRooms] = useState([]);
|
||||
const [item, setItem] = useState(null)
|
||||
export const FormUpdateItem = ({ itemId, onClose }) => {
|
||||
const [form] = Form.useForm();
|
||||
const [rooms, setRooms] = useState([]);
|
||||
const [item, setItem] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const roomsResponse = await getRooms();
|
||||
setRooms(roomsResponse);
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
const roomsResponse = await getRooms();
|
||||
setRooms(roomsResponse);
|
||||
|
||||
const itemResponse = await getItem(itemId);
|
||||
console.log(itemResponse)
|
||||
setItem(formatItem(itemResponse));
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, [itemId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (item) {
|
||||
form.setFieldsValue({
|
||||
...item,
|
||||
purchaseDate: item.purchaseDate ? moment(item.purchaseDate) : null,
|
||||
});
|
||||
}
|
||||
}, [item, form]);
|
||||
|
||||
const onFinish = async (values) => {
|
||||
try {
|
||||
const response = await axios.put(
|
||||
`${import.meta.env.VITE_API_URL}/item/${item._id}`,
|
||||
values,
|
||||
);
|
||||
console.log(response.data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
const itemResponse = await getItem(itemId);
|
||||
console.log(itemResponse);
|
||||
setItem(formatItem(itemResponse));
|
||||
};
|
||||
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={onFinish}
|
||||
initialValues={item} // Initialise le formulaire avec les valeurs de l'élément
|
||||
>
|
||||
<h1>Update Item</h1>
|
||||
<Form.Item label="Brand" name="brand">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item label="Model" name="model">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item label="Room" name="room">
|
||||
<Select placeholder="Select a room">
|
||||
{console.log(rooms)}
|
||||
{
|
||||
rooms.map((room) => (
|
||||
<Option key={room._id} value={room._id}>
|
||||
{room.name}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="Price" name="price">
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
<Form.Item label="Purchase Date" name="purchaseDate">
|
||||
<DatePicker
|
||||
dateFormat={dateFormat}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" name="description">
|
||||
<Input.TextArea rows={4} />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
fetchData();
|
||||
}, [itemId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (item) {
|
||||
form.setFieldsValue({
|
||||
...item,
|
||||
purchaseDate: item.purchaseDate ? moment(item.purchaseDate) : null,
|
||||
});
|
||||
}
|
||||
}, [item, form]);
|
||||
|
||||
const onFinish = async (values) => {
|
||||
try {
|
||||
const response = await axios.put(
|
||||
`${import.meta.env.VITE_API_URL}/item/${item._id}`,
|
||||
values,
|
||||
);
|
||||
console.log(response.data);
|
||||
// Fermer la fenêtre modale après soumission réussie
|
||||
onClose();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const dateFormat = "YYYY-MM-DD";
|
||||
return (
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={onFinish}
|
||||
initialValues={item} // Initialise le formulaire avec les valeurs de l'élément
|
||||
>
|
||||
<h1>Update Item</h1>
|
||||
<Form.Item label="Brand" name="brand">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item label="Model" name="model">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item label="Room" name="room">
|
||||
<Select placeholder="Select a room">
|
||||
{console.log(rooms)}
|
||||
{rooms.map((room) => (
|
||||
<Option key={room._id} value={room._id}>
|
||||
{room.name}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label="Price" name="price">
|
||||
<InputNumber />
|
||||
</Form.Item>
|
||||
<Form.Item label="Purchase Date" name="purchaseDate">
|
||||
<DatePicker dateFormat={dateFormat} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Description" name="description">
|
||||
<Input.TextArea rows={4} />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default FormUpdateItem;
|
||||
|
@ -1,16 +1,14 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import '../../assets/styles/modal.css'
|
||||
import '../../assets/styles/itembox.css'
|
||||
import FormUpdateItem from '../form/formUpdateItem';
|
||||
import {Image } from '../parts/image'
|
||||
|
||||
|
||||
import React, { useState } from "react";
|
||||
import "../../assets/styles/modal.css";
|
||||
import "../../assets/styles/itembox.css";
|
||||
import FormUpdateItem from "../form/formUpdateItem";
|
||||
import { Image } from "../parts/image";
|
||||
|
||||
// Composant Description
|
||||
const Description = ({ title, children }) => {
|
||||
return (
|
||||
<div className="description">
|
||||
<h2 className="text-ellipsis">{title}</h2>
|
||||
<h2 className="text-ellipsis">{title}</h2>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
@ -18,7 +16,6 @@ const Description = ({ title, children }) => {
|
||||
|
||||
// Composant Caractéristique
|
||||
const Characteristic = ({ label, value }) => {
|
||||
|
||||
return (
|
||||
<div className="characteristic">
|
||||
<strong>{label}:</strong> {value}
|
||||
@ -26,52 +23,48 @@ const Characteristic = ({ label, value }) => {
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Composant Détails du Produit
|
||||
export const ItemBox = ({ model, brand, purchaseDate, price, _id }) => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
// Fonction pour ouvrir la fenêtre modale
|
||||
const openModal = () => {
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
|
||||
// Fonction pour ouvrir la fenêtre modale
|
||||
const openModal = () => {
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
// Fonction pour fermer la fenêtre modale
|
||||
const closeModal = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
// Fonction pour fermer la fenêtre modale
|
||||
const closeModal = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
let productname = brand + " " + model;
|
||||
let formatedPrice = price + "€";
|
||||
let formatedDate = new Date(purchaseDate).toLocaleDateString("fr-FR");
|
||||
|
||||
let request = brand + " " + model;
|
||||
|
||||
|
||||
|
||||
let productname = brand + " " + model;
|
||||
let formatedPrice = price + "€";
|
||||
let formatedDate = new Date(purchaseDate).toLocaleDateString('fr-FR');
|
||||
|
||||
let request = brand + " " + model
|
||||
|
||||
return (
|
||||
<div className="product-details" >
|
||||
<Description title={productname} >
|
||||
<Image request={request} _id={_id} alt="Product" />
|
||||
<Characteristic label="Model" value={model} />
|
||||
<Characteristic label="Brand" value={brand} />
|
||||
<Characteristic label="Purchase Date" value={formatedDate} />
|
||||
<Characteristic label="Price" value={formatedPrice} />
|
||||
{/* Bouton d'édition pour ouvrir la fenêtre modale */}
|
||||
<button onClick={openModal}>Edit</button>
|
||||
</Description>
|
||||
{/* Fenêtre modale */}
|
||||
{isModalOpen && (
|
||||
<div className="modal">
|
||||
<div className="modal-content">
|
||||
<span className="close" onClick={closeModal}>×</span>
|
||||
<FormUpdateItem itemId={_id}>{console.log("item ID :" + _id)}</FormUpdateItem>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
return (
|
||||
<div className="product-details">
|
||||
<Description title={productname}>
|
||||
<Image request={request} _id={_id} alt="Product" />
|
||||
<Characteristic label="Model" value={model} />
|
||||
<Characteristic label="Brand" value={brand} />
|
||||
<Characteristic label="Purchase Date" value={formatedDate} />
|
||||
<Characteristic label="Price" value={formatedPrice} />
|
||||
{/* Bouton d'édition pour ouvrir la fenêtre modale */}
|
||||
<button onClick={openModal}>Edit</button>
|
||||
</Description>
|
||||
{/* Fenêtre modale pour la mise à jour */}
|
||||
{isModalOpen && (
|
||||
<div className="modal">
|
||||
<div className="modal-content">
|
||||
<span className="close" onClick={closeModal}>
|
||||
×
|
||||
</span>
|
||||
<FormUpdateItem itemId={_id} onClose={closeModal} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -1,18 +1,16 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import axios from 'axios'; // Assurez-vous que le chemin d'importation soit correct
|
||||
import { ItemBox } from './ItemBox';
|
||||
import { Space, DatePicker, Row, Col, Select, Input, InputNumber } from 'antd';
|
||||
import '../../assets/styles/item-page.css'
|
||||
|
||||
|
||||
import axios from "axios";
|
||||
import { ItemBox } from "./ItemBox";
|
||||
import { DatePicker, Row, Col, Select, Input, InputNumber } from "antd";
|
||||
import "../../assets/styles/item-page.css";
|
||||
import FormCreateItem from "../form/formCreateItem";
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
const { Option } = Select;
|
||||
|
||||
const itemsPerPage = 8; // Nombre total d'items par page
|
||||
const itemsPerRow = 4; // Nombre d'items par rangée
|
||||
const itemsPerPage = 8;
|
||||
const itemsPerRow = 4;
|
||||
|
||||
// Fonction pour diviser le tableau d'items en rangées
|
||||
const chunkArray = (arr, size) => {
|
||||
const chunkedArr = [];
|
||||
for (let i = 0; i < arr.length; i += size) {
|
||||
@ -21,39 +19,26 @@ const chunkArray = (arr, size) => {
|
||||
return chunkedArr;
|
||||
};
|
||||
|
||||
// Composant d'affichage de la page
|
||||
export const ItemPage = () => {
|
||||
const [items, setItems] = useState([]);
|
||||
const [filteredItems, setFilteredItems] = useState([]); // State pour les items filtrés
|
||||
const [filteredItems, setFilteredItems] = useState([]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [filterName, setFilterName] = useState('');
|
||||
const [filterPriceMin, setFilterPriceMin] = useState('');
|
||||
const [filterPriceMax, setFilterPriceMax] = useState('');
|
||||
const [filterName, setFilterName] = useState("");
|
||||
const [filterPriceMin, setFilterPriceMin] = useState("");
|
||||
const [filterPriceMax, setFilterPriceMax] = useState("");
|
||||
const [filterDateRange, setFilterDateRange] = useState([]);
|
||||
const [selectedRoom, setSelectedRoom] = useState('all'); // State pour la chambre sélectionnée
|
||||
|
||||
const [rooms, setRooms] = useState([]); // State pour stocker les chambres
|
||||
const [selectedRoom, setSelectedRoom] = useState("all");
|
||||
const [rooms, setRooms] = useState([]);
|
||||
const [isCreateItemModalOpen, setIsCreateItemModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchItems = async () => {
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`${import.meta.env.VITE_API_URL}/item`,
|
||||
);
|
||||
|
||||
//await response.data.forEach(async (item) => {
|
||||
// let cacheUrl = localStorage.getItem(item._id);
|
||||
// if (cacheUrl == null || cacheUrl == "") {
|
||||
// let request = item.brand + " " + item.model
|
||||
// cacheUrl = await searchAndResizeImage(request)
|
||||
// await localStorage.setItem(item._id, cacheUrl)
|
||||
// console.log("mise en cache "+ item.imageUrl)
|
||||
// }
|
||||
// item.imageUrl = cacheUrl;
|
||||
//})
|
||||
);
|
||||
setItems(response.data);
|
||||
}
|
||||
catch (error) {
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
@ -74,92 +59,102 @@ export const ItemPage = () => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
// Filtrer les éléments chaque fois que les filtres ou la chambre sélectionnée changent
|
||||
const filtered = items.filter(item => {
|
||||
// Filtrer par chambre si une chambre est sélectionnée
|
||||
const matchesRoom = selectedRoom === 'all' || item.room === selectedRoom;
|
||||
// Filtrer par nom (brand ou model)
|
||||
const matchesName = item.brand.toLowerCase().includes(filterName.toLowerCase()) ||
|
||||
item.model.toLowerCase().includes(filterName.toLowerCase());
|
||||
// Filtrer par prix
|
||||
const filtered = items.filter((item) => {
|
||||
const matchesRoom = selectedRoom === "all" || item.room === selectedRoom;
|
||||
const matchesName =
|
||||
item.brand.toLowerCase().includes(filterName.toLowerCase()) ||
|
||||
item.model.toLowerCase().includes(filterName.toLowerCase());
|
||||
const matchesPrice =
|
||||
(filterPriceMin === '' || item.price >= parseFloat(filterPriceMin)) &&
|
||||
(filterPriceMax === '' || item.price <= parseFloat(filterPriceMax));
|
||||
// Filtrer par date
|
||||
const matchesDate = filterDateRange.length === 0 || (
|
||||
new Date(item.purchaseDate) >= filterDateRange[0] &&
|
||||
new Date(item.purchaseDate) <= filterDateRange[1]
|
||||
);
|
||||
(filterPriceMin === "" || item.price >= parseFloat(filterPriceMin)) &&
|
||||
(filterPriceMax === "" || item.price <= parseFloat(filterPriceMax));
|
||||
const matchesDate =
|
||||
filterDateRange.length === 0 ||
|
||||
(new Date(item.purchaseDate) >= filterDateRange[0] &&
|
||||
new Date(item.purchaseDate) <= filterDateRange[1]);
|
||||
return matchesRoom && matchesName && matchesPrice && matchesDate;
|
||||
});
|
||||
setFilteredItems(filtered);
|
||||
}, [items, selectedRoom, filterName, filterPriceMin, filterPriceMax, filterDateRange]);
|
||||
}, [
|
||||
items,
|
||||
selectedRoom,
|
||||
filterName,
|
||||
filterPriceMin,
|
||||
filterPriceMax,
|
||||
filterDateRange,
|
||||
]);
|
||||
|
||||
const handleNextPage = () => {
|
||||
setCurrentPage(prevPage => prevPage + 1);
|
||||
setCurrentPage((prevPage) => prevPage + 1);
|
||||
};
|
||||
|
||||
const handlePrevPage = () => {
|
||||
setCurrentPage(prevPage => prevPage - 1);
|
||||
setCurrentPage((prevPage) => prevPage - 1);
|
||||
};
|
||||
|
||||
const handleRoomChange = (value) => {
|
||||
setSelectedRoom(value);
|
||||
};
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setIsCreateItemModalOpen(false);
|
||||
};
|
||||
|
||||
const chunkedItems = chunkArray(filteredItems, itemsPerRow);
|
||||
const startIndex = (currentPage - 1) * (itemsPerPage / itemsPerRow);
|
||||
const endIndex = startIndex + (itemsPerPage / itemsPerRow);
|
||||
const endIndex = startIndex + itemsPerPage / itemsPerRow;
|
||||
const rowsToDisplay = chunkedItems.slice(startIndex, endIndex);
|
||||
|
||||
return (
|
||||
<div className="item-container">
|
||||
<div className="filters">
|
||||
<div className="filter-group">
|
||||
<label htmlFor="roomSelect">Chambre :</label>
|
||||
<Select id="roomSelect" defaultValue="all" style={{ width: 120 }} onChange={handleRoomChange}>
|
||||
<Option value="all">Toutes</Option>
|
||||
{rooms.map(room => (
|
||||
<Option key={room._id} value={room._id}>{room.name}</Option>
|
||||
))}
|
||||
</Select>
|
||||
</div>
|
||||
<div className="filter-group">
|
||||
<label htmlFor="nameInput">Recherche par nom :</label>
|
||||
<Input id="nameInput" placeholder="Recherche par nom" value={filterName} onChange={e => setFilterName(e.target.value)} />
|
||||
</div>
|
||||
<div className="filter-group">
|
||||
<label>Prix :</label>
|
||||
<InputNumber placeholder="Prix min" value={filterPriceMin} onChange={value => setFilterPriceMin(value)} />
|
||||
<span> - </span>
|
||||
<InputNumber placeholder="Prix max" value={filterPriceMax} onChange={value => setFilterPriceMax(value)} />
|
||||
</div>
|
||||
<div className="filter-group">
|
||||
<label>Date d'achat :</label>
|
||||
<RangePicker format="YYYY-MM-DD" onChange={dates => setFilterDateRange(dates)} value={filterDateRange} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="item-list">
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
{rowsToDisplay.map((row, rowIndex) => (
|
||||
<React.Fragment key={rowIndex}>
|
||||
{row.map(item => (
|
||||
<Col className="gutter-row" span={24 / itemsPerRow} key={item._id}>
|
||||
<ItemBox {...item} />
|
||||
</Col>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
<div className="pagination">
|
||||
<button onClick={handlePrevPage} disabled={currentPage === 1}>Précédente</button>
|
||||
<span>Page {currentPage}</span>
|
||||
<button onClick={handleNextPage} disabled={endIndex >= chunkedItems.length}>Suivante</button>
|
||||
<div className="item-container">
|
||||
<div className="filters">{/* Filters here */}</div>
|
||||
|
||||
{/* Button to open create item modal */}
|
||||
<button onClick={() => setIsCreateItemModalOpen(true)}>
|
||||
Create Item
|
||||
</button>
|
||||
|
||||
{/* Create item form modal */}
|
||||
{isCreateItemModalOpen && (
|
||||
<div className="modal">
|
||||
<div className="modal-content">
|
||||
<span className="close" onClick={handleCloseModal}>
|
||||
×
|
||||
</span>
|
||||
<FormCreateItem onClose={handleCloseModal} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="item-list">
|
||||
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }}>
|
||||
{rowsToDisplay.map((row, rowIndex) => (
|
||||
<React.Fragment key={rowIndex}>
|
||||
{row.map((item) => (
|
||||
<Col
|
||||
className="gutter-row"
|
||||
span={24 / itemsPerRow}
|
||||
key={item._id}
|
||||
>
|
||||
<ItemBox {...item} />
|
||||
</Col>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<div className="pagination">
|
||||
<button onClick={handlePrevPage} disabled={currentPage === 1}>
|
||||
Previous
|
||||
</button>
|
||||
<span>Page {currentPage}</span>
|
||||
<button
|
||||
onClick={handleNextPage}
|
||||
disabled={endIndex >= chunkedItems.length}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user