leumas-private-shared
Version:
Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains
104 lines (93 loc) • 4.21 kB
JSX
// SpeedDial.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { FaPlus, FaChevronUp, FaChevronDown, FaHome, FaTachometerAlt, FaExternalLinkAlt, FaBook } from 'react-icons/fa';
import "./speeddial.css";
// Map icon names to actual icon components
const iconMap = {
FaHome: FaHome,
FaTachometerAlt: FaTachometerAlt,
FaExternalLinkAlt: FaExternalLinkAlt,
FaBook: FaBook
};
const SpeedDial = () => {
const [open, setOpen] = useState(false);
const [currentPage, setCurrentPage] = useState(0);
const [links, setLinks] = useState([]);
const itemsPerPage = 4;
useEffect(() => {
const fetchLinks = async () => {
try {
const response = await axios.get('http://localhost:3002/configs/speed-dial');
setLinks(response.data);
} catch (error) {
console.error('Error fetching links:', error);
}
};
fetchLinks();
}, []);
const toggleOpen = () => {
setOpen(!open);
};
const nextPage = () => {
if ((currentPage + 1) * itemsPerPage < links.length) {
setCurrentPage(currentPage + 1);
}
};
const prevPage = () => {
if (currentPage > 0) {
setCurrentPage(currentPage - 1);
}
};
const startIndex = currentPage * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const visibleLinks = links.slice(startIndex, endIndex);
return (
<div className="fixed bottom-4 right-4 group">
{open && (
<div className="flex flex-col items-center mb-2 space-y-1 overflow-auto" style={{ maxHeight: '150px' }}>
{visibleLinks.map((link, index) => (
<button
key={index}
type="button"
className="relative w-24 h-8 flex items-center justify-start px-2 text-gray-500 bg-white rounded-md border border-gray-200 hover:text-gray-900 dark:border-gray-600 shadow-sm dark:hover:text-white dark:text-gray-400 hover:bg-gray-50 dark:bg-gray-700 dark:hover:bg-gray-600 focus:ring-2 focus:ring-gray-300 focus:outline-none dark:focus:ring-gray-400"
onClick={() => window.location.href = link.link}
>
{React.createElement(iconMap[link.icon], { className: 'w-4 h-4 mr-1' })}
<span className="text-[8px] font-medium">
{link.title}
</span>
</button>
))}
<div className="flex justify-between w-full mt-1">
<button
type="button"
className="w-7 h-7 flex items-center justify-center text-gray-500 bg-white rounded-md border border-gray-200 hover:text-gray-900 dark:border-gray-600 shadow-sm dark:hover:text-white dark:text-gray-400 hover:bg-gray-50 dark:bg-gray-700 dark:hover:bg-gray-600 focus:ring-2 focus:ring-gray-300 focus:outline-none dark:focus:ring-gray-400"
onClick={prevPage}
disabled={currentPage === 0}
>
<FaChevronUp className="w-4 h-4" />
</button>
<button
type="button"
className="w-7 h-7 flex items-center justify-center text-gray-500 bg-white rounded-md border border-gray-200 hover:text-gray-900 dark:border-gray-600 shadow-sm dark:hover:text-white dark:text-gray-400 hover:bg-gray-50 dark:bg-gray-700 dark:hover:bg-gray-600 focus:ring-2 focus:ring-gray-300 focus:outline-none dark:focus:ring-gray-400"
onClick={nextPage}
disabled={endIndex >= links.length}
>
<FaChevronDown className="w-4 h-4" />
</button>
</div>
</div>
)}
<button
type="button"
onClick={toggleOpen}
className="flex items-center justify-center text-white bg-blue-700 rounded-md w-7 h-7 hover:bg-blue-800 dark:bg-blue-600 dark:hover:bg-blue-700 focus:ring-2 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800"
>
<FaPlus className={`w-4 h-4 transition-transform ${open ? 'rotate-45' : ''}`} />
<span className="sr-only">Open actions menu</span>
</button>
</div>
);
};
export default SpeedDial;