Files
dare/client/App.js
2026-05-06 18:16:28 +02:00

286 lines
7.3 KiB
JavaScript

// App.js
import { $, watch, h, when } from "./sigpro.js";
import {
Navbar,
Drawer,
DrawerToggle,
DrawerContent,
DrawerSide,
DrawerOverlay,
Menu,
Tabs,
Swap,
SwapToggle,
SwapOn,
SwapOff,
Icon,
Avatar,
Dropdown,
DropdownButton,
DropdownContent,
Modal,
Fieldset,
Input,
Button
} from "./sigpro-ui.js";
import './sigpro-ui.css';
export const App = () => {
// Tema oscuro/claro
const isDark = $(localStorage.getItem("theme") === "dark"
|| (!localStorage.getItem("theme") && window.matchMedia("(prefers-color-scheme: dark)").matches));
// Sincronizar el tema con el atributo data-theme del HTML
watch(isDark, (dark) => {
const theme = dark ? "dark" : "light";
document.documentElement.setAttribute("data-theme", theme);
localStorage.setItem("theme", theme);
});
// Activar tema inicial
document.documentElement.setAttribute("data-theme", isDark() ? "dark" : "light");
// Estado de login persistente
const logged = $(false, "logged");
// Estado para buscador
const searchQuery = $("");
// Estado para modal de login
const showLoginModal = $(false);
const loginForm = {
username: $(""),
password: $("")
};
// Pestañas: la primera (Escritorio) no es cerrable
const tabs = $([
{
label: "Escritorio",
content: () => `¡Bienvenido al escritorio!`,
closable: false
}
]);
const activeTab = $(0);
const openDrawer = $(false);
// Elementos del menú en el drawer
const menuItems = [
{
label: "Clientes",
children: [
{ label: "Buscar Cliente", onclick: () => openTab("Clientes") },
]
},
{
label: "Recibos",
children: [
{ label: "Buscar Recibo" },
{ label: "Pendientes" },
{ label: "Extornos" },
],
},
{
label: "Polizas",
children: [
{ label: "Buscar Póliza", onclick: () => openTab("Polizas") },
{ label: "Nueva producción", onclick: () => openTab("Polizas") },
{ label: "Anulaciones", onclick: () => openTab("Polizas") },
{ label: "Renovación Cartera", onclick: () => openTab("Polizas") }
]
},
{
label: "Comercial",
children: [
{ label: "Oportunidades" },
],
},
{
label: "Siniestros",
children: [
{ label: "Nuevo Siniestro" },
{ label: "Buscar Siniestro" },
]
},
{
label: "Soporte",
children: [
{ label: "Tickets" },
{ label: "Reportes" },
]
}
];
// Referencia al contenedor de pestañas para manejar el foco
let tabsContainerRef = null;
let drawerToggleRef = null;
// Abre o crea una pestaña, cierra el drawer
const openTab = (label) => {
const currentTabs = tabs();
if (currentTabs.length >= 15) return;
const newTab = {
label,
content: () => `¡Bienvenido al escritorio!`,
closable: true
};
tabs([...currentTabs, newTab]);
activeTab(tabs().length - 1);
closeDrawer();
};
const closeDrawer = () => {
openDrawer(false);
if (drawerToggleRef) drawerToggleRef.checked = false;
};
// Manejo del login
const handleLogin = () => {
logged(true);
showLoginModal(false);
loginForm.username("");
loginForm.password("");
};
const handleLogout = () => {
logged(false);
};
return [
Drawer({}, [
// Control oculto del drawer
DrawerToggle({
id: "app-drawer",
ref: (el) => drawerToggleRef = el,
checked: openDrawer,
onchange: (e) => openDrawer(e.target.checked)
}),
// Contenido principal
DrawerContent({}, [
Navbar({ class: "bg-base-100 shadow-lg align-center" }, [
// Botón hamburguesa
div({ class: "flex-none" }, [
label({ for: "app-drawer", class: "btn btn-ghost btn-square" }, [
Icon({}, "icon-[lucide--menu]")
])
]),
// Buscador
div({ class: "flex-1 max-w-md mx-4" }, [
Input({
type: "search",
placeholder: "Buscar...",
value: searchQuery,
left: span({ class: "icon-[lucide--search]" }),
oninput: (e) => console.log(e.target.value)
})
]),
// Espaciador central
div({ class: "flex-1" }, []),
// Swap para tema claro/oscuro
Swap({ class: "text-xl" }, [
SwapToggle({ value: isDark, class: "swap-rotate" }),
SwapOn({}, span({ class: "icon-[lucide--moon]" })),
SwapOff({}, span({ class: "icon-[lucide--sun]" })),
]),
// Avatar con dropdown o botón de login
when(logged,
() => Dropdown({ class: "flex-none ml-2 dropdown-bottom dropdown-end" }, [
DropdownButton({ class: "btn-circle btn btn-ghost", tabindex: "0", role: "button" }, [
div({ class: "w-10 rounded-full flex items-center justify-center" }, [
Icon({}, "icon-[lucide--user] text-xl")
])
]),
DropdownContent(
{ class: "menu bg-base-100 rounded-box w-52 p-2 shadow" },
[
Menu({
class: "bg-base-100 max-w-xs w-full",
items: [
{ label: "Mis mensajes", onclick: () => hide() },
{ label: "Delete", onclick: () => hide() },
{ label: "Cerrar Sesión", onclick: handleLogout },
],
}),
],
),
]),
() => Button({
class: "flex-none ml-2 btn btn-ghost btn-circle relative",
onclick: () => showLoginModal(true)
}, [
Icon({}, "icon-[lucide--user] text-xl"),
])
)
]),
// Área principal con las pestañas
div({
class: "p-4",
ref: (el) => tabsContainerRef = el
}, [
Tabs({
class: 'tabs-box',
items: tabs,
activeIndex: activeTab
})
])
]),
// Lateral del drawer
DrawerSide({ class: "z-50" }, [
DrawerOverlay({ for: "app-drawer" }),
div({
class: "menu bg-base-200 text-base-content min-h-full w-80 p-4"
}, [
h2({ class: "text-lg font-bold mb-4" }, ["Menú"]),
Menu({ items: menuItems, class: "bg-base-200 max-w-xs w-full" })
])
])
]),
// Modal de login
Modal({
open: showLoginModal,
actions: [
Button({
class: "btn btn-ghost",
onclick: () => showLoginModal(false)
}, "Cancelar"),
Button({
class: "btn btn-primary",
onclick: handleLogin
}, "Entrar")
]
}, [
Fieldset({ label: "Iniciar sesión", class: "bg-base-200 border-base-300 rounded-box border gap-3 p-4", }, [
Input({
class: "w-full",
type: "text",
label: "Usuario",
float: true,
placeholder: "Nombre de usuario",
value: loginForm.username
})
,
Input({
class: "w-full",
type: "password",
label: "Contraseña",
float: true,
placeholder: "Contraseña",
value: loginForm.password
})
])
])
];
};