![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/soundstudiopro.com/public_html/ |
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: /auth/login.php');
exit;
}
require_once 'config/database.php';
require_once 'includes/translations.php';
$pdo = getDBConnection();
$stmt = $pdo->prepare("
SELECT
et.*,
e.id AS event_id,
e.title,
e.start_date,
e.end_date,
e.location,
e.venue_name,
e.address,
e.cover_image,
e.banner_image,
e.event_type,
u.name AS organizer_name
FROM event_tickets et
JOIN events e ON et.event_id = e.id
JOIN users u ON e.creator_id = u.id
WHERE et.user_id = ?
ORDER BY e.start_date DESC, et.purchase_date DESC
");
$stmt->execute([$_SESSION['user_id']]);
$tickets = $stmt->fetchAll(PDO::FETCH_ASSOC);
function formatTicketDateRange($startDate, $endDate = null) {
if (empty($startDate)) {
return '';
}
try {
$start = new DateTime($startDate);
if (!empty($endDate)) {
$end = new DateTime($endDate);
if ($start->format('Y-m-d') === $end->format('Y-m-d')) {
return $start->format('M j, Y g:i A') . ' - ' . $end->format('g:i A');
}
return $start->format('M j, Y g:i A') . ' → ' . $end->format('M j, Y g:i A');
}
return $start->format('M j, Y g:i A');
} catch (Exception $e) {
return $startDate;
}
}
function buildTicketCalendarLink($title, $startDate, $endDate, $locationLabel) {
if (empty($startDate)) {
return '#';
}
try {
$start = new DateTime($startDate);
$end = $endDate ? new DateTime($endDate) : (clone $start)->modify('+2 hours');
$startStr = $start->format('Ymd\THis\Z');
$endStr = $end->format('Ymd\THis\Z');
$text = urlencode($title ?? 'SoundStudioPro Event');
$details = urlencode('Ticket from SoundStudioPro');
$location = urlencode($locationLabel ?? '');
return "https://www.google.com/calendar/render?action=TEMPLATE&text={$text}&dates={$startStr}/{$endStr}&details={$details}&location={$location}";
} catch (Exception $e) {
return '#';
}
}
$page_title = t('tickets.page_title');
$page_description = t('tickets.page_description');
$current_page = 'tickets';
include 'includes/header.php';
?>
<main>
<section class="tickets-page">
<div class="tickets-header">
<h1 class="tickets-title"><?= t('tickets.title') ?></h1>
<p class="tickets-subtitle"><?= t('tickets.subtitle') ?></p>
</div>
<?php if (empty($tickets)): ?>
<div class="tickets-empty">
<i class="fas fa-ticket-alt"></i>
<h3><?= t('tickets.empty_title') ?></h3>
<p><?= t('tickets.empty_message') ?></p>
<a href="/events.php" class="browse-events-btn">
<i class="fas fa-calendar-plus"></i>
<?= t('tickets.browse_events') ?>
</a>
</div>
<?php else: ?>
<div class="tickets-grid">
<?php foreach ($tickets as $ticket): ?>
<?php
$statusSlug = strtolower($ticket['status'] ?? 'confirmed');
$statusKey = 'tickets.status_' . $statusSlug;
$statusLabel = t($statusKey);
if ($statusLabel === $statusKey) {
$statusLabel = ucfirst($statusSlug);
}
$dateLabel = formatTicketDateRange($ticket['start_date'] ?? null, $ticket['end_date'] ?? null);
$locationParts = array_filter([
$ticket['venue_name'] ?? '',
$ticket['address'] ?? '',
$ticket['location'] ?? ''
]);
$locationLabel = implode(', ', $locationParts);
$calendarLink = buildTicketCalendarLink($ticket['title'], $ticket['start_date'] ?? null, $ticket['end_date'] ?? null, $locationLabel);
?>
<article class="ticket-card">
<div class="ticket-glow"></div>
<div class="ticket-header">
<div>
<h2 class="ticket-event-title"><?= htmlspecialchars($ticket['title']) ?></h2>
<p class="ticket-organizer"><?= t('account.organized_by') ?> <?= htmlspecialchars($ticket['organizer_name']) ?></p>
</div>
<span class="ticket-status <?= htmlspecialchars($statusSlug) ?>"><?= htmlspecialchars($statusLabel) ?></span>
</div>
<div class="ticket-details">
<?php if (!empty($dateLabel)): ?>
<div class="ticket-detail-item">
<i class="fas fa-calendar"></i>
<div>
<label><?= t('tickets.event_dates') ?></label>
<span><?= htmlspecialchars($dateLabel) ?></span>
</div>
</div>
<?php endif; ?>
<?php if (!empty($locationLabel)): ?>
<div class="ticket-detail-item">
<i class="fas fa-map-marker-alt"></i>
<div>
<label><?= t('account.event_location') ?></label>
<span><?= htmlspecialchars($locationLabel) ?></span>
</div>
</div>
<?php endif; ?>
<div class="ticket-detail-item">
<i class="fas fa-barcode"></i>
<div>
<label><?= t('account.ticket_code') ?></label>
<span><?= htmlspecialchars($ticket['ticket_code']) ?></span>
</div>
</div>
</div>
<div class="ticket-actions">
<a href="/event_details.php?id=<?= $ticket['event_id'] ?>" class="ticket-btn outline">
<i class="fas fa-eye"></i>
<?= t('account.view_event') ?>
</a>
<a href="/generate_ticket_qr.php?code=<?= urlencode($ticket['ticket_code']) ?>" class="ticket-btn primary" target="_blank" rel="noopener">
<i class="fas fa-qrcode"></i>
<?= t('tickets.print_qr') ?>
</a>
<button class="ticket-btn outline" onclick="copyTicketCode('<?= htmlspecialchars($ticket['ticket_code'], ENT_QUOTES, 'UTF-8') ?>', this)">
<i class="fas fa-copy"></i>
<?= t('tickets.copy_code') ?>
</button>
<a href="<?= htmlspecialchars($calendarLink) ?>" target="_blank" rel="noopener" class="ticket-btn outline">
<i class="fas fa-calendar-plus"></i>
<?= t('account.add_to_calendar') ?>
</a>
</div>
</article>
<?php endforeach; ?>
</div>
<?php endif; ?>
</section>
</main>
<style>
.tickets-page {
max-width: 1200px;
margin: 0 auto;
padding: 3rem 2rem 5rem;
}
.tickets-header {
text-align: center;
margin-bottom: 3rem;
}
.tickets-title {
font-size: 3rem;
font-weight: 800;
margin-bottom: 0.75rem;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.tickets-subtitle {
color: #a0aec0;
font-size: 1.4rem;
}
.tickets-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
gap: 2rem;
}
.ticket-card {
position: relative;
background: rgba(13, 17, 33, 0.85);
border: 1px solid rgba(103, 126, 234, 0.2);
border-radius: 20px;
padding: 2.5rem;
overflow: hidden;
box-shadow: 0 20px 45px rgba(0, 0, 0, 0.35);
backdrop-filter: blur(18px);
}
.ticket-glow {
position: absolute;
inset: -20px;
background: radial-gradient(circle at top, rgba(79, 172, 254, 0.2), transparent 60%);
opacity: 0.6;
pointer-events: none;
}
.ticket-header {
display: flex;
justify-content: space-between;
gap: 1rem;
margin-bottom: 1.5rem;
position: relative;
z-index: 1;
}
.ticket-event-title {
color: #fff;
font-size: 1.9rem;
margin-bottom: 0.5rem;
}
.ticket-organizer {
color: #a0aec0;
font-size: 1.2rem;
}
.ticket-status {
padding: 0.35rem 1rem;
border-radius: 999px;
font-size: 1.1rem;
font-weight: 600;
text-transform: capitalize;
}
.ticket-status.confirmed { background: rgba(72, 187, 120, 0.2); color: #48bb78; }
.ticket-status.pending { background: rgba(237, 137, 54, 0.2); color: #ed8936; }
.ticket-status.used { background: rgba(66, 153, 225, 0.2); color: #4299e1; }
.ticket-status.cancelled { background: rgba(245, 101, 101, 0.2); color: #f56565; }
.ticket-details {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 1.5rem;
}
.ticket-detail-item {
display: flex;
gap: 1rem;
align-items: center;
color: #e2e8f0;
}
.ticket-detail-item i {
color: #667eea;
font-size: 1.4rem;
}
.ticket-detail-item label {
font-size: 1.1rem;
color: #a0aec0;
display: block;
}
.ticket-actions {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
position: relative;
z-index: 1;
}
.ticket-btn {
flex: 1;
min-width: 150px;
text-align: center;
border-radius: 12px;
padding: 0.9rem 1.2rem;
font-weight: 600;
font-size: 1.2rem;
border: 1px solid rgba(255, 255, 255, 0.2);
color: #e2e8f0;
background: transparent;
text-decoration: none;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
cursor: pointer;
}
.ticket-btn.primary {
background: linear-gradient(135deg, #667eea, #764ba2);
border: none;
color: #fff;
}
.ticket-btn:hover {
transform: translateY(-2px);
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.35);
}
.tickets-empty {
text-align: center;
padding: 5rem 2rem;
color: #a0aec0;
}
.tickets-empty i {
font-size: 4rem;
margin-bottom: 1rem;
color: #667eea;
}
.tickets-empty h3 {
font-size: 2rem;
color: #fff;
margin-bottom: 0.5rem;
}
.tickets-empty p {
max-width: 480px;
margin: 0 auto 1.5rem;
}
.browse-events-btn {
background: linear-gradient(135deg, #667eea, #764ba2);
color: #fff;
padding: 1rem 2rem;
border-radius: 10px;
text-decoration: none;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.5rem;
transition: all 0.3s ease;
}
.browse-events-btn:hover {
transform: translateY(-2px);
box-shadow: 0 12px 30px rgba(102, 126, 234, 0.4);
}
@media (max-width: 600px) {
.ticket-actions {
flex-direction: column;
}
}
</style>
<script>
function copyTicketCode(code, el) {
if (!navigator.clipboard) {
alert('<?= addslashes(t('tickets.copy_code')) ?>');
return;
}
const original = el.innerHTML;
navigator.clipboard.writeText(code).then(() => {
el.innerHTML = '<i class="fas fa-check"></i><?= addslashes(t('tickets.code_copied')) ?>';
setTimeout(() => {
el.innerHTML = original;
}, 2000);
}).catch(() => {
alert('<?= addslashes(t('tickets.copy_code')) ?>');
});
}
</script>
<?php include 'includes/footer.php'; ?>