Sindbad~EG File Manager

Current Path : /home/copmadinaarea/thecopmadinaarea.org/conference/admin/
Upload File :
Current File : /home/copmadinaarea/thecopmadinaarea.org/conference/admin/tickets.php

<?php
require_once '../includes/functions.php';

// Check if user is logged in and has admin privileges
if (!isLoggedIn()) {
    header('Location: ' . BASE_URL . 'login.php');
    exit();
}

$user = getCurrentUser();
if (!in_array($user['role'], ['superuser', 'area_admin', 'district_admin', 'assembly_admin'])) {
    header('Location: ' . BASE_URL . 'dashboard.php');
    exit();
}

$db = new CopMadinaDB();
$conn = $db->getConnection();

// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['action'])) {
        switch ($_POST['action']) {
            case 'add':
                $stmt = $conn->prepare("INSERT INTO ticket_types (event_id, name, description, price, capacity, status) VALUES (?, ?, ?, ?, ?, ?)");
                $result = $stmt->execute([
                    $_POST['event_id'],
                    $_POST['name'],
                    $_POST['description'],
                    $_POST['price'],
                    $_POST['capacity'],
                    $_POST['status']
                ]);
                
                if ($result) {
                    addNotification('success', 'Ticket type added successfully!', $user['id']);
                    logActivity($user['id'], 'ticket_created', 'Created ticket type: ' . $_POST['name']);
                } else {
                    addNotification('error', 'Failed to add ticket type.', $user['id']);
                }
                break;
                
            case 'edit':
                $stmt = $conn->prepare("UPDATE ticket_types SET event_id = ?, name = ?, description = ?, price = ?, capacity = ?, status = ? WHERE id = ?");
                $result = $stmt->execute([
                    $_POST['event_id'],
                    $_POST['name'],
                    $_POST['description'],
                    $_POST['price'],
                    $_POST['capacity'],
                    $_POST['status'],
                    $_POST['ticket_id']
                ]);
                
                if ($result) {
                    addNotification('success', 'Ticket type updated successfully!', $user['id']);
                    logActivity($user['id'], 'ticket_updated', 'Updated ticket type: ' . $_POST['name']);
                } else {
                    addNotification('error', 'Failed to update ticket type.', $user['id']);
                }
                break;
                
            case 'delete':
                $stmt = $conn->prepare("DELETE FROM ticket_types WHERE id = ?");
                $result = $stmt->execute([$_POST['ticket_id']]);
                
                if ($result) {
                    addNotification('success', 'Ticket type deleted successfully!', $user['id']);
                    logActivity($user['id'], 'ticket_deleted', 'Deleted ticket type ID: ' . $_POST['ticket_id']);
                } else {
                    addNotification('error', 'Failed to delete ticket type.', $user['id']);
                }
                break;
        }
        
        header('Location: tickets.php');
        exit();
    }
}

// Get tickets with event information
$whereClause = "WHERE 1=1";
$params = [];

// Role-based filtering
if ($user['role'] === 'area_admin') {
    $whereClause .= " AND e.area_id = ?";
    $params[] = $user['area_id'];
} elseif ($user['role'] === 'district_admin') {
    $whereClause .= " AND e.district_id = ?";
    $params[] = $user['district_id'];
} elseif ($user['role'] === 'assembly_admin') {
    $whereClause .= " AND e.assembly_id = ?";
    $params[] = $user['assembly_id'];
}

