Skip to content

Commit dc4c1df

Browse files
authored
Elevate Pescamar to a premium operational design system
Aplica el sistema visual oceánico definido en DESIGN.md, mejora jerarquía, dark/light, navegación, formularios, tablas, estados y responsive sin alterar la lógica operacional.
1 parent d4697ef commit dc4c1df

4 files changed

Lines changed: 111 additions & 6 deletions

File tree

‎src/components/AppShell.tsx‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Activity,Blocks,Boxes,CheckCheck,ChevronDown,Database,Factory,FileSpreadsheet,Landmark,LayoutDashboard,LogOut,Menu,Moon,ReceiptText,Settings2,Sun,X} from "lucide-react";
1+
import {Activity,Blocks,Boxes,CheckCheck,Database,Factory,FileSpreadsheet,Landmark,LayoutDashboard,LogOut,Menu,Moon,ReceiptText,Settings2,Sun,X} from "lucide-react";
22
import {NavLink,useLocation} from "react-router-dom";
33
import {useEffect,useState,type ReactNode} from "react";
44
import {canAccessPath,canCreateReception} from "../access";
@@ -19,7 +19,7 @@ const secondaryNavigation=[
1919
{to:"/importaciones",label:"Importaciones",icon:FileSpreadsheet},
2020
{to:"/operadores",label:"Operadores",icon:Settings2},
2121
];
22-
const roleLabels={admin:"Administrador",operations:"Operaciones",finance:"Finanzas",quality:"Calidad",viewer:"Lectura"} as const;
22+
const roleLabels={admin:"Administrador",operations:"Gerente Operaciones",finance:"Finanzas",quality:"Calidad",viewer:"Lectura"} as const;
2323

