Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"short_description": "Sell and register event tickets",
"description": "",
"tile": "/events/static/image/events.png",
"min_lnbits_version": "1.3.0",
"min_lnbits_version": "1.4.1",
"contributors": [
{
"name": "talvasconcelos",
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ dependencies = [ "lnbits>1" ]
[tool.poetry]
package-mode = false

[tool.uv]
dev-dependencies = [
[dependency-groups]
dev = [
"black",
"pytest-asyncio",
"pytest",
Expand Down
150 changes: 86 additions & 64 deletions static/js/display.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
window.app = Vue.createApp({
el: '#vue',
mixins: [windowMixin],
window.PageEventsDisplay = {
template: '#page-events-display',
data() {
return {
eventName: '',
paymentReq: null,
redirectUrl: null,
formDialog: {
Expand All @@ -27,18 +27,30 @@ window.app = Vue.createApp({
}
},
async created() {
this.info = event_info
this.info = this.info.substring(1, this.info.length - 1)
this.banner = event_banner
this.extra = event_extra
this.hasPromoCodes = has_promoCodes
this.eventId = this.$route.params.id
await this.getEvent()
},
computed: {
formatDescription() {
return LNbits.utils.convertMarkdown(this.info)
}
},
methods: {
async getEvent() {
try {
const {data} = await LNbits.api.request(
'GET',
`/events/api/v1/events/${this.eventId}`
)
this.eventName = data.event_name
this.info = data.event_info
this.banner = data.event_banner
this.extra = data.event_extra
this.hasPromoCodes = data.has_promo_codes
} catch (error) {
LNbits.utils.notifyApiError(error)
}
},
resetForm(e) {
e.preventDefault()
this.formDialog.data.name = ''
Expand All @@ -63,68 +75,78 @@ window.app = Vue.createApp({
const regex = /^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$/
return regex.test(val) || 'Please enter valid email.'
},
Invoice() {
axios
.post(`/events/api/v1/tickets/${event_id}`, {
name: this.formDialog.data.name,
email: this.formDialog.data.email,
promo_code: this.formDialog.data.promo_code || null
})
.then(response => {
this.paymentReq = response.data.payment_request
this.paymentCheck = response.data.payment_hash
async createInvoice() {
try {
const {data} = await LNbits.api.request(
'POST',
`/events/api/v1/tickets/${this.eventId}`,
null,
{
name: this.formDialog.data.name,
email: this.formDialog.data.email,
refund: this.formDialog.data.refund || null
}
)
this.paymentReq = data.payment_request
this.paymentCheck = data.payment_hash

dismissMsg = Quasar.Notify.create({
timeout: 0,
message: 'Waiting for payment...'
})
dismissMsg = Quasar.Notify.create({
timeout: 0,
message: 'Waiting for payment...'
})

this.receive = {
show: true,
status: 'pending',
paymentReq: this.paymentReq
}
paymentChecker = setInterval(() => {
axios
.post(`/events/api/v1/tickets/${event_id}/${this.paymentCheck}`, {
event: event_id,
event_name: event_name,
this.receive = {
show: true,
status: 'pending',
paymentReq: this.paymentReq
}
//TODO: use websockets
paymentChecker = setInterval(async () => {
try {
const res = await LNbits.api.request(
'POST',
`/events/api/v1/tickets/${this.eventId}/${this.paymentCheck}`,
{
event: this.eventId,
event_name: this.eventName,
name: this.formDialog.data.name,
email: this.formDialog.data.email
})
.then(res => {
if (res.data.paid) {
clearInterval(paymentChecker)
dismissMsg()
this.formDialog.data.name = ''
this.formDialog.data.email = ''
}
)
if (res.data.paid) {
clearInterval(paymentChecker)
dismissMsg()
this.formDialog.data.name = ''
this.formDialog.data.email = ''

Quasar.Notify.create({
type: 'positive',
message: 'Sent, thank you!',
icon: null
})
this.receive = {
show: false,
status: 'complete',
paymentReq: null
}
Quasar.Notify.create({
type: 'positive',
message: 'Sent, thank you!',
icon: null
})
this.receive = {
show: false,
status: 'complete',
paymentReq: null
}

this.ticketLink = {
show: true,
data: {
link: `/events/ticket/${res.data.ticket_id}`
}
}
setTimeout(() => {
window.location.href = `/events/ticket/${res.data.ticket_id}`
}, 5000)
this.ticketLink = {
show: true,
data: {
link: `/events/ticket/${res.data.ticket_id}`
}
})
.catch(LNbits.utils.notifyApiError)
}, 2000)
})
.catch(LNbits.utils.notifyApiError)
}
setTimeout(() => {
window.location.href = `/events/ticket/${res.data.ticket_id}`
}, 5000)
}
} catch (error) {
LNbits.utils.notifyApiError(error)
}
}, 2000)
} catch (error) {
LNbits.utils.notifyApiError(error)
}
}
}
})
}
115 changes: 115 additions & 0 deletions static/js/display.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<template id="page-events-display">
<div class="row q-col-gutter-md justify-center">
<div class="col-12 col-md-7 col-lg-6 q-gutter-y-md">
<q-card>
<q-img v-if="banner" :src="banner" transition="slide-up"></q-img>
<q-card-section class="q-pa-none">
<h3 class="q-my-none q-pa-lg" v-text="eventName"></h3>
<br />
<div v-html="formatDescription" class="q-pa-md"></div>
<br />
</q-card-section>
</q-card>
<q-card class="q-pa-lg">
<q-card-section class="q-pa-none">
<h5 class="q-mt-none">Buy Ticket</h5>
<q-form @submit="createInvoice()" class="q-gutter-md">
<q-input
filled
dense
v-model.trim="formDialog.data.name"
label="Your name "
:rules="[val => nameValidation(val)]"
></q-input>
<q-input
filled
dense
v-model.trim="formDialog.data.email"
type="email"
label="Your email "
:rules="[
val => !!val || '* Required',
val => emailValidation(val)
]"
lazy-rules
></q-input>
<q-input
v-if="this.extra?.conditional"
filled
dense
v-model.trim="formDialog.data.refund"
label="Refund lnadress or LNURL "
:rules="[val => !!val || '* Required']"
lazy-rules
:hint="`If minimum tickets (${this.extra?.min_tickets}) are not met, refund will be sent.`"
></q-input>
<q-input
v-if="hasPromoCodes"
filled
dense
v-model.trim="formDialog.data.promo_code"
label="Apply Promo Code "
></q-input>
<div class="row q-mt-lg">
<q-btn
unelevated
color="primary"
:disable="
formDialog.data.name == '' ||
formDialog.data.email == '' ||
Boolean(paymentReq)
"
type="submit"
>Submit</q-btn
>
<q-btn @click="resetForm" flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
</div>
</q-form>
</q-card-section>
</q-card>

<q-card v-show="ticketLink.show" class="q-pa-lg">
<div class="text-center q-mb-lg">
<q-btn
unelevated
size="xl"
:href="ticketLink.data.link"
target="_blank"
color="primary"
type="a"
>Link to your ticket!</q-btn
>
<br /><br />
<p>You'll be redirected in a few moments...</p>
</div>
</q-card>
</div>

<q-dialog v-model="receive.show" position="top" @hide="closeReceiveDialog">
<q-card
v-if="!receive.paymentReq"
class="q-pa-lg q-pt-xl lnbits__dialog-card"
>
</q-card>
<q-card v-else class="q-pa-lg q-pt-xl lnbits__dialog-card">
<div class="text-center q-mb-lg">
<lnbits-qrcode
:href="'lightning:' + receive.paymentReq"
:value="'lightning:' + receive.paymentReq.toUpperCase()"
></lnbits-qrcode>
</div>
<div class="row q-mt-lg">
<q-btn
outline
color="grey"
@click="utils.copyText(receive.paymentReq)"
>Copy invoice</q-btn
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Close</q-btn>
</div>
</q-card>
</q-dialog>
</div>
</template>
13 changes: 8 additions & 5 deletions static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ const mapEvents = function (obj) {
return obj
}

window.app = Vue.createApp({
el: '#vue',
mixins: [windowMixin],
window.PageEvents = {
template: '#page-events',
data() {
return {
events: [],
Expand Down Expand Up @@ -290,7 +289,11 @@ window.app = Vue.createApp({
if (this.g.user.wallets.length) {
this.getTickets()
this.getEvents()
this.currencies = await LNbits.api.getCurrencies()
if (g.allowedCurrencies && g.allowedCurrencies.length) {
this.currencies = ['sats', ...g.allowedCurrencies]
} else {
this.currencies = ['sats', ...g.currencies]
}
}
}
})
}
Loading
Loading