Usuario vendedor y pestaña descargas
This commit is contained in:
@@ -1025,6 +1025,11 @@ select {
|
||||
color: #0e7490;
|
||||
}
|
||||
|
||||
.rol-vendedor {
|
||||
background: linear-gradient(135deg, rgba(252, 211, 77, 0.22) 0%, rgba(251, 146, 60, 0.22) 100%);
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
.you-badge {
|
||||
display: inline-block;
|
||||
margin-left: 6px;
|
||||
@@ -1194,6 +1199,89 @@ select {
|
||||
75% { transform: translateX(6px); }
|
||||
}
|
||||
|
||||
/* ════════════════════════════════
|
||||
SUBTABS (vista Descargas)
|
||||
════════════════════════════════ */
|
||||
.subtabs {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 6px;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-lg);
|
||||
margin-bottom: 18px;
|
||||
width: fit-content;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.subtab {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 9px 18px;
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: var(--ink-mute);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
font-size: 0.88rem;
|
||||
border-radius: calc(var(--radius-lg) - 6px);
|
||||
cursor: pointer;
|
||||
transition: color .18s ease, background .18s ease, border-color .18s ease;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.subtab:hover:not(.active) {
|
||||
color: var(--ink);
|
||||
background: rgba(255,255,255,0.45);
|
||||
}
|
||||
|
||||
.subtab.active {
|
||||
background: linear-gradient(135deg, var(--violet), var(--pink));
|
||||
color: #fff;
|
||||
border-color: var(--line-strong);
|
||||
box-shadow: 0 4px 14px -6px rgba(167, 139, 250, 0.55);
|
||||
}
|
||||
|
||||
.subtab-icon { font-size: 1rem; line-height: 1; }
|
||||
.subtab-label { line-height: 1; }
|
||||
|
||||
.subtab-panel { display: none; }
|
||||
.subtab-panel.active { display: block; }
|
||||
|
||||
.subtab-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
padding: 48px 24px;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.subtab-placeholder-icon {
|
||||
font-size: 3.2rem;
|
||||
line-height: 1;
|
||||
opacity: 0.85;
|
||||
filter: drop-shadow(0 6px 18px rgba(167, 139, 250, 0.35));
|
||||
}
|
||||
|
||||
.subtab-placeholder h3 {
|
||||
margin: 0;
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.35rem;
|
||||
font-weight: 400;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.subtab-placeholder p {
|
||||
margin: 0;
|
||||
color: var(--ink-mute);
|
||||
max-width: 460px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*, *::before, *::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
@@ -1202,6 +1290,12 @@ select {
|
||||
.mesh-blob { animation: none; }
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.subtab { padding: 8px 12px; font-size: 0.82rem; }
|
||||
.subtab-placeholder { padding: 32px 16px; }
|
||||
.subtab-placeholder-icon { font-size: 2.6rem; }
|
||||
}
|
||||
|
||||
/* ════════════════════════════════
|
||||
RESPONSIVE — topbar wrap
|
||||
════════════════════════════════ */
|
||||
|
||||
@@ -10,13 +10,15 @@
|
||||
const TABS = [
|
||||
{ id: 'productos', label: 'Productos', icon: '📦' },
|
||||
{ id: 'agotados', label: 'Agotados', icon: '🚫' },
|
||||
{ id: 'descargas', label: 'Descargas', icon: '⬇️' },
|
||||
{ id: 'categorias', label: 'Categorías', icon: '🗂️' },
|
||||
{ id: 'usuarios', label: 'Usuarios', icon: '👥' }
|
||||
];
|
||||
|
||||
const ROLES = {
|
||||
admin: 'Administrador',
|
||||
editor: 'Editor'
|
||||
admin: 'Administrador',
|
||||
editor: 'Editor',
|
||||
vendedor: 'Vendedor'
|
||||
};
|
||||
|
||||
// Iconos disponibles para categorías
|
||||
@@ -41,6 +43,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
setupLoginForm();
|
||||
setupLogout();
|
||||
setupNavigation();
|
||||
setupSubtabs();
|
||||
setupModals();
|
||||
setupPermisosToggles();
|
||||
setupCategoriasModals();
|
||||
@@ -94,19 +97,28 @@ function mostrarDashboard(user) {
|
||||
// Aplicar permisos (visibilidad de nav, subsección admin-only, etc.)
|
||||
aplicarPermisos();
|
||||
|
||||
// Reset a la vista dashboard
|
||||
cambiarVista('dashboard');
|
||||
// Determinar vista inicial
|
||||
const esAdmin = user.rol === 'admin';
|
||||
const perms = getPermisosEfectivos();
|
||||
let viewInicial;
|
||||
if (esAdmin || perms.includes('dashboard')) {
|
||||
viewInicial = 'dashboard';
|
||||
} else {
|
||||
// Primera vista visible según permisos
|
||||
viewInicial = perms[0] || 'descargas';
|
||||
}
|
||||
cambiarVista(viewInicial);
|
||||
|
||||
cargarEstadisticas();
|
||||
}
|
||||
|
||||
function cambiarVista(view) {
|
||||
// Check defensivo: si el usuario no tiene permiso para esta vista, redirige a dashboard
|
||||
if (currentUser && view !== 'dashboard') {
|
||||
// Check defensivo: si el usuario no tiene permiso para esta vista, redirige a la primera vista visible
|
||||
if (currentUser) {
|
||||
const esAdmin = currentUser.rol === 'admin';
|
||||
const permisos = currentUser.permisos || [];
|
||||
if (!esAdmin && !permisos.includes(view)) {
|
||||
view = 'dashboard';
|
||||
const perms = getPermisosEfectivos();
|
||||
if (!esAdmin && !perms.includes(view)) {
|
||||
view = perms[0] || 'descargas';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +162,10 @@ function cambiarVista(view) {
|
||||
if (view === 'agotados') {
|
||||
cargarAgotados();
|
||||
}
|
||||
|
||||
if (view === 'descargas') {
|
||||
cargarDescargas();
|
||||
}
|
||||
}
|
||||
|
||||
async function cargarEstadisticas() {
|
||||
@@ -172,27 +188,28 @@ async function cargarEstadisticas() {
|
||||
|
||||
// ════════════════════════════════
|
||||
// PERMISOS — visibilidad según rol + permisos[]
|
||||
// Vendedor: SIEMPRE ve 'descargas' (implícito) + lo que le hayan dado
|
||||
// ════════════════════════════════
|
||||
function getPermisosEfectivos() {
|
||||
if (!currentUser) return [];
|
||||
const permisos = currentUser.permisos || [];
|
||||
if (currentUser.rol === 'vendedor' && !permisos.includes('descargas')) {
|
||||
return ['descargas', ...permisos];
|
||||
}
|
||||
return permisos;
|
||||
}
|
||||
|
||||
function aplicarPermisos() {
|
||||
if (!currentUser) return;
|
||||
|
||||
const esAdmin = currentUser.rol === 'admin';
|
||||
const permisos = currentUser.permisos || [];
|
||||
const puedeGestionarUsuarios = esAdmin || permisos.includes('usuarios');
|
||||
const perms = getPermisosEfectivos();
|
||||
const puedeGestionarUsuarios = esAdmin || perms.includes('usuarios');
|
||||
|
||||
// Mostrar/ocultar cada nav-item según permisos
|
||||
document.querySelectorAll('.nav-item[data-view]').forEach(item => {
|
||||
const view = item.dataset.view;
|
||||
let visible = false;
|
||||
|
||||
if (view === 'dashboard') {
|
||||
visible = true; // Dashboard siempre visible
|
||||
} else if (esAdmin) {
|
||||
visible = true; // Admin ve todo
|
||||
} else {
|
||||
visible = permisos.includes(view); // Editor: solo sus permisos
|
||||
}
|
||||
|
||||
const visible = esAdmin || perms.includes(view);
|
||||
item.style.display = visible ? '' : 'none';
|
||||
});
|
||||
|
||||
@@ -220,6 +237,35 @@ function setupNavigation() {
|
||||
});
|
||||
}
|
||||
|
||||
// ════════════════════════════════
|
||||
// SUBTABS (dentro de la view 'descargas')
|
||||
// ════════════════════════════════
|
||||
function setupSubtabs() {
|
||||
document.querySelectorAll('.subtab').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const subtab = btn.dataset.subtab;
|
||||
// Activar solo este botón
|
||||
btn.parentElement.querySelectorAll('.subtab').forEach(b => {
|
||||
b.classList.toggle('active', b === btn);
|
||||
b.setAttribute('aria-selected', b === btn ? 'true' : 'false');
|
||||
});
|
||||
// Mostrar solo el panel correspondiente
|
||||
document.querySelectorAll('.subtab-panel').forEach(p => {
|
||||
p.classList.toggle('active', p.dataset.subtabPanel === subtab);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ════════════════════════════════
|
||||
// DESCARGAS (vista + subtabs pdf / fotos)
|
||||
// Funcionalidad TBD — placeholders por ahora
|
||||
// ════════════════════════════════
|
||||
function cargarDescargas() {
|
||||
// Placeholder. Cuando se implemente cada subpestaña, se cargan
|
||||
// los datos del backend (PDFs disponibles, lotes de fotos, etc.).
|
||||
}
|
||||
|
||||
// ════════════════════════════════
|
||||
// PERMISOS EN MODALES — render y lectura
|
||||
// ════════════════════════════════
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="admin.css?v=5">
|
||||
<link rel="stylesheet" href="admin.css?v=6">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -73,6 +73,10 @@
|
||||
<span class="nav-icon">🚫</span>
|
||||
<span class="nav-label">Agotados</span>
|
||||
</button>
|
||||
<button type="button" class="nav-item" data-view="descargas">
|
||||
<span class="nav-icon">⬇️</span>
|
||||
<span class="nav-label">Descargas</span>
|
||||
</button>
|
||||
<button type="button" class="nav-item" data-view="categorias">
|
||||
<span class="nav-icon">🗂️</span>
|
||||
<span class="nav-label">Categorías</span>
|
||||
@@ -233,6 +237,45 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- DESCARGAS VIEW (vendedores y otros usuarios con permiso) -->
|
||||
<section class="view" data-view="descargas">
|
||||
<header class="view-header">
|
||||
<h1 class="view-title">Descargas</h1>
|
||||
<p class="view-subtitle">Recursos descargables del catálogo.</p>
|
||||
</header>
|
||||
|
||||
<div class="subtabs" role="tablist" aria-label="Tipos de descarga">
|
||||
<button type="button" class="subtab active" data-subtab="pdf" role="tab" aria-selected="true">
|
||||
<span class="subtab-icon">📄</span>
|
||||
<span class="subtab-label">PDF</span>
|
||||
</button>
|
||||
<button type="button" class="subtab" data-subtab="fotos" role="tab" aria-selected="false">
|
||||
<span class="subtab-icon">🖼️</span>
|
||||
<span class="subtab-label">Fotos</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="subtab-panel active" data-subtab-panel="pdf">
|
||||
<div class="view-content-card">
|
||||
<div class="subtab-placeholder">
|
||||
<span class="subtab-placeholder-icon">📄</span>
|
||||
<h3>Descargas en PDF</h3>
|
||||
<p>Próximamente: herramientas para generar y descargar PDFs del catálogo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="subtab-panel" data-subtab-panel="fotos">
|
||||
<div class="view-content-card">
|
||||
<div class="subtab-placeholder">
|
||||
<span class="subtab-placeholder-icon">🖼️</span>
|
||||
<h3>Descargas de fotos</h3>
|
||||
<p>Próximamente: herramientas para descargar lotes de fotos del catálogo.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CATEGORÍAS VIEW -->
|
||||
<section class="view" data-view="categorias">
|
||||
<header class="view-header view-header-with-action">
|
||||
@@ -337,6 +380,7 @@
|
||||
<label for="nuevoRol">Rol</label>
|
||||
<select id="nuevoRol" required>
|
||||
<option value="editor">Editor</option>
|
||||
<option value="vendedor">Vendedor</option>
|
||||
<option value="admin">Administrador</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -382,6 +426,7 @@
|
||||
<label for="editarRol">Rol</label>
|
||||
<select id="editarRol" required>
|
||||
<option value="editor">Editor</option>
|
||||
<option value="vendedor">Vendedor</option>
|
||||
<option value="admin">Administrador</option>
|
||||
</select>
|
||||
</div>
|
||||
@@ -500,6 +545,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="admin.js?v=5"></script>
|
||||
<script src="admin.js?v=6"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user