Files
Condopay/components/Layout.tsx
frakarr 79e249b638 feat: Setup project with Vite and React
Initializes the Condopay frontend project using Vite, React, and TypeScript. Includes basic project structure, dependencies, and configuration for Tailwind CSS and React Router.
2025-12-06 18:55:48 +01:00

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>
);
};