feat(cms): Vue 3 + Quasar 2 UMD CMS templates
LNbits convention: extends base.html, declares window.app =
Vue.createApp({mixins: [windowMixin], data, methods, created}); the
LNbits init-app.js loads after extension scripts and finishes the
mount with app.use(Quasar) + app.mount('#vue').
Pages
- index.html restaurant list / dashboard with create dialog;
scoped to the logged-in user's wallets.
- menu.html category sidebar + items grid; full item dialog
with price/currency/images/dietary/allergens/
ingredients/calories/stock/availability/featured.
Modifier groups managed in a separate dialog
with required|optional + one|many semantics.
- orders.html filterable q-table with status colors and inline
state-machine actions (accept/ready/complete/
cancel). Polls every 8s.
- kds.html kitchen display: card-per-order, items + selected
modifiers + notes, age-based color escalation
(>5min orange, >15min red), polls every 5s. The
poll loop is a stand-in until SSE/Nostr push
lands.
- settings.html restaurant profile editor + delete + per-instance
ext settings panel (Nostr publish toggle, auto-
accept, invoice expiry).
Static
- js/api.js single REST client (LNbits.api.request wrapper)
used by all pages.
- js/index.js dashboard logic.
- js/menu.js menu CRUD.
- js/orders.js order monitor.
- js/kds.js kitchen display.
- js/settings.js settings persistence.
Customer kiosk UI lives in ~/dev/webapp; this extension only ships
the operator console.
This commit is contained in:
parent
c37b17d474
commit
3382462af4
11 changed files with 1576 additions and 0 deletions
72
static/js/settings.js
Normal file
72
static/js/settings.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
window.app = Vue.createApp({
|
||||
el: '#vue',
|
||||
mixins: [windowMixin],
|
||||
data() {
|
||||
return {
|
||||
form: window.RESTAURANT_BOOTSTRAP || {},
|
||||
relaysText: '',
|
||||
extSettings: null,
|
||||
isAdmin: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
adminkey() {
|
||||
const w = this.g.user.wallets.find((w) => w.id === this.form.wallet)
|
||||
return (w && w.adminkey) || (this.g.user.wallets[0] && this.g.user.wallets[0].adminkey)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async save() {
|
||||
try {
|
||||
const payload = {
|
||||
...this.form,
|
||||
nostr_relays: (this.relaysText || '')
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean)
|
||||
}
|
||||
const {data} = await RestaurantAPI.updateRestaurant(
|
||||
this.adminkey,
|
||||
this.form.id,
|
||||
payload
|
||||
)
|
||||
this.form = data
|
||||
this.relaysText = (data.nostr_relays || []).join(', ')
|
||||
Quasar.Notify.create({type: 'positive', message: 'Saved'})
|
||||
} catch (err) {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
}
|
||||
},
|
||||
async deleteRestaurant() {
|
||||
if (!confirm(`Permanently delete ${this.form.name} and all its data?`)) return
|
||||
try {
|
||||
await RestaurantAPI.deleteRestaurant(this.adminkey, this.form.id)
|
||||
window.location.href = '/restaurant/'
|
||||
} catch (err) {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
}
|
||||
},
|
||||
async fetchExtSettings() {
|
||||
try {
|
||||
const {data} = await RestaurantAPI.getSettings(this.adminkey)
|
||||
this.extSettings = data
|
||||
this.isAdmin = true
|
||||
} catch (err) {
|
||||
// Non-admins get 401/403 — silently swallow.
|
||||
this.isAdmin = false
|
||||
}
|
||||
},
|
||||
async saveExtSettings() {
|
||||
if (!this.extSettings) return
|
||||
try {
|
||||
await RestaurantAPI.updateSettings(this.adminkey, this.extSettings)
|
||||
} catch (err) {
|
||||
LNbits.utils.notifyApiError(err)
|
||||
}
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.relaysText = (this.form.nostr_relays || []).join(', ')
|
||||
await this.fetchExtSettings()
|
||||
}
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue