Initializes the Condopay frontend project using Vite, React, and TypeScript. Includes basic project structure, dependencies, and configuration for Tailwind CSS and React Router.
103 lines
4.5 KiB
TypeScript
103 lines
4.5 KiB
TypeScript
import React from 'react';
|
|
import { NavLink, Outlet } from 'react-router-dom';
|
|
import { Users, Settings, Building, LogOut, Menu, X } from 'lucide-react';
|
|
import { CondoService } from '../services/mockDb';
|
|
|
|
export const Layout: React.FC = () => {
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
|
|
const user = CondoService.getCurrentUser();
|
|
const isAdmin = user?.role === 'admin';
|
|
|
|
const navClass = ({ isActive }: { isActive: boolean }) =>
|
|
`flex items-center gap-3 px-4 py-3 rounded-lg transition-all duration-200 ${
|
|
isActive
|
|
? 'bg-blue-600 text-white shadow-md'
|
|
: 'text-slate-600 hover:bg-slate-100'
|
|
}`;
|
|
|
|
const closeMenu = () => setIsMobileMenuOpen(false);
|
|
|
|
return (
|
|
<div className="flex h-screen bg-slate-50 overflow-hidden">
|
|
|
|
{/* Mobile Header */}
|
|
<div className="lg:hidden fixed top-0 left-0 right-0 h-16 bg-white border-b border-slate-200 flex items-center justify-between px-4 z-40 shadow-sm">
|
|
<div className="flex items-center gap-2">
|
|
<div className="bg-blue-600 p-1.5 rounded-lg">
|
|
<Building className="text-white w-5 h-5" />
|
|
</div>
|
|
<h1 className="font-bold text-lg text-slate-800">CondoPay</h1>
|
|
</div>
|
|
<button onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} className="p-2 text-slate-600 focus:outline-none">
|
|
{isMobileMenuOpen ? <X className="w-6 h-6" /> : <Menu className="w-6 h-6" />}
|
|
</button>
|
|
</div>
|
|
|
|
{/* Sidebar Overlay for Mobile */}
|
|
{isMobileMenuOpen && (
|
|
<div className="fixed inset-0 bg-black/50 z-40 lg:hidden backdrop-blur-sm" onClick={closeMenu}></div>
|
|
)}
|
|
|
|
{/* Sidebar Navigation */}
|
|
<aside className={`
|
|
fixed top-0 left-0 bottom-0 w-72 bg-white border-r border-slate-200 flex flex-col shadow-xl z-50 transform transition-transform duration-300 ease-in-out
|
|
${isMobileMenuOpen ? 'translate-x-0' : '-translate-x-full'} lg:translate-x-0 lg:static lg:shadow-none lg:z-auto
|
|
`}>
|
|
<div className="p-6 hidden lg:flex items-center gap-3 border-b border-slate-100 h-20">
|
|
<div className="bg-blue-600 p-2 rounded-lg">
|
|
<Building className="text-white w-6 h-6" />
|
|
</div>
|
|
<h1 className="font-bold text-xl text-slate-800 tracking-tight">CondoPay</h1>
|
|
</div>
|
|
|
|
{/* Mobile Header inside drawer to align content */}
|
|
<div className="lg:hidden p-4 flex items-center justify-between border-b border-slate-100 h-16">
|
|
<span className="font-bold text-slate-700 text-lg">Menu</span>
|
|
<button onClick={closeMenu} className="p-1 rounded-md hover:bg-slate-100"><X className="w-6 h-6 text-slate-500"/></button>
|
|
</div>
|
|
|
|
<nav className="flex-1 p-4 space-y-2 overflow-y-auto">
|
|
<div className="lg:hidden mb-4 px-2 pt-2">
|
|
<p className="text-xs font-semibold text-slate-400 uppercase tracking-wider">Navigazione</p>
|
|
</div>
|
|
|
|
<NavLink to="/" className={navClass} onClick={closeMenu}>
|
|
<Users className="w-5 h-5" />
|
|
<span className="font-medium">Famiglie</span>
|
|
</NavLink>
|
|
|
|
{isAdmin && (
|
|
<NavLink to="/settings" className={navClass} onClick={closeMenu}>
|
|
<Settings className="w-5 h-5" />
|
|
<span className="font-medium">Impostazioni</span>
|
|
</NavLink>
|
|
)}
|
|
</nav>
|
|
|
|
<div className="p-4 border-t border-slate-100 bg-slate-50/50">
|
|
<div className="mb-4 px-2">
|
|
<p className="text-sm font-bold text-slate-800 truncate">{user?.name || 'Utente'}</p>
|
|
<p className="text-xs text-slate-500 truncate">{user?.email}</p>
|
|
<div className="mt-1 inline-block px-2 py-0.5 rounded text-[10px] font-bold bg-slate-200 text-slate-600 uppercase">
|
|
{user?.role || 'User'}
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={() => CondoService.logout()}
|
|
className="flex items-center gap-3 px-4 py-2.5 w-full text-slate-600 hover:bg-red-50 hover:text-red-600 rounded-lg transition-colors text-sm font-medium border border-slate-200 hover:border-red-200 bg-white"
|
|
>
|
|
<LogOut className="w-4 h-4" />
|
|
Esci
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
|
|
{/* Main Content Area */}
|
|
<main className="flex-1 overflow-y-auto overflow-x-hidden bg-slate-50 pt-16 lg:pt-0 w-full">
|
|
<div className="max-w-7xl mx-auto p-4 md:p-8 w-full">
|
|
<Outlet />
|
|
</div>
|
|
</main>
|
|
</div>
|
|
);
|
|
}; |