tunk / index.html
Dataio's picture
Una web para una discoteca,/salon de conciertos. Nombre "new Tunk ", espacio para el logo, publicacion de eventos, venta de ntradas, reservacion de mesas. Funcionalidad que pueda darse de baja/alta los eventos y la configuracion de mesas. - Initial Deployment
d3d6b27 verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Tunk - Club & Concert Venue</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">
<style>
/* Custom CSS for elements that need more specific styling */
.event-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
}
.table-selected {
box-shadow: 0 0 0 3px #f59e0b;
}
.admin-panel {
transition: all 0.3s ease;
}
.admin-panel.hidden {
transform: translateX(100%);
opacity: 0;
}
.logo-text {
font-family: 'Impact', sans-serif;
text-shadow: 3px 3px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen">
<!-- Admin Login Button (Fixed) -->
<button id="adminToggle" class="fixed top-4 right-4 bg-purple-800 hover:bg-purple-700 text-white px-4 py-2 rounded-full z-50 shadow-lg">
<i class="fas fa-lock mr-2"></i>Admin
</button>
<!-- Admin Panel -->
<div id="adminPanel" class="admin-panel hidden fixed top-0 right-0 h-full w-full md:w-1/3 bg-gray-800 z-40 p-6 overflow-y-auto shadow-2xl">
<div class="flex justify-between items-center mb-8">
<h2 class="text-2xl font-bold">Admin Panel</h2>
<button id="closeAdmin" class="text-gray-400 hover:text-white">
<i class="fas fa-times text-2xl"></i>
</button>
</div>
<div class="mb-8">
<h3 class="text-xl font-semibold mb-4 border-b border-gray-700 pb-2">Manage Events</h3>
<div class="space-y-4">
<div class="bg-gray-700 p-4 rounded-lg">
<h4 class="font-medium mb-2">Add New Event</h4>
<div class="space-y-3">
<input type="text" id="eventTitle" placeholder="Event Title" class="w-full bg-gray-600 rounded px-3 py-2">
<input type="date" id="eventDate" class="w-full bg-gray-600 rounded px-3 py-2">
<input type="time" id="eventTime" class="w-full bg-gray-600 rounded px-3 py-2">
<textarea id="eventDescription" placeholder="Description" class="w-full bg-gray-600 rounded px-3 py-2"></textarea>
<input type="number" id="eventPrice" placeholder="Ticket Price" class="w-full bg-gray-600 rounded px-3 py-2">
<input type="text" id="eventImage" placeholder="Image URL" class="w-full bg-gray-600 rounded px-3 py-2">
<button id="addEvent" class="w-full bg-green-600 hover:bg-green-700 py-2 rounded font-medium">
<i class="fas fa-plus mr-2"></i>Add Event
</button>
</div>
</div>
<div class="bg-gray-700 p-4 rounded-lg">
<h4 class="font-medium mb-2">Current Events</h4>
<div id="adminEventsList" class="space-y-3">
<!-- Events will be added here dynamically -->
</div>
</div>
</div>
</div>
<div>
<h3 class="text-xl font-semibold mb-4 border-b border-gray-700 pb-2">Table Configuration</h3>
<div class="grid grid-cols-2 gap-4 mb-4">
<div>
<label class="block mb-1">Table Rows</label>
<input type="number" id="tableRows" min="1" max="10" value="4" class="w-full bg-gray-600 rounded px-3 py-2">
</div>
<div>
<label class="block mb-1">Tables per Row</label>
<input type="number" id="tablesPerRow" min="1" max="10" value="6" class="w-full bg-gray-600 rounded px-3 py-2">
</div>
</div>
<button id="updateTableLayout" class="w-full bg-blue-600 hover:bg-blue-700 py-2 rounded font-medium mb-6">
<i class="fas fa-sync-alt mr-2"></i>Update Layout
</button>
<div class="bg-gray-700 p-4 rounded-lg">
<h4 class="font-medium mb-2">Current Reservations</h4>
<div id="reservationsList" class="space-y-3">
<!-- Reservations will be added here dynamically -->
</div>
</div>
</div>
</div>
<!-- Main Content -->
<div class="container mx-auto px-4">
<!-- Header with Logo -->
<header class="py-8 text-center">
<div class="logo-container inline-block relative">
<div class="absolute -inset-4 bg-purple-600 rounded-full blur-md opacity-30 animate-pulse"></div>
<h1 class="logo-text text-6xl md:text-8xl font-bold text-purple-400 relative z-10">NEW TUNK</h1>
</div>
<p class="mt-4 text-xl text-purple-200">Club & Concert Venue</p>
</header>
<!-- Navigation -->
<nav class="flex justify-center mb-12">
<div class="flex space-x-1 bg-gray-800 rounded-full p-1">
<button class="nav-link px-6 py-2 rounded-full font-medium active" data-section="events">
<i class="fas fa-calendar-alt mr-2"></i>Events
</button>
<button class="nav-link px-6 py-2 rounded-full font-medium" data-section="tickets">
<i class="fas fa-ticket-alt mr-2"></i>Tickets
</button>
<button class="nav-link px-6 py-2 rounded-full font-medium" data-section="reservations">
<i class="fas fa-utensils mr-2"></i>Reservations
</button>
<button class="nav-link px-6 py-2 rounded-full font-medium" data-section="about">
<i class="fas fa-info-circle mr-2"></i>About
</button>
</div>
</nav>
<!-- Main Sections -->
<main>
<!-- Events Section -->
<section id="events-section" class="section-content py-8">
<h2 class="text-3xl font-bold mb-8 text-center">Upcoming Events</h2>
<div id="eventsContainer" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- Events will be loaded here dynamically -->
<div class="text-center py-12">
<div class="animate-spin inline-block text-purple-500 text-4xl mb-4">
<i class="fas fa-compact-disc"></i>
</div>
<p>Loading events...</p>
</div>
</div>
</section>
<!-- Tickets Section -->
<section id="tickets-section" class="section-content py-8 hidden">
<h2 class="text-3xl font-bold mb-8 text-center">Buy Tickets</h2>
<div id="ticketsContainer" class="max-w-2xl mx-auto">
<div class="bg-gray-800 rounded-lg p-6 mb-6">
<p class="text-center text-gray-400">Select an event to purchase tickets</p>
</div>
</div>
</section>
<!-- Reservations Section -->
<section id="reservations-section" class="section-content py-8 hidden">
<h2 class="text-3xl font-bold mb-8 text-center">Table Reservations</h2>
<div class="max-w-4xl mx-auto">
<div class="bg-gray-800 rounded-lg p-6 mb-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h3 class="text-xl font-semibold mb-4">Available Tables</h3>
<div id="tableLayout" class="grid grid-cols-6 gap-2 mb-4">
<!-- Tables will be generated here dynamically -->
</div>
<div class="text-sm text-gray-400">
<p>Click on a table to select it for reservation</p>
</div>
</div>
<div>
<h3 class="text-xl font-semibold mb-4">Reservation Details</h3>
<div class="space-y-4">
<div>
<label class="block mb-1">Selected Table</label>
<input type="text" id="selectedTable" readonly class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<div>
<label class="block mb-1">Event</label>
<select id="reservationEvent" class="w-full bg-gray-700 rounded px-3 py-2">
<option value="">Select an event</option>
</select>
</div>
<div>
<label class="block mb-1">Name</label>
<input type="text" id="reservationName" class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<div>
<label class="block mb-1">Email</label>
<input type="email" id="reservationEmail" class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<div>
<label class="block mb-1">Phone</label>
<input type="tel" id="reservationPhone" class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<div>
<label class="block mb-1">Number of Guests</label>
<input type="number" id="reservationGuests" min="1" max="10" value="2" class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<button id="submitReservation" class="w-full bg-purple-600 hover:bg-purple-700 py-2 rounded font-medium">
<i class="fas fa-check mr-2"></i>Confirm Reservation
</button>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- About Section -->
<section id="about-section" class="section-content py-8 hidden">
<h2 class="text-3xl font-bold mb-8 text-center">About New Tunk</h2>
<div class="max-w-3xl mx-auto">
<div class="bg-gray-800 rounded-lg p-6 mb-6">
<div class="flex flex-col md:flex-row gap-6">
<div class="md:w-1/3">
<div class="bg-purple-900 aspect-square rounded-lg mb-4 flex items-center justify-center">
<i class="fas fa-music text-6xl text-purple-400"></i>
</div>
</div>
<div class="md:w-2/3">
<h3 class="text-xl font-semibold mb-4">The Ultimate Nightlife Experience</h3>
<p class="mb-4">New Tunk is the premier destination for music lovers and party-goers alike. With state-of-the-art sound systems, stunning light shows, and an electric atmosphere, we bring you unforgettable nights.</p>
<p class="mb-4">Our venue hosts world-class DJs, live bands, and special events throughout the year. Whether you're looking to dance the night away or enjoy cocktails with friends, New Tunk has something for everyone.</p>
<div class="flex space-x-4 mt-6">
<a href="#" class="text-purple-400 hover:text-purple-300">
<i class="fab fa-facebook-f text-2xl"></i>
</a>
<a href="#" class="text-purple-400 hover:text-purple-300">
<i class="fab fa-instagram text-2xl"></i>
</a>
<a href="#" class="text-purple-400 hover:text-purple-300">
<i class="fab fa-twitter text-2xl"></i>
</a>
</div>
</div>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-gray-800 rounded-lg p-6">
<h3 class="text-xl font-semibold mb-4 flex items-center">
<i class="fas fa-clock mr-3 text-purple-400"></i>Opening Hours
</h3>
<ul class="space-y-2">
<li class="flex justify-between border-b border-gray-700 pb-2">
<span>Monday - Thursday</span>
<span>6PM - 2AM</span>
</li>
<li class="flex justify-between border-b border-gray-700 pb-2">
<span>Friday - Saturday</span>
<span>8PM - 4AM</span>
</li>
<li class="flex justify-between">
<span>Sunday</span>
<span>Closed</span>
</li>
</ul>
</div>
<div class="bg-gray-800 rounded-lg p-6">
<h3 class="text-xl font-semibold mb-4 flex items-center">
<i class="fas fa-map-marker-alt mr-3 text-purple-400"></i>Location
</h3>
<p class="mb-4">123 Music Avenue<br>Nightlife District<br>City, ST 12345</p>
<button class="bg-purple-600 hover:bg-purple-700 px-4 py-2 rounded font-medium">
<i class="fas fa-directions mr-2"></i>Get Directions
</button>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer class="py-12 mt-12 border-t border-gray-800">
<div class="text-center">
<div class="logo-container inline-block mb-6">
<h2 class="logo-text text-4xl font-bold text-purple-400">NEW TUNK</h2>
</div>
<p class="text-gray-400 mb-6">© 2023 New Tunk. All rights reserved.</p>
<div class="flex justify-center space-x-6">
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-instagram"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-twitter"></i>
</a>
<a href="#" class="text-gray-400 hover:text-white">
<i class="fab fa-soundcloud"></i>
</a>
</div>
</div>
</footer>
</div>
<!-- Event Modal -->
<div id="eventModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden">
<div class="bg-gray-800 rounded-lg max-w-2xl w-full mx-4 max-h-[90vh] overflow-y-auto">
<div class="p-6">
<div class="flex justify-between items-start mb-4">
<div>
<h2 id="modalEventTitle" class="text-2xl font-bold"></h2>
<p id="modalEventDate" class="text-purple-400"></p>
</div>
<button id="closeModal" class="text-gray-400 hover:text-white">
<i class="fas fa-times text-2xl"></i>
</button>
</div>
<div class="mb-6">
<div id="modalEventImage" class="w-full h-48 md:h-64 bg-gray-700 rounded-lg mb-4 flex items-center justify-center">
<i class="fas fa-music text-5xl text-gray-500"></i>
</div>
<p id="modalEventDescription" class="mb-4"></p>
<div class="flex items-center">
<span class="bg-purple-600 text-white px-3 py-1 rounded-full text-sm font-medium">
<i class="fas fa-ticket-alt mr-1"></i> <span id="modalEventPrice"></span>
</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<button id="buyTicketsBtn" class="bg-green-600 hover:bg-green-700 py-3 rounded font-medium">
<i class="fas fa-ticket-alt mr-2"></i>Buy Tickets
</button>
<button id="reserveTableBtn" class="bg-purple-600 hover:bg-purple-700 py-3 rounded font-medium">
<i class="fas fa-utensils mr-2"></i>Reserve Table
</button>
</div>
</div>
</div>
</div>
<!-- Ticket Purchase Modal -->
<div id="ticketModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden">
<div class="bg-gray-800 rounded-lg max-w-md w-full mx-4">
<div class="p-6">
<div class="flex justify-between items-start mb-4">
<div>
<h2 class="text-2xl font-bold">Ticket Purchase</h2>
<p id="ticketEventTitle" class="text-purple-400"></p>
</div>
<button id="closeTicketModal" class="text-gray-400 hover:text-white">
<i class="fas fa-times text-2xl"></i>
</button>
</div>
<div class="space-y-4 mb-6">
<div>
<label class="block mb-1">Quantity</label>
<div class="flex items-center">
<button id="decrementTicket" class="bg-gray-700 px-3 py-2 rounded-l">
<i class="fas fa-minus"></i>
</button>
<input type="number" id="ticketQuantity" min="1" value="1" class="bg-gray-700 w-16 text-center py-2">
<button id="incrementTicket" class="bg-gray-700 px-3 py-2 rounded-r">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
<div>
<label class="block mb-1">Name</label>
<input type="text" id="ticketName" class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<div>
<label class="block mb-1">Email</label>
<input type="email" id="ticketEmail" class="w-full bg-gray-700 rounded px-3 py-2">
</div>
<div class="pt-4 border-t border-gray-700">
<div class="flex justify-between mb-2">
<span>Tickets (<span id="ticketQtyDisplay">1</span>x)</span>
<span id="ticketUnitPrice"></span>
</div>
<div class="flex justify-between font-bold text-lg">
<span>Total</span>
<span id="ticketTotalPrice"></span>
</div>
</div>
</div>
<button id="confirmPurchase" class="w-full bg-green-600 hover:bg-green-700 py-3 rounded font-medium">
<i class="fas fa-credit-card mr-2"></i>Confirm Purchase
</button>
</div>
</div>
</div>
<!-- Confirmation Modal -->
<div id="confirmationModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 hidden">
<div class="bg-gray-800 rounded-lg max-w-md w-full mx-4">
<div class="p-6 text-center">
<div class="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="fas fa-check text-2xl text-white"></i>
</div>
<h2 id="confirmationTitle" class="text-2xl font-bold mb-2"></h2>
<p id="confirmationMessage" class="mb-6"></p>
<button id="closeConfirmation" class="bg-purple-600 hover:bg-purple-700 px-6 py-2 rounded font-medium">
Close
</button>
</div>
</div>
</div>
<script>
// Sample data for events
let events = [
{
id: 1,
title: "Electronic Night",
date: "2023-12-15",
time: "22:00",
description: "Experience the best electronic music with our resident DJs and special guests. A night of non-stop beats and incredible light show.",
price: 25,
image: "https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
active: true
},
{
id: 2,
title: "Live Rock Band",
date: "2023-12-22",
time: "21:00",
description: "The legendary rock band 'Midnight Riders' performs live with all their greatest hits. Don't miss this exclusive show!",
price: 40,
image: "https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
active: true
},
{
id: 3,
title: "Hip Hop Festival",
date: "2024-01-05",
time: "20:00",
description: "A full night of hip hop with performances from top artists, DJ battles, and breakdance competitions.",
price: 30,
image: "https://images.unsplash.com/photo-1514525253161-7a46d19cd819?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80",
active: true
}
];
let reservations = [];
let selectedEvent = null;
let selectedTable = null;
let tableRows = 4;
let tablesPerRow = 6;
// DOM Elements
const adminPanel = document.getElementById('adminPanel');
const adminToggle = document.getElementById('adminToggle');
const closeAdmin = document.getElementById('closeAdmin');
const navLinks = document.querySelectorAll('.nav-link');
const sectionContents = document.querySelectorAll('.section-content');
const eventsContainer = document.getElementById('eventsContainer');
const ticketsContainer = document.getElementById('ticketsContainer');
const tableLayout = document.getElementById('tableLayout');
const reservationEvent = document.getElementById('reservationEvent');
const selectedTableInput = document.getElementById('selectedTable');
const submitReservation = document.getElementById('submitReservation');
const eventModal = document.getElementById('eventModal');
const closeModal = document.getElementById('closeModal');
const modalEventTitle = document.getElementById('modalEventTitle');
const modalEventDate = document.getElementById('modalEventDate');
const modalEventDescription = document.getElementById('modalEventDescription');
const modalEventPrice = document.getElementById('modalEventPrice');
const modalEventImage = document.getElementById('modalEventImage');
const buyTicketsBtn = document.getElementById('buyTicketsBtn');
const reserveTableBtn = document.getElementById('reserveTableBtn');
const ticketModal = document.getElementById('ticketModal');
const closeTicketModal = document.getElementById('closeTicketModal');
const ticketEventTitle = document.getElementById('ticketEventTitle');
const ticketQuantity = document.getElementById('ticketQuantity');
const decrementTicket = document.getElementById('decrementTicket');
const incrementTicket = document.getElementById('incrementTicket');
const ticketQtyDisplay = document.getElementById('ticketQtyDisplay');
const ticketUnitPrice = document.getElementById('ticketUnitPrice');
const ticketTotalPrice = document.getElementById('ticketTotalPrice');
const confirmPurchase = document.getElementById('confirmPurchase');
const confirmationModal = document.getElementById('confirmationModal');
const confirmationTitle = document.getElementById('confirmationTitle');
const confirmationMessage = document.getElementById('confirmationMessage');
const closeConfirmation = document.getElementById('closeConfirmation');
const adminEventsList = document.getElementById('adminEventsList');
const reservationsList = document.getElementById('reservationsList');
const addEvent = document.getElementById('addEvent');
const eventTitle = document.getElementById('eventTitle');
const eventDate = document.getElementById('eventDate');
const eventTime = document.getElementById('eventTime');
const eventDescription = document.getElementById('eventDescription');
const eventPrice = document.getElementById('eventPrice');
const eventImage = document.getElementById('eventImage');
const tableRowsInput = document.getElementById('tableRows');
const tablesPerRowInput = document.getElementById('tablesPerRow');
const updateTableLayout = document.getElementById('updateTableLayout');
// Initialize the page
document.addEventListener('DOMContentLoaded', function() {
renderEvents();
generateTableLayout();
setupAdminPanel();
// Set today's date as min date for event date picker
const today = new Date().toISOString().split('T')[0];
eventDate.min = today;
});
// Navigation
navLinks.forEach(link => {
link.addEventListener('click', function() {
// Remove active class from all links
navLinks.forEach(l => l.classList.remove('active'));
// Add active class to clicked link
this.classList.add('active');
// Hide all sections
sectionContents.forEach(section => section.classList.add('hidden'));
// Show selected section
const sectionId = this.getAttribute('data-section');
document.getElementById(`${sectionId}-section`).classList.remove('hidden');
});
});
// Admin Panel Toggle
adminToggle.addEventListener('click', function() {
adminPanel.classList.toggle('hidden');
});
closeAdmin.addEventListener('click', function() {
adminPanel.classList.add('hidden');
});
// Render events
function renderEvents() {
eventsContainer.innerHTML = '';
const activeEvents = events.filter(event => event.active);
if (activeEvents.length === 0) {
eventsContainer.innerHTML = `
<div class="col-span-full text-center py-12">
<i class="fas fa-calendar-times text-4xl text-gray-500 mb-4"></i>
<p>No upcoming events scheduled. Check back soon!</p>
</div>
`;
return;
}
activeEvents.forEach(event => {
const eventDate = new Date(`${event.date}T${event.time}`);
const options = { weekday: 'long', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' };
const formattedDate = eventDate.toLocaleDateString('en-US', options);
const eventCard = document.createElement('div');
eventCard.className = 'event-card bg-gray-800 rounded-lg overflow-hidden transition-all duration-300 cursor-pointer';
eventCard.innerHTML = `
<div class="h-48 overflow-hidden">
<img src="${event.image}" alt="${event.title}" class="w-full h-full object-cover">
</div>
<div class="p-6">
<h3 class="text-xl font-bold mb-2">${event.title}</h3>
<p class="text-purple-400 mb-3">${formattedDate}</p>
<p class="text-gray-400 mb-4 line-clamp-2">${event.description}</p>
<div class="flex justify-between items-center">
<span class="bg-purple-600 text-white px-3 py-1 rounded-full text-sm font-medium">
$${event.price}
</span>
<button class="text-white hover:text-purple-300 font-medium">
More info <i class="fas fa-arrow-right ml-1"></i>
</button>
</div>
</div>
`;
eventCard.addEventListener('click', () => openEventModal(event));
eventsContainer.appendChild(eventCard);
});
// Update reservation event dropdown
updateReservationEventDropdown();
}
// Open event modal
function openEventModal(event) {
selectedEvent = event;
const eventDate = new Date(`${event.date}T${event.time}`);
const options = { weekday: 'long', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' };
const formattedDate = eventDate.toLocaleDateString('en-US', options);
modalEventTitle.textContent = event.title;
modalEventDate.textContent = formattedDate;
modalEventDescription.textContent = event.description;
modalEventPrice.textContent = `$${event.price}`;
// Set event image
modalEventImage.innerHTML = '';
const img = document.createElement('img');
img.src = event.image;
img.alt = event.title;
img.className = 'w-full h-full object-cover rounded-lg';
modalEventImage.appendChild(img);
eventModal.classList.remove('hidden');
document.body.style.overflow = 'hidden';
}
// Close event modal
closeModal.addEventListener('click', function() {
eventModal.classList.add('hidden');
document.body.style.overflow = '';
});
// Buy tickets button
buyTicketsBtn.addEventListener('click', function() {
eventModal.classList.add('hidden');
openTicketModal();
});
// Reserve table button
reserveTableBtn.addEventListener('click', function() {
eventModal.classList.add('hidden');
// Switch to reservations section
navLinks.forEach(l => l.classList.remove('active'));
document.querySelector('.nav-link[data-section="reservations"]').classList.add('active');
sectionContents.forEach(section => section.classList.add('hidden'));
document.getElementById('reservations-section').classList.remove('hidden');
// Set the selected event in the dropdown
reservationEvent.value = selectedEvent.id;
// Scroll to top
window.scrollTo(0, 0);
});
// Open ticket modal
function openTicketModal() {
ticketEventTitle.textContent = selectedEvent.title;
ticketUnitPrice.textContent = `$${selectedEvent.price}`;
updateTicketTotal();
ticketModal.classList.remove('hidden');
document.body.style.overflow = 'hidden';
}
// Close ticket modal
closeTicketModal.addEventListener('click', function() {
ticketModal.classList.add('hidden');
document.body.style.overflow = '';
});
// Ticket quantity controls
decrementTicket.addEventListener('click', function() {
if (ticketQuantity.value > 1) {
ticketQuantity.value--;
updateTicketDisplay();
}
});
incrementTicket.addEventListener('click', function() {
ticketQuantity.value++;
updateTicketDisplay();
});
ticketQuantity.addEventListener('change', function() {
if (this.value < 1) this.value = 1;
updateTicketDisplay();
});
function updateTicketDisplay() {
ticketQtyDisplay.textContent = ticketQuantity.value;
updateTicketTotal();
}
function updateTicketTotal() {
const total = selectedEvent.price * ticketQuantity.value;
ticketTotalPrice.textContent = `$${total.toFixed(2)}`;
}
// Confirm purchase
confirmPurchase.addEventListener('click', function() {
const name = document.getElementById('ticketName').value;
const email = document.getElementById('ticketEmail').value;
if (!name || !email) {
showConfirmation('Error', 'Please fill in all required fields.', false);
return;
}
// In a real app, you would process payment here
ticketModal.classList.add('hidden');
showConfirmation('Purchase Complete!', `Your tickets for ${selectedEvent.title} have been reserved. A confirmation has been sent to ${email}.`, true);
// Reset form
ticketQuantity.value = 1;
document.getElementById('ticketName').value = '';
document.getElementById('ticketEmail').value = '';
updateTicketDisplay();
});
// Table layout generation
function generateTableLayout() {
tableLayout.innerHTML = '';
const totalTables = tableRows * tablesPerRow;
for (let i = 1; i <= totalTables; i++) {
const table = document.createElement('div');
table.className = 'bg-gray-700 rounded-lg aspect-square flex items-center justify-center cursor-pointer hover:bg-gray-600 transition-colors';
table.innerHTML = `
<div class="text-center">
<i class="fas fa-utensils text-xl mb-1"></i>
<div>Table ${i}</div>
</div>
`;
table.addEventListener('click', () => selectTable(i));
// Check if table is reserved for any event
const isReserved = reservations.some(r => r.table === i &&
events.some(e => e.id === r.eventId && e.active));
if (isReserved) {
table.classList.add('bg-red-900', 'hover:bg-red-800');
table.classList.remove('bg-gray-700', 'hover:bg-gray-600');
}
tableLayout.appendChild(table);
}
}
// Select table
function selectTable(tableNumber) {
// Check if table is already reserved for any active event
const isReserved = reservations.some(r => r.table === tableNumber &&
events.some(e => e.id === r.eventId && e.active));
if (isReserved) {
showConfirmation('Table Reserved', `Table ${tableNumber} is already reserved for an event. Please choose another table.`, false);
return;
}
// Remove selected class from all tables
document.querySelectorAll('#tableLayout > div').forEach(t => {
t.classList.remove('table-selected');
});
// Add selected class to clicked table
const selectedTableElement = document.querySelector(`#tableLayout > div:nth-child(${tableNumber})`);
selectedTableElement.classList.add('table-selected');
selectedTable = tableNumber;
selectedTableInput.value = `Table ${tableNumber}`;
}
// Submit reservation
submitReservation.addEventListener('click', function() {
const eventId = parseInt(reservationEvent.value);
const name = document.getElementById('reservationName').value;
const email = document.getElementById('reservationEmail').value;
const phone = document.getElementById('reservationPhone').value;
const guests = document.getElementById('reservationGuests').value;
if (!eventId || !name || !email || !selectedTable) {
showConfirmation('Error', 'Please fill in all required fields and select a table.', false);
return;
}
// Create reservation
const reservation = {
id: Date.now(),
eventId: eventId,
table: selectedTable,
name: name,
email: email,
phone: phone,
guests: guests,
date: new Date().toISOString()
};
reservations.push(reservation);
// Show confirmation
const event = events.find(e => e.id === eventId);
showConfirmation('Reservation Confirmed!', `Your table at ${event.title} has been reserved. A confirmation has been sent to ${email}.`, true);
// Reset form
selectedTable = null;
selectedTableInput.value = '';
document.getElementById('reservationName').value = '';
document.getElementById('reservationEmail').value = '';
document.getElementById('reservationPhone').value = '';
document.getElementById('reservationGuests').value = '2';
// Update table layout to show reserved tables
generateTableLayout();
// Update admin panel reservations list
updateAdminReservationsList();
});
// Show confirmation modal
function showConfirmation(title, message, isSuccess) {
confirmationTitle.textContent = title;
confirmationMessage.textContent = message;
const icon = document.querySelector('#confirmationModal .w-16');
icon.className = `w-16 h-16 rounded-full flex items-center justify-center mx-auto mb-4 ${isSuccess ? 'bg-green-500' : 'bg-red-500'}`;
icon.innerHTML = isSuccess ? '<i class="fas fa-check text-2xl text-white"></i>' : '<i class="fas fa-times text-2xl text-white"></i>';
confirmationModal.classList.remove('hidden');
document.body.style.overflow = 'hidden';
}
// Close confirmation modal
closeConfirmation.addEventListener('click', function() {
confirmationModal.classList.add('hidden');
document.body.style.overflow = '';
});
// Update reservation event dropdown
function updateReservationEventDropdown() {
reservationEvent.innerHTML = '<option value="">Select an event</option>';
const activeEvents = events.filter(event => event.active);
activeEvents.forEach(event => {
const option = document.createElement('option');
option.value = event.id;
option.textContent = event.title;
reservationEvent.appendChild(option);
});
// Also update the dropdown in the tickets section
const ticketsEventDropdown = document.createElement('select');
ticketsEventDropdown.className = 'w-full bg-gray-700 rounded px-3 py-2 mb-4';
ticketsEventDropdown.innerHTML = '<option value="">Select an event to purchase tickets</option>';
activeEvents.forEach(event => {
const option = document.createElement('option');
option.value = event.id;
option.textContent = `${event.title} - $${event.price}`;
ticketsEventDropdown.appendChild(option);
});
ticketsEventDropdown.addEventListener('change', function() {
const selectedId = parseInt(this.value);
if (selectedId) {
const event = events.find(e => e.id === selectedId);
selectedEvent = event;
openTicketModal();
}
});
ticketsContainer.innerHTML = '';
ticketsContainer.appendChild(ticketsEventDropdown);
}
// Admin Panel Setup
function setupAdminPanel() {
// Initialize table configuration inputs
tableRowsInput.value = tableRows;
tablesPerRowInput.value = tablesPerRow;
// Update table layout when configuration changes
updateTableLayout.addEventListener('click', function() {
tableRows = parseInt(tableRowsInput.value);
tablesPerRow = parseInt(tablesPerRowInput.value);
generateTableLayout();
});
// Add new event
addEvent.addEventListener('click', function() {
const title = eventTitle.value.trim();
const date = eventDate.value;
const time = eventTime.value;
const description = eventDescription.value.trim();
const price = parseFloat(eventPrice.value);
const image = eventImage.value.trim();
if (!title || !date || !time || !description || isNaN(price) || !image) {
alert('Please fill in all fields with valid data');
return;
}
const newEvent = {
id: Date.now(),
title: title,
date: date,
time: time,
description: description,
price: price,
image: image,
active: true
};
events.push(newEvent);
renderEvents();
updateAdminEventsList();
// Reset form
eventTitle.value = '';
eventDate.value = '';
eventTime.value = '';
eventDescription.value = '';
eventPrice.value = '';
eventImage.value = '';
});
// Initialize admin lists
updateAdminEventsList();
updateAdminReservationsList();
}
// Update admin events list
function updateAdminEventsList() {
adminEventsList.innerHTML = '';
events.forEach(event => {
const eventElement = document.createElement('div');
eventElement.className = 'bg-gray-700 p-3 rounded flex justify-between items-center';
eventElement.innerHTML = `
<div>
<h4 class="font-medium">${event.title}</h4>
<p class="text-sm text-gray-400">${event.date} at ${event.time}</p>
</div>
<div class="flex space-x-2">
<button class="toggle-event px-3 py-1 rounded text-sm ${event.active ? 'bg-green-600 hover:bg-green-700' : 'bg-gray-600 hover:bg-gray-500'}" data-id="${event.id}">
${event.active ? 'Active' : 'Inactive'}
</button>
<button class="delete-event px-3 py-1 rounded text-sm bg-red-600 hover:bg-red-700" data-id="${event.id}">
<i class="fas fa-trash"></i>
</button>
</div>
`;
adminEventsList.appendChild(eventElement);
});
// Add event listeners to toggle buttons
document.querySelectorAll('.toggle-event').forEach(button => {
button.addEventListener('click', function() {
const eventId = parseInt(this.getAttribute('data-id'));
const event = events.find(e => e.id === eventId);
if (event) {
event.active = !event.active;
updateAdminEventsList();
renderEvents();
}
});
});
// Add event listeners to delete buttons
document.querySelectorAll('.delete-event').forEach(button => {
button.addEventListener('click', function() {
if (confirm('Are you sure you want to delete this event?')) {
const eventId = parseInt(this.getAttribute('data-id'));
events = events.filter(e => e.id !== eventId);
updateAdminEventsList();
renderEvents();
}
});
});
}
// Update admin reservations list
function updateAdminReservationsList() {
reservationsList.innerHTML = '';
if (reservations.length === 0) {
reservationsList.innerHTML = '<p class="text-gray-400 text-center py-4">No reservations yet</p>';
return;
}
// Sort by most recent first
const sortedReservations = [...reservations].sort((a, b) => new Date(b.date) - new Date(a.date));
sortedReservations.forEach(reservation => {
const event = events.find(e => e.id === reservation.eventId);
if (!event) return;
const reservationElement = document.createElement('div');
reservationElement.className = 'bg-gray-700 p-3 rounded';
reservationElement.innerHTML = `
<div class="flex justify-between items-start mb-2">
<h4 class="font-medium">${event.title}</h4>
<button class="delete-reservation text-red-400 hover:text-red-300 text-sm" data-id="${reservation.id}">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="grid grid-cols-2 gap-2 text-sm">
<div>
<span class="text-gray-400">Table:</span>
<span>${reservation.table}</span>
</div>
<div>
<span class="text-gray-400">Guests:</span>
<span>${reservation.guests}</span>
</div>
<div>
<span class="text-gray-400">Name:</span>
<span>${reservation.name}</span>
</div>
<div>
<span class="text-gray-400">Contact:</span>
<span>${reservation.email}</span>
</div>
<div class="col-span-2 text-xs text-gray-500">
Reserved on: ${new Date(reservation.date).toLocaleString()}
</div>
</div>
`;
reservationsList.appendChild(reservationElement);
});
// Add event listeners to delete buttons
document.querySelectorAll('.delete-reservation').forEach(button => {
button.addEventListener('click', function() {
if (confirm('Are you sure you want to delete this reservation?')) {
const reservationId = parseInt(this.getAttribute('data-id'));
reservations = reservations.filter(r => r.id !== reservationId);
updateAdminReservationsList();
generateTableLayout();
}
});
});
}
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Dataio/tunk" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>