refactor: Revamp PurchaseTicketDialog and introduce useTicketPurchase composable

- Update PurchaseTicketDialog.vue to integrate authentication checks and enhance ticket purchasing flow with wallet support.
- Implement useTicketPurchase composable for managing ticket purchase logic, including payment handling and QR code generation.
- Improve user experience by displaying user information and wallet status during the ticket purchase process.
- Refactor API interactions in events.ts to streamline ticket purchasing and payment status checks.
This commit is contained in:
padreug 2025-08-01 21:33:11 +02:00
parent ed51c95799
commit f7450627bc
5 changed files with 555 additions and 113 deletions

View file

@ -1,9 +1,15 @@
import type { Event, EventsApiError } from '../types/event'
import { config } from '@/lib/config'
import { lnbitsAPI } from './lnbits'
const API_BASE_URL = config.api.baseUrl || 'http://lnbits'
const API_KEY = config.api.key
// Generic error type for API responses
interface ApiError {
detail: string | Array<{ loc: [string, number]; msg: string; type: string }>
}
export async function fetchEvents(allWallets = true): Promise<Event[]> {
try {
const response = await fetch(
@ -17,8 +23,11 @@ export async function fetchEvents(allWallets = true): Promise<Event[]> {
)
if (!response.ok) {
const error: EventsApiError = await response.json()
throw new Error(error.detail[0]?.msg || 'Failed to fetch events')
const error: ApiError = await response.json()
const errorMessage = typeof error.detail === 'string'
? error.detail
: error.detail[0]?.msg || 'Failed to fetch events'
throw new Error(errorMessage)
}
return await response.json() as Event[]
@ -26,4 +35,100 @@ export async function fetchEvents(allWallets = true): Promise<Event[]> {
console.error('Error fetching events:', error)
throw error
}
}
export async function purchaseTicket(eventId: string): Promise<{ payment_hash: string; payment_request: string }> {
try {
// Get current user to ensure authentication
const user = await lnbitsAPI.getCurrentUser()
if (!user) {
throw new Error('User not authenticated')
}
const response = await fetch(
`${API_BASE_URL}/events/api/v1/tickets/${eventId}/user/${user.id}`,
{
method: 'GET',
headers: {
'accept': 'application/json',
'X-API-KEY': API_KEY,
'Authorization': `Bearer ${lnbitsAPI.getAccessToken()}`,
},
}
)
if (!response.ok) {
const error: ApiError = await response.json()
const errorMessage = typeof error.detail === 'string'
? error.detail
: error.detail[0]?.msg || 'Failed to purchase ticket'
throw new Error(errorMessage)
}
return await response.json()
} catch (error) {
console.error('Error purchasing ticket:', error)
throw error
}
}
export async function payInvoiceWithWallet(paymentRequest: string, walletId: string, adminKey: string): Promise<{ payment_hash: string; fee_msat: number; preimage: string }> {
try {
const response = await fetch(
`${API_BASE_URL}/api/v1/payments`,
{
method: 'POST',
headers: {
'accept': 'application/json',
'Content-Type': 'application/json',
'X-API-KEY': adminKey,
},
body: JSON.stringify({
out: true,
bolt11: paymentRequest,
}),
}
)
if (!response.ok) {
const error: ApiError = await response.json()
const errorMessage = typeof error.detail === 'string'
? error.detail
: error.detail[0]?.msg || 'Failed to pay invoice'
throw new Error(errorMessage)
}
return await response.json()
} catch (error) {
console.error('Error paying invoice:', error)
throw error
}
}
export async function checkPaymentStatus(eventId: string, paymentHash: string): Promise<{ paid: boolean; ticket_id?: string }> {
try {
const response = await fetch(
`${API_BASE_URL}/events/api/v1/tickets/${eventId}/${paymentHash}`,
{
method: 'POST',
headers: {
'accept': 'application/json',
'X-API-KEY': API_KEY,
},
}
)
if (!response.ok) {
const error: ApiError = await response.json()
const errorMessage = typeof error.detail === 'string'
? error.detail
: error.detail[0]?.msg || 'Failed to check payment status'
throw new Error(errorMessage)
}
return await response.json()
} catch (error) {
console.error('Error checking payment status:', error)
throw error
}
}

View file

@ -17,13 +17,47 @@ interface AuthResponse {
email?: string
}
interface Wallet {
id: string
user: string
name: string
adminkey: string
inkey: string
deleted: boolean
created_at: string
updated_at: string
currency?: string
balance_msat: number
extra?: {
icon: string
color: string
pinned: boolean
}
}
interface User {
id: string
username?: string
email?: string
pubkey?: string
external_id?: string
extensions: string[]
wallets: Wallet[]
admin: boolean
super_user: boolean
fiat_providers: string[]
has_password: boolean
created_at: string
updated_at: string
extra?: {
email_verified?: boolean
first_name?: string
last_name?: string
display_name?: string
picture?: string
provider?: string
visible_wallet_count?: number
}
}
import { getApiUrl, getAuthToken, setAuthToken, removeAuthToken } from '@/lib/config/lnbits'