refactor: reorganización de estructura, pages y components
This commit is contained in:
184
src/components/layout/Sidebar.tsx
Normal file
184
src/components/layout/Sidebar.tsx
Normal file
@@ -0,0 +1,184 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Home,
|
||||
Settings,
|
||||
WaterDrop,
|
||||
ExpandMore,
|
||||
ExpandLess,
|
||||
Menu,
|
||||
People,
|
||||
Key
|
||||
} from "@mui/icons-material";
|
||||
|
||||
interface SidebarProps {
|
||||
setPage: (page: string) => void;
|
||||
}
|
||||
|
||||
export default function Sidebar({ setPage }: SidebarProps) {
|
||||
const [systemOpen, setSystemOpen] = useState(true);
|
||||
const [waterOpen, setWaterOpen] = useState(true);
|
||||
const [usersOpen, setUsersOpen] = useState(true); // Nuevo
|
||||
const [pinned, setPinned] = useState(false);
|
||||
const [hovered, setHovered] = useState(false);
|
||||
|
||||
const isExpanded = pinned || hovered;
|
||||
|
||||
return (
|
||||
<aside
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
className={`
|
||||
h-full bg-[#1f2a48] border-r border-white/10
|
||||
transition-all duration-300 flex flex-col overflow-hidden
|
||||
${isExpanded ? "w-72" : "w-16"}
|
||||
`}
|
||||
>
|
||||
{/* HEADER */}
|
||||
<div className="border-b border-white/10 px-4 py-3 flex items-center gap-3">
|
||||
<button
|
||||
onClick={() => setPinned(!pinned)}
|
||||
className="text-white opacity-90 hover:opacity-100"
|
||||
>
|
||||
<Menu />
|
||||
</button>
|
||||
{isExpanded && (
|
||||
<span className="text-lg font-bold text-white whitespace-nowrap">
|
||||
Water System
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* MENU */}
|
||||
<div className="flex-1 py-4 px-2 overflow-y-auto">
|
||||
<ul className="space-y-1 text-white text-sm">
|
||||
|
||||
{/* DASHBOARD */}
|
||||
<li>
|
||||
<button
|
||||
onClick={() => setPage("home")}
|
||||
className="flex items-center w-full px-2 py-2 rounded-md hover:bg-white/10 font-bold"
|
||||
>
|
||||
<Home className="w-5 h-5 shrink-0" />
|
||||
{isExpanded && <span className="ml-3">Dashboard</span>}
|
||||
</button>
|
||||
</li>
|
||||
|
||||
{/* PROJECT MANAGEMENT */}
|
||||
<li>
|
||||
<button
|
||||
onClick={() => isExpanded && setSystemOpen(!systemOpen)}
|
||||
className="flex items-center w-full px-2 py-2 rounded-md hover:bg-white/10 font-bold"
|
||||
>
|
||||
<Settings className="w-5 h-5 shrink-0" />
|
||||
{isExpanded && (
|
||||
<>
|
||||
<span className="ml-3 flex-1 text-left">Project Management</span>
|
||||
{systemOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{isExpanded && systemOpen && (
|
||||
<ul className="mt-1 space-y-1 text-xs">
|
||||
<li>
|
||||
<button
|
||||
onClick={() => setPage("concentrators")}
|
||||
className="pl-10 w-full text-left px-2 py-1.5 rounded-md hover:bg-white/10"
|
||||
>
|
||||
Concentradores
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
onClick={() => setPage("meters")}
|
||||
className="pl-10 w-full text-left px-2 py-1.5 rounded-md hover:bg-white/10"
|
||||
>
|
||||
Medidores
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
|
||||
{/* WATER METER SYSTEM
|
||||
<li>
|
||||
<button
|
||||
onClick={() => isExpanded && setWaterOpen(!waterOpen)}
|
||||
className="flex items-center w-full px-2 py-2 rounded-md hover:bg-white/10 font-bold"
|
||||
>
|
||||
<WaterDrop className="w-5 h-5 shrink-0" />
|
||||
{isExpanded && (
|
||||
<>
|
||||
<span className="ml-3 flex-1 text-left">Water Meter System Management</span>
|
||||
{waterOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{isExpanded && waterOpen && (
|
||||
<ul className="mt-1 space-y-1 text-xs">
|
||||
{[
|
||||
["water-install", "Water Meter Installation"],
|
||||
["device-install", "Device Installation"],
|
||||
["meter-management", "Meter Management"],
|
||||
["device-management", "Device Management"],
|
||||
["data-monitoring", "Data Monitoring"],
|
||||
["data-query", "Data Query"],
|
||||
].map(([key, label]) => (
|
||||
<li key={key}>
|
||||
<button
|
||||
onClick={() => setPage(key)}
|
||||
className="pl-10 w-full text-left px-2 py-1.5 rounded-md hover:bg-white/10"
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
*}
|
||||
|
||||
{/* SYSTEM USERS */}
|
||||
<li>
|
||||
<button
|
||||
onClick={() => isExpanded && setUsersOpen(!usersOpen)}
|
||||
className="flex items-center w-full px-2 py-2 rounded-md hover:bg-white/10 font-bold"
|
||||
>
|
||||
<People className="w-5 h-5 shrink-0" />
|
||||
{isExpanded && (
|
||||
<>
|
||||
<span className="ml-3 flex-1 text-left">Users Management</span>
|
||||
{usersOpen ? <ExpandLess /> : <ExpandMore />}
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{isExpanded && usersOpen && (
|
||||
<ul className="mt-1 space-y-1 text-xs">
|
||||
<li>
|
||||
<button
|
||||
onClick={() => setPage("users")}
|
||||
className="pl-10 w-full text-left px-2 py-1.5 rounded-md hover:bg-white/10"
|
||||
>
|
||||
Users
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button
|
||||
onClick={() => setPage("roles")}
|
||||
className="pl-10 w-full text-left px-2 py-1.5 rounded-md hover:bg-white/10"
|
||||
>
|
||||
Roles
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
)}
|
||||
</li>
|
||||
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
61
src/components/layout/TopMenu.tsx
Normal file
61
src/components/layout/TopMenu.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import React from "react";
|
||||
import { Bell, User, Settings } from "lucide-react";
|
||||
|
||||
interface TopMenuProps {
|
||||
page: string;
|
||||
subPage: string;
|
||||
setSubPage: (subPage: string) => void;
|
||||
}
|
||||
|
||||
const TopMenu: React.FC<TopMenuProps> = ({ page, subPage, setSubPage }) => {
|
||||
return (
|
||||
<header
|
||||
className="h-14 shrink-0 flex items-center justify-between px-4 text-white"
|
||||
style={{
|
||||
background:
|
||||
"linear-gradient(135deg, #4c5f9e, #2a355d, #566bb8, #3d4e87)",
|
||||
}}
|
||||
>
|
||||
{/* IZQUIERDA */}
|
||||
<div className="flex items-center gap-2 text-sm font-medium opacity-90">
|
||||
{page !== "home" && (
|
||||
<>
|
||||
<span className="capitalize">{page}</span>
|
||||
{subPage !== "default" && (
|
||||
<>
|
||||
<span className="opacity-60">/</span>
|
||||
<span className="capitalize">{subPage}</span>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* DERECHA */}
|
||||
<div className="flex items-center gap-3">
|
||||
<button
|
||||
aria-label="Notificaciones"
|
||||
className="p-2 rounded-full hover:bg-white/10 transition"
|
||||
>
|
||||
<Bell size={20} />
|
||||
</button>
|
||||
|
||||
<button
|
||||
aria-label="Configuración"
|
||||
className="p-2 rounded-full hover:bg-white/10 transition"
|
||||
>
|
||||
<Settings size={20} />
|
||||
</button>
|
||||
|
||||
<div
|
||||
className="w-9 h-9 rounded-full bg-white/15 flex items-center justify-center cursor-pointer hover:bg-white/25 transition"
|
||||
title="Perfil"
|
||||
>
|
||||
<User size={20} />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopMenu;
|
||||
0
src/components/layout/common/ConfirmModal.tsx
Normal file
0
src/components/layout/common/ConfirmModal.tsx
Normal file
Reference in New Issue
Block a user