From c5be7df5e450a3abfd2e7c86f881ee3ae0c83060 Mon Sep 17 00:00:00 2001 From: mberlin Date: Wed, 18 Mar 2026 18:00:34 -0300 Subject: [PATCH] Add sidebar menu with module actions in admin UI --- public/admin.html | 197 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 174 insertions(+), 23 deletions(-) diff --git a/public/admin.html b/public/admin.html index 3fd874f..5b39b8c 100644 --- a/public/admin.html +++ b/public/admin.html @@ -63,8 +63,8 @@

Admin Panel

Interfaz de administración (Vue 3 + JWT).

-
-
+
+

Iniciar sesión

@@ -104,32 +104,60 @@
{{ registerMessage }}
-
-
-
- Autenticado como: {{ user?.name || user?.email }} +
+
+
+
+
+
{{ user?.name || user?.email }}
+
Tenant: {{ tenantId }}
+
+ +
- -
- - - {{ status }} +
+

Módulos

+
+ +
+
-
-
-

{{ mod.name }}

-

{{ mod.key }} {{ mod.description }}

- +
+

Acciones

+
+ +
-
-

Administrar: {{ selectedModule }}

-
+
+
+
+
+ +
+
{{ status }}
+
+
+ +
+

Administrar: {{ selectedModule }}

+
+
@@ -263,6 +291,125 @@ } }; + const formatJson = (value) => `
${JSON.stringify(value, null, 2)}
`; + + const showResult = (value) => { + moduleHtml.value = formatJson(value); + }; + + const confirmPrompt = (message, defaultValue = '') => { + const result = prompt(message, defaultValue); + return result === null ? null : result.trim(); + }; + + const listGuests = async () => { + const guests = await api('/guest'); + showResult(guests); + }; + + const createGuest = async () => { + const name = confirmPrompt('Nombre'); + if (!name) return; + const email = confirmPrompt('Email'); + const phone = confirmPrompt('Teléfono'); + const guest = await api('/guest', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, email, phone }), + }); + showResult(guest); + }; + + const updateGuestRsvp = async () => { + const id = confirmPrompt('ID del invitado'); + if (!id) return; + const rsvp = confirmPrompt('RSVP (true/false)', 'true'); + const updated = await api(`/guest/${id}/rsvp`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ rsvp: rsvp === 'true' }), + }); + showResult(updated); + }; + + const listTodos = async () => { + const todos = await api('/todo'); + showResult(todos); + }; + + const createTodo = async () => { + const title = confirmPrompt('Título'); + if (!title) return; + const description = confirmPrompt('Descripción'); + const todo = await api('/todo', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ title, description }), + }); + showResult(todo); + }; + + const completeTodo = async () => { + const id = confirmPrompt('ID del To-do'); + if (!id) return; + const completed = await api(`/todo/${id}/complete`, { + method: 'PATCH', + }); + showResult(completed); + }; + + const listGifts = async () => { + const gifts = await api('/gift'); + showResult(gifts); + }; + + const createGift = async () => { + const name = confirmPrompt('Nombre del regalo'); + if (!name) return; + const description = confirmPrompt('Descripción'); + const price = confirmPrompt('Precio'); + const gift = await api('/gift', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ name, description, price: Number(price) || 0 }), + }); + showResult(gift); + }; + + const contributeGift = async () => { + const id = confirmPrompt('ID del regalo'); + if (!id) return; + const name = confirmPrompt('Nombre del contribuyente'); + const amount = confirmPrompt('Monto'); + const contribution = await api(`/gift/${id}/contribution`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ contributorName: name, amount: Number(amount) || 0 }), + }); + showResult(contribution); + }; + + const actions = computed(() => { + const map = { + guest: [ + { key: 'list', label: 'Listar invitados', handler: listGuests }, + { key: 'create', label: 'Crear invitado', handler: createGuest }, + { key: 'rsvp', label: 'Actualizar RSVP', handler: updateGuestRsvp }, + ], + todo: [ + { key: 'list', label: 'Listar To-dos', handler: listTodos }, + { key: 'create', label: 'Crear To-do', handler: createTodo }, + { key: 'complete', label: 'Completar To-do', handler: completeTodo }, + ], + gift: [ + { key: 'list', label: 'Listar regalos', handler: listGifts }, + { key: 'create', label: 'Crear regalo', handler: createGift }, + { key: 'contribute', label: 'Agregar contribución', handler: contributeGift }, + ], + }; + return map[selectedModule.value] || []; + }); + const loadModules = async () => { if (!token.value) return; try { @@ -274,7 +421,7 @@ const selectModule = (key) => { selectedModule.value = key; - moduleHtml.value = `

Seleccionado ${key}. Usa los botones del módulo para operar.

`; + moduleHtml.value = `

Seleccionado ${key}. Usa las acciones en el menú.

`; }; return { @@ -285,6 +432,7 @@ modules, selectedModule, moduleHtml, + actions, login, register, loginMessage, @@ -304,4 +452,7 @@ }).mount('#app'); + + +