$stmt = $conn->prepare("
    SELECT tt.*, e.title as event_title, e.start_date, e.end_date,
           (SELECT COUNT(*) FROM event_registrations er WHERE er.ticket_type_id = tt.id) as sold_count,
           (SELECT COUNT(*) FROM nonmember_registrations nr WHERE nr.ticket_type_id = tt.id) as nonmember_sold_count
    FROM ticket_types tt 
    JOIN events e ON tt.event_id = e.id 
    $whereClause
    ORDER BY e.start_date DESC, tt.name ASC
");
$stmt->execute($params);
$tickets = $stmt->fetchAll(PDO::FETCH_ASSOC);

// Get events for dropdown
$eventStmt = $conn->prepare("
    SELECT id, title, start_date, end_date 
    FROM events 
    $whereClause
    ORDER BY start_date DESC
");
$eventStmt->execute($params);
$events = $eventStmt->fetchAll(PDO::FETCH_ASSOC);

$notifications = getNotifications($user['id']);
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ticket Management - COP Madina Conference</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    animation: {
                        'fade-in': 'fadeIn 0.5s ease-out',
                        'slide-up': 'slideUp 0.6s ease-out',
                        'scale-in': 'scaleIn 0.3s ease-out'
                    },
                    keyframes: {
                        fadeIn: {
                            '0%': { opacity: '0' },
                            '100%': { opacity: '1' }
                        },
                        slideUp: {
                            '0%': { opacity: '0', transform: 'translateY(20px)' },
                            '100%': { opacity: '1', transform: 'translateY(0)' }
                        },
                        scaleIn: {
                            '0%': { opacity: '0', transform: 'scale(0.95)' },
                            '100%': { opacity: '1', transform: 'scale(1)' }
                        }
                    }
                }
            }
        }
    </script>
