feat: event proposal and approval workflow #9

Closed
padreug wants to merge 38 commits from feat/event-approval-workflow into main
2 changed files with 64 additions and 16 deletions
Showing only changes of commit ba97205592 - Show all commits

feat: separate admin view into own events and all users' events
Some checks failed
lint.yml / feat: separate admin view into own events and all users' events (pull_request) Failing after 0s

Admin sees two tables: "Events" (own wallet events) and "All Users'
Events" (events from other users' wallets, admin only). Non-admin
users only see their own events table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Padreug 2026-04-27 11:34:59 +02:00

View file

@ -11,7 +11,9 @@ window.app = Vue.createApp({
data() { data() {
return { return {
events: [], events: [],
allUserEvents: [],
pendingEvents: [], pendingEvents: [],
isAdmin: false,
tickets: [], tickets: [],
currencies: [], currencies: [],
eventsTable: { eventsTable: {
@ -200,21 +202,7 @@ window.app = Vue.createApp({
LNbits.utils.exportCSV(this.ticketsTable.columns, this.tickets) LNbits.utils.exportCSV(this.ticketsTable.columns, this.tickets)
}, },
getEvents() { getEvents() {
// Try admin endpoint first (shows all events across all wallets) // Always fetch own events
// Falls back to user's own events if not admin
LNbits.api
.request(
'GET',
'/events/api/v1/events/all'
)
.then(response => {
this.events = response.data.map(obj => {
return mapEvents(obj)
})
this.checkCanceledEvents()
})
.catch(() => {
// Not admin, fall back to own events
LNbits.api LNbits.api
.request( .request(
'GET', 'GET',
@ -227,6 +215,24 @@ window.app = Vue.createApp({
}) })
this.checkCanceledEvents() this.checkCanceledEvents()
}) })
// Admin: also fetch all users' events
LNbits.api
.request(
'GET',
'/events/api/v1/events/all'
)
.then(response => {
this.isAdmin = true
// Exclude own events (already in this.events)
const ownWalletIds = this.g.user.wallets.map(w => w.id)
this.allUserEvents = response.data
.filter(obj => !ownWalletIds.includes(obj.wallet))
.map(obj => mapEvents(obj))
})
.catch(() => {
this.isAdmin = false
this.allUserEvents = []
}) })
}, },
getPendingEvents() { getPendingEvents() {

View file

@ -229,6 +229,48 @@
</q-card-section> </q-card-section>
</q-card> </q-card>
<!-- All Users' Events (admin only) -->
<q-card v-if="isAdmin && allUserEvents.length > 0">
<q-card-section>
<div class="row items-center no-wrap q-mb-md">
<div class="col">
<h5 class="text-subtitle1 q-my-none">
All Users' Events
<q-badge color="blue" :label="allUserEvents.length" class="q-ml-sm"></q-badge>
</h5>
</div>
</div>
<q-table
dense
flat
:rows="allUserEvents"
row-key="id"
:columns="eventsTable.columns"
:pagination="{rowsPerPage: 10}"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span v-text="col.label"></span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<q-badge
v-if="col.name === 'status'"
:color="col.value === 'approved' ? 'green' : col.value === 'proposed' ? 'orange' : 'red'"
:label="col.value"
></q-badge>
<span v-else v-text="col.value"></span>
</q-td>
</q-tr>
</template>
</q-table>
</q-card-section>
</q-card>
<q-card> <q-card>
<q-card-section> <q-card-section>
<div class="row items-center no-wrap q-mb-md"> <div class="row items-center no-wrap q-mb-md">