2424
export function AppShell({children,onNewReception}:{children:ReactNode;onNewReception:()=>void}){
2525
const [mobileOpen,setMobileOpen]=useState(false);
@@ -33,21 +33,23 @@ export function AppShell({children,onNewReception}:{children:ReactNode;onNewRece
3333
const visiblePrimary=operator?navigation.map(group=>({...group,items:group.items.filter(item=>canAccessPath(operator.role,item.to))})):[];
3434
const visibleSecondary=operator?secondaryNavigation.filter(item=>canAccessPath(operator.role,item.to)):[];
3535
const mayCreate=operator?canCreateReception(operator.role):false;
36+
const platformLabel=!status?"Verificando":status.ok?"Plataforma activa":"Revisar plataforma";
37+
const databaseLabel=!status?"Sincronizando estado":status.persistence.database?"Neon conectado":"Base pendiente";
3638
return <div className="app-shell">
3739
<aside className={`sidebar ${mobileOpen?"is-open":""}`}>
3840
<div className="brand"><span className="pescamar-symbol" aria-hidden="true"><svg viewBox="0 0 52 34" role="img"><path d="M4 17c8-8 17-12 27-10 5 1 10 4 15 10-5 6-10 9-15 10-10 2-19-2-27-10Z"/><path d="M36 11c4-4 8-6 12-6-1 5-1 8 0 12-4 0-8-2-12-6Z"/><circle cx="14" cy="15" r="1.35"/><path className="brand-wave" d="M3 27c8-3 15-3 22 0s15 3 24-1"/></svg></span><div className="brand-copy"><strong className="brand-name">Pescamar</strong><small className="brand-product">Control operacional</small></div><button className="icon-btn mobile-close" onClick={()=>setMobileOpen(false)} aria-label="Cerrar menú"><X size={18}/></button></div>
39-
<div className="plant-chip"><span className="live-dot pending"/><div><b>Red Pescamar</b><small>{operator?.role==="admin"?"Acceso a seis plantas":operator?.plantIds.length?`${operator.plantIds.length} planta${operator.plantIds.length===1?"":"s"} autorizada${operator.plantIds.length===1?"":"s"}`:"Sin plantas asignadas"}</small></div><ChevronDown size={15}/></div>
41+
<div className="plant-chip"><span className="live-dot pending"/><div><b>Red Pescamar</b><small>{operator?.role==="admin"?"Cobertura corporativa · 6 plantas":operator?.plantIds.length?`${operator.plantIds.length} planta${operator.plantIds.length===1?"":"s"} bajo tu alcance`:"Sin plantas asignadas"}</small></div></div>
4042
<nav className="side-nav grouped-nav" aria-label="Navegación principal">
4143
{visiblePrimary.map(group=><section key={group.label}><small>{group.label}</small>{group.items.map(({to,label,icon:Icon})=><NavLink key={to} to={to} end={to==="/"} onClick={()=>setMobileOpen(false)}><Icon size={18}/><span>{label}</span></NavLink>)}</section>)}
42-
{visibleSecondary.length?<details className="nav-more"><summary><Blocks size={18}/><span>Más módulos</span><ChevronDown size={14}/></summary><div>{visibleSecondary.map(({to,label,icon:Icon})=><NavLink key={to} to={to} onClick={()=>setMobileOpen(false)}><Icon size={18}/><span>{label}</span></NavLink>)}</div></details>:null}
44+
{visibleSecondary.length?<details className="nav-more"><summary><Blocks size={18}/><span>Gestión y datos</span></summary><div>{visibleSecondary.map(({to,label,icon:Icon})=><NavLink key={to} to={to} onClick={()=>setMobileOpen(false)}><Icon size={18}/><span>{label}</span></NavLink>)}</div></details>:null}
4345
</nav>
4446
<div className="sidebar-spacer"/>
45-
<div className="pilot-card"><span className="overline">Control por excepción</span><b>Operación simplificada</b><p>El sistema eleva solamente decisiones que necesitan criterio humano.</p><span className="n3-signature">N3URALIA / INTELLIGENCE SYSTEM</span></div>
47+
<div className="pilot-card"><span className="overline">Control por excepción</span><b>Solo lo que requiere criterio</b><p>La operación normal permanece silenciosa. Aquí aparecen las decisiones que necesitan atención.</p><span className="n3-signature">PESCAMAR · CONTROL OPERACIONAL</span></div>
4648
{operator&&canAccessPath(operator.role,"/modulos")?<NavLink className="settings-link" to="/modulos"><Settings2 size={18}/><span>Configuración modular</span></NavLink>:null}
4749
</aside>
4850
<div className="workspace"><header className="topbar"><button className="icon-btn menu-btn" onClick={()=>setMobileOpen(true)} aria-label="Abrir menú"><Menu size={20}/></button><div className="topbar-context"><span>Centro de control</span><b>{context}</b></div><div className="topbar-actions">
4951
<button className="theme-toggle" type="button" onClick={()=>setTheme(theme==="dark"?"light":"dark")} aria-label={`Activar modo ${theme==="dark"?"claro":"oscuro"}`} aria-pressed={theme==="dark"} title={`Modo ${theme==="dark"?"claro":"oscuro"}`}>{theme==="dark"?<Sun size={15}/>:<Moon size={15}/>}<span>{theme==="dark"?"Claro":"Oscuro"}</span></button>
50-
{operator&&canAccessPath(operator.role,"/modulos")?<NavLink className="system-state" to="/modulos"><Activity size={15}/><span><b>{status?.ok?"Plataforma activa":"Conexión pendiente"}</b><small>{status?.persistence.database?"Base conectada":"PostgreSQL pendiente"}</small></span></NavLink>:<div className="system-state"><Activity size={15}/><span><b>{status?.ok?"Plataforma activa":"Conexión pendiente"}</b><small>{status?.persistence.database?"Base conectada":"PostgreSQL pendiente"}</small></span></div>}
52+
{operator&&canAccessPath(operator.role,"/modulos")?<NavLink className="system-state" to="/modulos"><Activity size={15}/><span><b>{platformLabel}</b><small>{databaseLabel}</small></span></NavLink>:<div className="system-state"><Activity size={15}/><span><b>{platformLabel}</b><small>{databaseLabel}</small></span></div>}
5153
<button className="operator-state operator-session-button" type="button" onClick={()=>void logout()} title="Cerrar sesión"><span>{initials}</span><div><b>{operator?.fullName??"Sesión operativa"}</b><small>{operator?roleLabels[operator.role]:"Operador"}</small></div><LogOut size={14}/></button>
5254
</div></header><main className="main-content">{children}</main></div>
5355
{mayCreate?<button className="floating-action" onClick={onNewReception}>+ Nueva recepción</button>:null}

‎src/login-premium.css‎

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/main.tsx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ import { BrowserRouter } from 'react-router-dom'
44
import App from './App'
55
import { AuthProvider } from './auth'
66
import './styles.css'
7+
import './premium.css'
8+
import './login-premium.css'
79
createRoot(document.getElementById('root')!).render(<StrictMode><AuthProvider><BrowserRouter><App /></BrowserRouter></AuthProvider></StrictMode>)

0 commit comments

Comments
 (0)