</head>
<body class="bg-gradient-to-br from-slate-50 to-blue-50 min-h-screen">
    <div id="app" class="flex h-screen">
        <!-- Sidebar -->
        <?php include 'includes/admin_sidebar.php'; ?>
        
        <!-- Main Content -->
        <div class="flex-1 flex flex-col overflow-hidden ml-72">
            <!-- Header -->
            <header class="bg-white/80 backdrop-blur-sm shadow-lg border-b border-slate-200/50">
                <div class="flex items-center justify-between px-8 py-6">
                    <div class="animate-fade-in">
                        <h1 class="text-3xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent flex items-center">
                            <div class="p-2 rounded-xl bg-gradient-to-br from-blue-500 to-purple-600 mr-3">
                                <i class="fas fa-ticket-alt text-white"></i>
                            </div>
                            Ticket Management
                        </h1>
                        <p class="text-slate-600 mt-1">Manage event ticket types and pricing</p>
                    </div>
                    <button @click="showCreateModal = true" 
                            class="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white font-medium rounded-xl transition-all duration-200 flex items-center space-x-2 shadow-lg hover:shadow-xl animate-scale-in">
                        <i class="fas fa-plus"></i>
                        <span>Add Ticket Type</span>
                    </button>
                </div>
            </header>

            <!-- Content -->
            <main class="flex-1 overflow-y-auto p-8">

                <!-- Notifications -->
                <?php if (!empty($notifications)): ?>
                <div class="mb-6 space-y-2">
                    <?php foreach ($notifications as $notification): ?>
                        <div class="alert alert-<?php echo $notification['type']; ?> p-4 rounded-xl border-l-4 <?php echo $notification['type'] === 'success' ? 'bg-emerald-50 border-emerald-500 text-emerald-800' : 'bg-red-50 border-red-500 text-red-800'; ?>">
                            <div class="flex items-center">
                                <i class="fas <?php echo $notification['type'] === 'success' ? 'fa-check-circle' : 'fa-exclamation-circle'; ?> mr-3"></i>
                                <?php echo htmlspecialchars($notification['message']); ?>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
                <?php endif; ?>

                <!-- Tickets Grid -->
                <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
                    <?php foreach ($tickets as $index => $ticket): ?>
                    <div class="group bg-white/70 backdrop-blur-sm rounded-2xl shadow-lg hover:shadow-xl transition-all duration-300 p-6 border border-slate-200/50 hover:border-blue-300/50 animate-slide-up" 
                         style="animation-delay: <?php echo $index * 0.1; ?>s">
                        <div class="flex items-start justify-between mb-4">
                            <div class="flex-1">
                                <h3 class="text-xl font-bold text-slate-800 mb-1"><?php echo htmlspecialchars($ticket['name']); ?></h3>
                                <p class="text-sm text-slate-600 mb-2"><?php echo htmlspecialchars($ticket['event_title']); ?></p>
                                <span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium <?php echo $ticket['status'] === 'active' ? 'bg-emerald-100 text-emerald-800' : 'bg-slate-100 text-slate-800'; ?>">
                                    <?php echo ucfirst($ticket['status']); ?>
                                </span>
                            </div>
                            <div class="flex space-x-2">
                                <button @click="editTicket(<?php echo htmlspecialchars(json_encode($ticket)); ?>)" class="text-blue-600 hover:text-blue-800 p-2 rounded-lg hover:bg-blue-50 transition-colors">
                                    <i class="fas fa-edit"></i>
                                </button>
                                <button @click="deleteTicket(<?php echo $ticket['id']; ?>)" class="text-red-600 hover:text-red-800 p-2 rounded-lg hover:bg-red-50 transition-colors">
                                    <i class="fas fa-trash"></i>
                                </button>
                            </div>
                        </div>
                        
                        <div class="space-y-3">
                            <div class="flex justify-between items-center">
                                <span class="text-sm text-slate-600">Price:</span>
                                <span class="font-semibold text-slate-800">GH₵<?php echo number_format($ticket['price'], 2); ?></span>
                            </div>
                            
                            <div class="flex justify-between items-center">
                                <span class="text-sm text-slate-600">Capacity:</span>
                                <span class="font-semibold text-slate-800"><?php echo $ticket['capacity'] ?: 'Unlimited'; ?></span>
                            </div>
                            
                            <div class="flex justify-between items-center">
                                <span class="text-sm text-slate-600">Sold:</span>
                                <span class="font-semibold text-slate-800"><?php echo ($ticket['sold_count'] + $ticket['nonmember_sold_count']); ?></span>
                            </div>
                            
                            <?php if ($ticket['description']): ?>
                            <div class="pt-3 border-t border-slate-200">
                                <p class="text-sm text-slate-600"><?php echo htmlspecialchars($ticket['description']); ?></p>
                            </div>
                            <?php endif; ?>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>

                <?php if (empty($tickets)): ?>
                <div class="text-center py-12">
                    <div class="inline-flex items-center justify-center w-16 h-16 bg-slate-100 rounded-full mb-4">
                        <i class="fas fa-ticket-alt text-2xl text-slate-400"></i>
                    </div>
                    <h3 class="text-xl font-semibold text-slate-800 mb-2">No Ticket Types Found</h3>
                    <p class="text-slate-600 mb-6">Create your first ticket type to get started.</p>
                    <button @click="showCreateModal = true" class="bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white px-6 py-3 rounded-xl font-semibold shadow-lg hover:shadow-xl transition-all duration-300">
                        <i class="fas fa-plus mr-2"></i>Add Ticket Type
                    </button>
                </div>
                <?php endif; ?>

                <!-- Create/Edit Modal -->
                <div v-if="showCreateModal || showEditModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50" @click.self="closeModals">
                    <div class="bg-white rounded-2xl shadow-2xl w-full max-w-2xl mx-4 max-h-[90vh] overflow-y-auto">
                        <div class="p-6 border-b border-slate-200">
                            <h2 class="text-2xl font-bold text-slate-800">{{ showEditModal ? 'Edit Ticket Type' : 'Create New Ticket Type' }}</h2>
                        </div>
                        
                        <form :action="'tickets.php'" method="POST" class="p-6 space-y-6">
                            <input type="hidden" name="action" :value="showEditModal ? 'edit' : 'add'">
                            <input v-if="showEditModal" type="hidden" name="ticket_id" :value="editingTicket.id">
                            
                            <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
                                <div>
                                    <label class="block text-sm font-semibold text-slate-700 mb-2">Event *</label>
                                    <select name="event_id" v-model="formData.event_id" required class="w-full px-4 py-3 border border-slate-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                                        <option value="">Select Event</option>
                                        <?php foreach ($events as $event): ?>
                                        <option value="<?php echo $event['id']; ?>"><?php echo htmlspecialchars($event['title']); ?></option>
                                        <?php endforeach; ?>
                                    </select>
                                </div>
                                
                                <div>
                                    <label class="block text-sm font-semibold text-slate-700 mb-2">Ticket Name *</label>
                                    <input type="text" name="name" v-model="formData.name" required class="w-full px-4 py-3 border border-slate-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="e.g., Early Bird, Regular, VIP">
                                </div>
                            </div>
                            
                            <div>
                                <label class="block text-sm font-semibold text-slate-700 mb-2">Description</label>
                                <textarea name="description" v-model="formData.description" rows="3" class="w-full px-4 py-3 border border-slate-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="Ticket description..."></textarea>
                            </div>
                            
                            <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                                <div>
                                    <label class="block text-sm font-semibold text-slate-700 mb-2">Price (GH₵) *</label>
                                    <input type="number" name="price" v-model="formData.price" step="0.01" min="0" required class="w-full px-4 py-3 border border-slate-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="0.00">
                                </div>
                                
                                <div>
                                    <label class="block text-sm font-semibold text-slate-700 mb-2">Capacity</label>
                                    <input type="number" name="capacity" v-model="formData.capacity" min="0" class="w-full px-4 py-3 border border-slate-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent" placeholder="Leave empty for unlimited">
                                </div>
                                
                                <div>
                                    <label class="block text-sm font-semibold text-slate-700 mb-2">Status *</label>
                                    <select name="status" v-model="formData.status" required class="w-full px-4 py-3 border border-slate-300 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-transparent">
                                        <option value="active">Active</option>
                                        <option value="inactive">Inactive</option>
                                    </select>
                                </div>
                            </div>
                            
                            <div class="flex justify-end space-x-4 pt-6 border-t border-slate-200">
                                <button type="button" @click="closeModals" class="px-6 py-3 border border-slate-300 text-slate-700 rounded-xl hover:bg-slate-50 font-semibold transition-colors">
                                    Cancel
                                </button>
                                <button type="submit" class="px-6 py-3 bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-white rounded-xl font-semibold shadow-lg hover:shadow-xl transition-all duration-300">
                                    {{ showEditModal ? 'Update Ticket Type' : 'Create Ticket Type' }}
                                </button>
                            </div>
                        </form>
                    </div>
                </div>

                <!-- Delete Confirmation Modal -->
                <div v-if="showDeleteModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
                    <div class="bg-white rounded-2xl shadow-2xl w-full max-w-md mx-4">
                        <div class="p-6 text-center">
                            <div class="inline-flex items-center justify-center w-16 h-16 bg-red-100 rounded-full mb-4">
                                <i class="fas fa-exclamation-triangle text-2xl text-red-600"></i>
                            </div>
                            <h3 class="text-xl font-bold text-slate-800 mb-2">Delete Ticket Type</h3>
                            <p class="text-slate-600 mb-6">Are you sure you want to delete this ticket type? This action cannot be undone.</p>
                            
                            <div class="flex justify-center space-x-4">
                                <button @click="showDeleteModal = false" class="px-6 py-3 border border-slate-300 text-slate-700 rounded-xl hover:bg-slate-50 font-semibold transition-colors">
                                    Cancel
                                </button>
                                <form method="POST" class="inline">
                                    <input type="hidden" name="action" value="delete">
                                    <input type="hidden" name="ticket_id" :value="deletingTicketId">
                                    <button type="submit" class="px-6 py-3 bg-red-600 hover:bg-red-700 text-white rounded-xl font-semibold transition-colors">
                                        Delete
                                    </button>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </main>
        </div>
    </div>

    <script>
        const { createApp } = Vue;
        
        createApp({
            data() {
                return {
                    showCreateModal: false,
                    showEditModal: false,
                    showDeleteModal: false,
                    editingTicket: {},
                    deletingTicketId: null,
                    formData: {
                        event_id: '',
                        name: '',
                        description: '',
                        price: '',
                        capacity: '',
                        status: 'active'
                    }
                }
            },
            methods: {
                editTicket(ticket) {
                    this.editingTicket = ticket;
                    this.formData = {
                        event_id: ticket.event_id,
                        name: ticket.name,
                        description: ticket.description || '',
                        price: ticket.price,
                        capacity: ticket.capacity || '',
                        status: ticket.status
                    };
                    this.showEditModal = true;
                },
                deleteTicket(ticketId) {
                    this.deletingTicketId = ticketId;
                    this.showDeleteModal = true;
                },
                closeModals() {
                    this.showCreateModal = false;
                    this.showEditModal = false;
                    this.showDeleteModal = false;
                    this.editingTicket = {};
                    this.deletingTicketId = null;
                    this.formData = {
                        event_id: '',
                        name: '',
                        description: '',
                        price: '',
                        capacity: '',
                        status: 'active'
                    };
                }
            }
        }).mount('#app');
    </script>
</body>
</html>

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists