Files
funcode2.0/app/api/purchase/route.js
devbeni 2c5461b0e0 Refactor socket handling and integrate database for event management
- Removed old socket handling code and replaced it with a new implementation in `app/api/socketio/route.js`.
- Added MySQL database integration for managing active sessions and queue entries.
- Implemented event retrieval and ticket purchasing APIs in `app/api/events/route.js` and `app/api/purchase/route.js`.
- Created database schema for events, tickets, active sessions, and orders in `database/schema.sql`.
- Updated front-end to handle event data fetching and ticket purchasing with improved UI components.
- Removed unused SVG files from the public directory.
2025-09-19 19:02:15 +02:00

107 lines
3.1 KiB
JavaScript

import mysql from 'mysql2/promise'
import jwt from 'jsonwebtoken'
async function getDbConnection() {
if (!process.env.MYSQL_HOST) return null
return await mysql.createConnection({
host: process.env.MYSQL_HOST,
user: process.env.MYSQL_USER,
password: process.env.MYSQL_PASSWORD,
database: process.env.MYSQL_DATABASE,
})
}
export async function POST(request) {
try {
const { eventId, ticketType, quantity, token } = await request.json()
if (!eventId || !ticketType || !quantity || !token) {
return Response.json({ error: 'Missing required fields' }, { status: 400 })
}
// Verify JWT token
let decoded
try {
decoded = jwt.verify(token, process.env.JWT_SECRET || 'dev-secret')
} catch (error) {
return Response.json({ error: 'Invalid or expired token' }, { status: 401 })
}
const connection = await getDbConnection()
if (!connection) {
return Response.json({ error: 'Database not configured' }, { status: 500 })
}
// Check if token is still active in database
const [activeRows] = await connection.execute(
'SELECT * FROM active_sessions WHERE event_id = ? AND socket_id = ? AND expires_at > NOW()',
[eventId, decoded.sid]
)
if (activeRows.length === 0) {
await connection.end()
return Response.json({ error: 'Session expired or not authorized' }, { status: 401 })
}
// Get ticket information
const [ticketRows] = await connection.execute(
'SELECT * FROM tickets WHERE event_id = ? AND type = ?',
[eventId, ticketType]
)
if (ticketRows.length === 0) {
await connection.end()
return Response.json({ error: 'Ticket type not found' }, { status: 404 })
}
const ticket = ticketRows[0]
const availableQuantity = ticket.total_quantity - ticket.sold_quantity
if (quantity > availableQuantity) {
await connection.end()
return Response.json({
error: 'Not enough tickets available',
available: availableQuantity
}, { status: 400 })
}
const totalPrice = ticket.price * quantity
// Start transaction
await connection.beginTransaction()
try {
// Create order
const [orderResult] = await connection.execute(
'INSERT INTO orders (event_id, socket_id, ticket_type, quantity, total_price, status) VALUES (?, ?, ?, ?, ?, ?)',
[eventId, decoded.sid, ticketType, quantity, totalPrice, 'completed']
)
// Update sold quantity
await connection.execute(
'UPDATE tickets SET sold_quantity = sold_quantity + ? WHERE event_id = ? AND type = ?',
[quantity, eventId, ticketType]
)
await connection.commit()
await connection.end()
return Response.json({
success: true,
orderId: orderResult.insertId,
totalPrice,
message: `Successfully purchased ${quantity} ${ticketType} ticket(s)`
})
} catch (error) {
await connection.rollback()
await connection.end()
throw error
}
} catch (error) {
console.error('Purchase API error:', error)
return Response.json({ error: 'Purchase failed' }, { status: 500 })
}
}