reset
This commit is contained in:
286
client/App.js
Normal file
286
client/App.js
Normal file
@@ -0,0 +1,286 @@
|
||||
// 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
|
||||
})
|
||||
])
|
||||
|
||||
])
|
||||
];
|
||||
};
|
||||
Reference in New Issue
Block a user