The admin panel (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/akibanks/tienda_musica_web/llms.txt
Use this file to discover all available pages before exploring further.
admin.html + admin.js) provides a dashboard for managing users and sales. Access is restricted to users with esAdmin === 'true' or esDemo === 'true' in localStorage. Demo users see all data but cannot make changes — all action controls are rendered in a disabled state and a read-only banner is inserted below the header.
Access Control
On page load,admin.js reads vv_token, esAdmin, and esDemo from localStorage. If the token is missing, or if neither esAdmin nor esDemo is true, an error toast reading “Acceso denegado.” is shown and the user is redirected to index.html after 1.5 seconds.
The admin panel enforces access on the frontend as a UX guard. The backend independently validates the JWT for every admin endpoint (
GET /admin/usuarios, GET /admin/ventas, PUT, DELETE, etc.), so removing the client-side check would not grant actual access to data.Promise.all([cargarUsuarios(), cargarVentas()]). Statistics are computed from those responses immediately after.
Statistics Dashboard
Four stat cards are displayed at the top of the panel. All values are derived from the same two requests made at initialization — no additional API calls are needed for the stats.Total Users
Count of all entries returned by
GET /admin/usuariosTotal Sales
Count of all entries returned by
GET /admin/ventasRevenue
Sum of
total across all sales recordsPending Sales
Count of sales where
estado === 'pendiente'cargarStats(), which re-fetches both endpoints and recomputes all four values.
User Management
The Usuarios tab shows a table of all registered accounts. Data is fetched once and filtered client-side. Table columns: ID · Name · Email · Role · Created At · ActionsSearch
filtrarUsuarios(q) filters the in-memory _usuarios array by name or email (case-insensitive) and re-renders the table without a network request.
Role Management
PUT /admin/usuarios/{id}/rol with body { "rol": "nuevo_rol" }. The current admin cannot remove their own admin role — this is enforced by decoding the JWT payload (atob(token.split('.')[1])) to compare the current user’s ID with the target row’s ID. If they match and nuevoRol !== 'admin', the operation is blocked and the table is re-rendered to revert the select visually.
Available roles:
| Role | Description |
|---|---|
cliente | Standard customer account |
vendedor | Seller account |
admin | Full admin panel access with write permissions |
User Deletion
confirmarEliminarUsuario(id, nombre) replaces the action cell in the target table row with an inline confirmation prompt — “¿Eliminar a ""?” — and two buttons: Confirmar and Cancelar. Confirming calls eliminarUsuario(id, nombre), which sends DELETE /admin/usuarios/{id}. On success, the user is removed from the local _usuarios array, the table is re-rendered, and statistics are refreshed. Cancelling re-renders the table with the original action buttons.
Sales Management
The Ventas tab shows all orders placed through the store. Data is fetched in parallel with users on page load. Table columns: ID · User · Total · Status · Date · ActionsSearch
filtrarVentas(q) filters the in-memory _ventas array by sale ID or customer name (case-insensitive) and re-renders the table client-side.
Status Updates
PUT /admin/ventas/{id}/estado with body { "estado": "nuevo_estado" }. On success, the local _ventas entry is updated and statistics are refreshed. Possible statuses:
| Status | Meaning |
|---|---|
pendiente | Order placed, not yet processed |
pagada | Payment confirmed |
enviada | Order shipped |
entregada | Order delivered to customer |
cancelada | Order cancelled |
Sale Detail Modal
Clicking “Ver detalle” on any row callsverDetalleVenta(id), which fetches GET /admin/ventas/{id} for the full order record. The detail modal displays:
- Order header — sale ID, customer name, and current status badge
- Item list — each line shows the album title, quantity (
×N), and line subtotal - Order total — highlighted in amber
- Shipping address — recipient name, full address with interior number when present, and delivery references
Demo / Read-Only Mode
WhenesDemo === true and esAdmin === false, the panel enters read-only mode. The _esDemo flag is set to true at initialization and controls all disabled states throughout the page. A banner is inserted immediately below the admin header:
<select> and action button across both the Users and Sales tables is rendered with the disabled attribute and reduced opacity (opacity: 0.4; cursor: not-allowed), preventing any write operations from being triggered.
Even if a demo user manually removes the
disabled attribute via browser DevTools, the backend will reject any write requests because the JWT’s role claim does not carry admin privileges.