{ const totalPages = Math.ceil(totalQuizzes / quizzesPerPage); const scrollRef = useRef(null); const [showLeftArrow, setShowLeftArrow] = useState(false); const [showRightArrow, setShowRightArrow] = useState(true); const [showManualInput, setShowManualInput] = useState(false); const [manualPageInput, setManualPageInput] = useState(""); const inputRef = useRef(null); // Initialize current page from sessionStorage or props const initialPage = () => { const savedPage = sessionStorage.getItem("quizListPage"); // return savedPage ? Math.min(parseInt(savedPage, 10), totalPages) : propCurrentPage; return savedPage ? savedPage : propCurrentPage; }; const [currentPage, setCurrentPage] = useState(initialPage); const handlePageChange = (nu"> { const totalPages = Math.ceil(totalQuizzes / quizzesPerPage); const scrollRef = useRef(null); const [showLeftArrow, setShowLeftArrow] = useState(false); const [showRightArrow, setShowRightArrow] = useState(true); const [showManualInput, setShowManualInput] = useState(false); const [manualPageInput, setManualPageInput] = useState(""); const inputRef = useRef(null); // Initialize current page from sessionStorage or props const initialPage = () => { const savedPage = sessionStorage.getItem("quizListPage"); // return savedPage ? Math.min(parseInt(savedPage, 10), totalPages) : propCurrentPage; return savedPage ? savedPage : propCurrentPage; }; const [currentPage, setCurrentPage] = useState(initialPage); const handlePageChange = (nu"> { const totalPages = Math.ceil(totalQuizzes / quizzesPerPage); const scrollRef = useRef(null); const [showLeftArrow, setShowLeftArrow] = useState(false); const [showRightArrow, setShowRightArrow] = useState(true); const [showManualInput, setShowManualInput] = useState(false); const [manualPageInput, setManualPageInput] = useState(""); const inputRef = useRef(null); // Initialize current page from sessionStorage or props const initialPage = () => { const savedPage = sessionStorage.getItem("quizListPage"); // return savedPage ? Math.min(parseInt(savedPage, 10), totalPages) : propCurrentPage; return savedPage ? savedPage : propCurrentPage; }; const [currentPage, setCurrentPage] = useState(initialPage); const handlePageChange = (nu">
import React, { useRef, useEffect, useState } from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
const Pagination = ({
quizzesPerPage,
totalQuizzes,
currentPage: propCurrentPage,
paginate
}) => {
const totalPages = Math.ceil(totalQuizzes / quizzesPerPage);
const scrollRef = useRef(null);
const [showLeftArrow, setShowLeftArrow] = useState(false);
const [showRightArrow, setShowRightArrow] = useState(true);
const [showManualInput, setShowManualInput] = useState(false);
const [manualPageInput, setManualPageInput] = useState("");
const inputRef = useRef(null);
// Initialize current page from sessionStorage or props
const initialPage = () => {
const savedPage = sessionStorage.getItem("quizListPage");
// return savedPage ? Math.min(parseInt(savedPage, 10), totalPages) : propCurrentPage;
return savedPage ? savedPage : propCurrentPage;
};
const [currentPage, setCurrentPage] = useState(initialPage);
const handlePageChange = (number) => {
const validatedNumber = Math.max(1, Math.min(number, totalPages));
setCurrentPage(validatedNumber);
paginate(validatedNumber);
sessionStorage.setItem("quizListPage", validatedNumber);
};
const handleDoubleClick = () => {
setShowManualInput(true);
setManualPageInput(currentPage.toString());
};
const handleManualPageSubmit = (e) => {
e.preventDefault();
const pageNumber = parseInt(manualPageInput, 10);
if (!isNaN(pageNumber) && pageNumber >= 1 && pageNumber <= totalPages) {
handlePageChange(pageNumber);
}
setShowManualInput(false);
};
// Check scroll position to show/hide arrows
const checkScrollPosition = () => {
if (scrollRef.current) {
const { scrollLeft, scrollWidth, clientWidth } = scrollRef.current;
setShowLeftArrow(scrollLeft > 0);
setShowRightArrow(scrollLeft < scrollWidth - clientWidth);
}
};
// Scroll handler functions
const scrollLeft = () => {
if (scrollRef.current) {
scrollRef.current.scrollBy({
left: -100,
behavior: 'smooth'
});
}
};
const scrollRight = () => {
if (scrollRef.current) {
scrollRef.current.scrollBy({
left: 100,
behavior: 'smooth'
});
}
};
// Wheel scrolling handler
useEffect(() => {
const container = scrollRef.current;
if (!container) return;
const handleWheel = (e) => {
if (Math.abs(e.deltaX) < Math.abs(e.deltaY)) {
e.preventDefault();
container.scrollLeft += e.deltaY * 2;
}
};
container.addEventListener('wheel', handleWheel, { passive: false });
container.addEventListener('scroll', checkScrollPosition);
return () => {
container.removeEventListener('wheel', handleWheel);
container.removeEventListener('scroll', checkScrollPosition);
};
}, []);
// Center current page button
useEffect(() => {
const container = scrollRef.current;
const centerButton = container?.querySelector('#center');
if (centerButton && container) {
const containerWidth = container.clientWidth;
const buttonWidth = centerButton.clientWidth;
const buttonOffsetLeft = centerButton.offsetLeft;
const scrollPosition = buttonOffsetLeft - (containerWidth / 2) + (buttonWidth / 2);
container.scrollLeft = scrollPosition;
}
checkScrollPosition();
// Clear session storage when total pages changes
const savedPage = sessionStorage.getItem("quizListPage");
if (savedPage && parseInt(savedPage, 10) > totalPages) {
sessionStorage.removeItem("quizListPage");
setCurrentPage(1); // Reset to first page if saved page is invalid
paginate(1);
}
}, [currentPage, totalPages]);
// Sync currentPage with prop changes
useEffect(() => {
setCurrentPage(propCurrentPage);
}, [propCurrentPage]);
// Focus input when shown
useEffect(() => {
if (showManualInput && inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
}
}, [showManualInput]);
return (
<nav className="flex justify-center mt-4 relative w-full">
<div className="relative w-[200px] group">
{/* Left arrow */}
{showLeftArrow && (
<button
onClick={scrollLeft}
className="absolute left-[-50px] top-1/2 -translate-y-1/2 z-20
w-8 h-8 flex items-center justify-center
bg-[#979393] dark:bg-[#2e2d2d] rounded-full shadow-md
hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
>
<ChevronLeft className="text-gray-700 dark:text-gray-300" />
</button>
)}
{/* Right arrow */}
{showRightArrow && (
<button
onClick={scrollRight}
className="absolute right-[-50px] top-1/2 -translate-y-1/2 z-20
w-8 h-8 flex items-center justify-center
bg-[#979393] dark:bg-[#2e2d2d] rounded-full shadow-md
hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors"
>
<ChevronRight className="text-gray-700 dark:text-gray-300" />
</button>
)}
{/* Gradient overlays */}
<div className="absolute left-0 top-0 bottom-0 w-8 z-10 pointer-events-none
bg-gradient-to-r from-white to-transparent
dark:from-[#0f0f0f] dark:to-transparent" />
<div className="absolute right-0 top-0 bottom-0 w-8 z-10 pointer-events-none
bg-gradient-to-l from-white to-transparent
dark:from-[#0f0f0f] dark:to-transparent" />
{/* Scroll container */}
<ul
ref={scrollRef}
className="flex items-center gap-2 overflow-x-auto scrollbar-hide p-2 w-full"
style={{
scrollBehavior: 'smooth',
WebkitOverflowScrolling: 'touch',
overscrollBehavior: 'contain'
}}
>
{Array.from({ length: totalPages }, (_, i) => i + 1).map((number) => (
<li key={number} className="shrink-0">
{showManualInput && number === currentPage ? (
<form onSubmit={handleManualPageSubmit}>
<input
ref={inputRef}
type="number"
min="1"
max={totalPages}
value={manualPageInput}
onChange={(e) => setManualPageInput(e.target.value)}
onBlur={() => setShowManualInput(false)}
className="w-10 h-10 text-center rounded-full font-medium shadow-md
bg-yellow-600 text-white outline-none"
/>
</form>
) : (
<button
id={number === currentPage ? "center" : undefined}
data-page={number}
onClick={() => handlePageChange(number)}
onDoubleClick={handleDoubleClick}
className={`
w-10 h-10 flex items-center justify-center
rounded-full font-medium transition-all
duration-300 shadow-md
${number === currentPage
? "bg-yellow-600 text-white scale-110"
: "bg-red-400 text-white hover:bg-red-500"
}
`}
>
<p className="cursor-pointer">{number}</p>
</button>
)}
</li>
))}
</ul>
</div>
</nav>
);
};
export default Pagination;