chandelier-events / index.html
privateuserh's picture
Add 3 files
1294605 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Event Management System</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-checkbox:checked {
background-color: #4f46e5;
}
#eventModal {
transition: all 0.3s ease;
}
.month-nav:hover {
background-color: #4f46e5;
color: white;
}
.event-day {
background-color: #e0e7ff;
}
.has-event {
position: relative;
}
.has-event::after {
content: '';
position: absolute;
bottom: 5px;
left: 50%;
transform: translateX(-50%);
width: 6px;
height: 6px;
background-color: #4f46e5;
border-radius: 50%;
}
.floating-btn {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
}
.floating-btn:hover {
transform: translateY(-3px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.event-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
}
</style>
</head>
<body class="bg-gray-50">
<!-- Header -->
<header class="bg-indigo-600 text-white shadow-lg">
<div class="container mx-auto px-4 py-6">
<div class="flex justify-between items-center">
<h1 class="text-2xl md:text-3xl font-bold">Local Event Calendar</h1>
<div class="hidden md:block">
<input type="text" placeholder="Search events..." class="px-4 py-2 rounded-full text-gray-800 focus:outline-none focus:ring-2 focus:ring-indigo-300">
</div>
</div>
<div class="flex mt-4 space-x-4">
<button class="px-4 py-2 rounded-full bg-indigo-700 hover:bg-indigo-800 transition">All Events</button>
<button class="px-4 py-2 rounded-full hover:bg-indigo-700 transition">Music</button>
<button class="px-4 py-2 rounded-full hover:bg-indigo-700 transition">Sports</button>
<button class="px-4 py-2 rounded-full hover:bg-indigo-700 transition">Art</button>
</div>
</div>
</header>
<!-- Main Content -->
<main class="container mx-auto px-4 py-8">
<div class="flex flex-col lg:flex-row gap-8">
<!-- Calendar Section -->
<div class="lg:w-2/3">
<div class="bg-white rounded-lg shadow-md p-6 mb-8">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-bold text-gray-800">Event Calendar</h2>
<div class="flex space-x-2">
<button onclick="previousMonth()" class="month-nav px-3 py-1 rounded-lg bg-indigo-100 text-indigo-600"><i class="fas fa-chevron-left"></i></button>
<h3 id="currentMonthYear" class="px-4 py-1 font-semibold text-gray-700">June 2023</h3>
<button onclick="nextMonth()" class="month-nav px-3 py-1 rounded-lg bg-indigo-100 text-indigo-600"><i class="fas fa-chevron-right"></i></button>
</div>
</div>
<div class="grid grid-cols-7 gap-2 mb-2">
<div class="text-center font-semibold text-gray-500 py-2">Sun</div>
<div class="text-center font-semibold text-gray-500 py-2">Mon</div>
<div class="text-center font-semibold text-gray-500 py-2">Tue</div>
<div class="text-center font-semibold text-gray-500 py-2">Wed</div>
<div class="text-center font-semibold text-gray-500 py-2">Thu</div>
<div class="text-center font-semibold text-gray-500 py-2">Fri</div>
<div class="text-center font-semibold text-gray-500 py-2">Sat</div>
</div>
<div id="calendarDays" class="grid grid-cols-7 gap-2">
<!-- Calendar days will be populated by JavaScript -->
</div>
</div>
<!-- Events List Section -->
<div id="eventsList" class="space-y-4">
<!-- Events will be displayed here -->
</div>
</div>
<!-- Sidebar -->
<div class="lg:w-1/3">
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
<h2 class="text-xl font-bold text-gray-800 mb-4">Featured Venues</h2>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center">
<i class="fas fa-music text-indigo-600"></i>
</div>
<div>
<h3 class="font-semibold">The Jazz Club</h3>
<p class="text-sm text-gray-500">Live music venue</p>
</div>
</div>
<div class="flex items-center space-x-3">
<div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center">
<i class="fas fa-theater-masks text-indigo-600"></i>
</div>
<div>
<h3 class="font-semibold">City Theater</h3>
<p class="text-sm text-gray-500">Drama & plays</p>
</div>
</div>
<div class="flex items-center space-x-3">
<div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center">
<i class="fas fa-futbol text-indigo-600"></i>
</div>
<div>
<h3 class="font-semibold">Sports Arena</h3>
<p class="text-sm text-gray-500">Athletic events</p>
</div>
</div>
</div>
</div>
<div class="bg-white rounded-lg shadow-md p-6">
<h2 class="text-xl font-bold text-gray-800 mb-4">Recently Added</h2>
<div id="recentEvents" class="space-y-4">
<!-- Recent events will be shown here -->
</div>
</div>
</div>
</div>
</main>
<!-- Floating Add Event Button -->
<div id="addEventBtn" class="fixed bottom-6 right-6 bg-indigo-600 text-white rounded-full w-16 h-16 flex items-center justify-center cursor-pointer shadow-lg floating-btn z-50">
<i class="fas fa-plus text-2xl"></i>
</div>
<!-- Event Form Modal -->
<div id="eventModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-lg shadow-xl w-full max-w-md mx-4">
<div class="flex justify-between items-center border-b px-6 py-4">
<h3 class="text-lg font-semibold text-gray-800">Add New Event</h3>
<button id="closeModal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="p-6">
<form id="eventForm" class="space-y-4">
<div>
<label for="eventName" class="block text-sm font-medium text-gray-700 mb-1">Event Name</label>
<input type="text" id="eventName" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" required>
</div>
<div>
<label for="artistName" class="block text-sm font-medium text-gray-700 mb-1">Performer/Artist</label>
<input type="text" id="artistName" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" required>
</div>
<div>
<label for="eventDate" class="block text-sm font-medium text-gray-700 mb-1">Date & Time</label>
<input type="datetime-local" id="eventDate" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" required>
</div>
<div>
<label for="venueName" class="block text-sm font-medium text-gray-700 mb-1">Venue Name</label>
<input type="text" id="venueName" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" required>
</div>
<div>
<label for="ticketPrice" class="block text-sm font-medium text-gray-700 mb-1">Ticket Price ($)</label>
<input type="number" id="ticketPrice" min="0" step="0.01" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div>
<label for="eventUrl" class="block text-sm font-medium text-gray-700 mb-1">Event Website URL</label>
<input type="url" id="eventUrl" class="w-full px-4 py-2 border rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
</div>
<div class="flex items-center space-x-4">
<div class="flex items-center">
<input type="radio" id="statusActive" name="eventStatus" value="active" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500" checked>
<label for="statusActive" class="ml-2 block text-sm text-gray-700">Active</label>
</div>
<div class="flex items-center">
<input type="radio" id="statusCancelled" name="eventStatus" value="cancelled" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
<label for="statusCancelled" class="ml-2 block text-sm text-gray-700">Cancelled</label>
</div>
</div>
<div class="flex justify-end space-x-3 pt-4">
<button type="button" id="cancelBtn" class="px-4 py-2 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50">Cancel</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">Add Event</button>
</div>
</form>
</div>
</div>
</div>
<script>
// Sample events data
let events = [
{
id: 1,
name: "Jazz Night with Sarah Smith",
artist: "Sarah Smith Quartet",
date: "2023-06-15T20:00:00",
venue: "The Jazz Club",
price: 25.00,
status: "active",
url: "https://thejazzclub.com/events"
},
{
id: 2,
name: "Rock Festival 2023",
artist: "Various Artists",
date: "2023-06-22T15:00:00",
venue: "City Park",
price: 45.00,
status: "active",
url: "https://rockfest.city"
},
{
id: 3,
name: "Modern Art Exhibition",
artist: "Contemporary Artists",
date: "2023-06-10T10:00:00",
venue: "City Art Gallery",
price: 12.50,
status: "active",
url: "https://cityartgallery.net"
},
{
id: 4,
name: "Cancelled: Summer Poetry Slam",
artist: "Local Poets",
date: "2023-06-08T19:30:00",
venue: "Downtown Books",
price: 10.00,
status: "cancelled",
url: "https://dtbooks.com/events"
}
];
// DOM elements
const calendarDays = document.getElementById('calendarDays');
const currentMonthYear = document.getElementById('currentMonthYear');
const eventsList = document.getElementById('eventsList');
const recentEvents = document.getElementById('recentEvents');
const addEventBtn = document.getElementById('addEventBtn');
const eventModal = document.getElementById('eventModal');
const closeModal = document.getElementById('closeModal');
const cancelBtn = document.getElementById('cancelBtn');
const eventForm = document.getElementById('eventForm');
// Calendar variables
let currentDate = new Date();
let currentMonth = currentDate.getMonth();
let currentYear = currentDate.getFullYear();
// Initialize app
document.addEventListener('DOMContentLoaded', () => {
renderCalendar();
displayEvents();
displayRecentEvents();
// Event listeners
addEventBtn.addEventListener('click', () => {
eventModal.classList.remove('hidden');
});
closeModal.addEventListener('click', () => {
eventModal.classList.add('hidden');
});
cancelBtn.addEventListener('click', () => {
eventModal.classList.add('hidden');
});
eventForm.addEventListener('submit', addNewEvent);
});
// Render calendar
function renderCalendar() {
// Clear previous calendar
calendarDays.innerHTML = '';
// Set month and year display
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
currentMonthYear.textContent = `${monthNames[currentMonth]} ${currentYear}`;
// Get first day of month and total days
const firstDay = new Date(currentYear, currentMonth, 1).getDay();
const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
// Get days from previous month
const daysInPrevMonth = new Date(currentYear, currentMonth, 0).getDate();
// Get days from next month
const totalCells = Math.ceil((daysInMonth + firstDay) / 7) * 7;
const daysFromNextMonth = totalCells - (daysInMonth + firstDay);
// Previous month days
for (let i = 0; i < firstDay; i++) {
const day = daysInPrevMonth - firstDay + i + 1;
const dayElement = document.createElement('div');
dayElement.className = 'text-center py-2 text-gray-400';
dayElement.textContent = day;
calendarDays.appendChild(dayElement);
}
// Current month days
for (let i = 1; i <= daysInMonth; i++) {
const dayElement = document.createElement('div');
dayElement.className = 'text-center py-2 cursor-pointer rounded-lg';
// Check if this is today
const today = new Date();
if (currentYear === today.getFullYear() && currentMonth === today.getMonth() && i === today.getDate()) {
dayElement.classList.add('bg-indigo-100', 'font-semibold', 'text-indigo-700');
}
// Check if there are events on this day
const hasEvent = events.some(event => {
const eventDate = new Date(event.date);
return eventDate.getFullYear() === currentYear &&
eventDate.getMonth() === currentMonth &&
eventDate.getDate() === i;
});
if (hasEvent) {
dayElement.classList.add('has-event', 'event-day', 'hover:bg-indigo-200');
} else {
dayElement.classList.add('hover:bg-gray-100');
}
dayElement.textContent = i;
dayElement.dataset.day = i;
dayElement.dataset.month = currentMonth;
dayElement.dataset.year = currentYear;
dayElement.addEventListener('click', () => {
showEventsForDay(i, currentMonth, currentYear);
});
calendarDays.appendChild(dayElement);
}
// Next month days
for (let i = 1; i <= daysFromNextMonth; i++) {
const dayElement = document.createElement('div');
dayElement.className = 'text-center py-2 text-gray-400';
dayElement.textContent = i;
calendarDays.appendChild(dayElement);
}
}
// Navigate to previous month
function previousMonth() {
currentMonth--;
if (currentMonth < 0) {
currentMonth = 11;
currentYear--;
}
renderCalendar();
displayEvents(); // Update events display for the new month
}
// Navigate to next month
function nextMonth() {
currentMonth++;
if (currentMonth > 11) {
currentMonth = 0;
currentYear++;
}
renderCalendar();
displayEvents(); // Update events display for the new month
}
// Display all events for current month
function displayEvents() {
eventsList.innerHTML = '';
const filteredEvents = events.filter(event => {
const eventDate = new Date(event.date);
return eventDate.getFullYear() === currentYear && eventDate.getMonth() === currentMonth;
});
if (filteredEvents.length === 0) {
eventsList.innerHTML = '<p class="text-gray-500 text-center py-4">No events scheduled for this month.</p>';
return;
}
// Sort events by date
filteredEvents.sort((a, b) => new Date(a.date) - new Date(b.date));
filteredEvents.forEach(event => {
const eventCard = createEventCard(event);
eventsList.appendChild(eventCard);
});
}
// Show events for a specific day
function showEventsForDay(day, month, year) {
eventsList.innerHTML = '';
const filteredEvents = events.filter(event => {
const eventDate = new Date(event.date);
return eventDate.getFullYear() == year &&
eventDate.getMonth() == month &&
eventDate.getDate() == day;
});
if (filteredEvents.length === 0) {
const date = new Date(year, month, day);
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
eventsList.innerHTML = `
<div class="bg-white rounded-lg shadow-md p-6 text-center">
<h3 class="text-xl font-semibold text-gray-800 mb-2">No Events Scheduled</h3>
<p class="text-gray-500">${date.toLocaleDateString('en-US', options)}</p>
</div>
`;
return;
}
filteredEvents.forEach(event => {
const eventCard = createEventCard(event);
eventsList.appendChild(eventCard);
});
}
// Display recent events in sidebar
function displayRecentEvents() {
recentEvents.innerHTML = '';
const now = new Date();
const recent = events.filter(event => {
const eventDate = new Date(event.date);
return eventDate > now && event.status === 'active';
}).sort((a, b) => new Date(a.date) - new Date(b.date));
const maxRecent = 3;
const displayCount = Math.min(recent.length, maxRecent);
if (displayCount === 0) {
recentEvents.innerHTML = '<p class="text-gray-500">No upcoming events</p>';
return;
}
for (let i = 0; i < displayCount; i++) {
const eventCard = document.createElement('div');
eventCard.className = 'bg-gray-50 rounded-lg p-4 event-card transition cursor-pointer';
const eventDate = new Date(recent[i].date);
const options = { month: 'short', day: 'numeric' };
eventCard.innerHTML = `
<div class="flex justify-between items-start">
<div>
<h3 class="font-semibold text-gray-800">${recent[i].name}</h3>
<p class="text-sm text-indigo-600">${recent[i].artist}</p>
</div>
<div class="bg-indigo-100 text-indigo-800 text-xs font-medium px-2 py-1 rounded-lg">
${eventDate.toLocaleDateString('en-US', options)}
</div>
</div>
<div class="mt-2 text-sm text-gray-600">
<p>${recent[i].venue} • $${recent[i].price.toFixed(2)}</p>
</div>
`;
eventCard.addEventListener('click', () => {
// Scroll to the event in the main list
const eventElement = document.querySelector(`[data-event-id="${recent[i].id}"]`);
if (eventElement) {
eventElement.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
eventElement.classList.add('ring-2', 'ring-indigo-500');
setTimeout(() => {
eventElement.classList.remove('ring-2', 'ring-indigo-500');
}, 2000);
}
});
recentEvents.appendChild(eventCard);
}
}
// Create event card element
function createEventCard(event) {
const eventDate = new Date(event.date);
const eventDay = eventDate.getDate();
const eventMonth = eventDate.toLocaleString('default', { month: 'short' });
const eventTime = eventDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const fullDate = eventDate.toLocaleString('en-US', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' });
const eventCard = document.createElement('div');
eventCard.className = `bg-white rounded-lg shadow-md overflow-hidden event-card transition ${event.status === 'cancelled' ? 'opacity-70' : ''}`;
eventCard.dataset.eventId = event.id;
eventCard.innerHTML = `
<div class="p-6">
<div class="flex items-start justify-between">
<div class="flex items-start space-x-4">
<div class="bg-indigo-100 text-indigo-800 p-3 rounded-lg text-center">
<div class="font-bold text-xl">${eventDay}</div>
<div class="text-sm uppercase">${eventMonth}</div>
</div>
<div>
<h3 class="text-xl font-bold text-gray-800 ${event.status === 'cancelled' ? 'line-through' : ''}">${event.name}</h3>
<p class="text-indigo-600">${event.artist}</p>
<p class="text-gray-500 text-sm mt-1">${fullDate} at ${eventTime}</p>
<div class="flex items-center mt-2 space-x-4">
<span class="text-gray-700">${event.venue}</span>
<span class="text-gray-700">$${event.price.toFixed(2)}</span>
${event.status === 'cancelled' ?
'<span class="bg-red-100 text-red-800 text-xs font-medium px-2 py-0.5 rounded">Cancelled</span>' :
'<span class="bg-green-100 text-green-800 text-xs font-medium px-2 py-0.5 rounded">Active</span>'}
</div>
${event.url ? `<a href="${event.url}" target="_blank" class="inline-block mt-3 text-sm text-indigo-600 hover:underline">More info & tickets →</a>` : ''}
</div>
</div>
</div>
</div>
`;
return eventCard;
}
// Add new event
function addNewEvent(e) {
e.preventDefault();
// Get form values
const eventName = document.getElementById('eventName').value;
const artistName = document.getElementById('artistName').value;
const eventDate = document.getElementById('eventDate').value;
const venueName = document.getElementById('venueName').value;
const ticketPrice = parseFloat(document.getElementById('ticketPrice').value) || 0;
const eventUrl = document.getElementById('eventUrl').value;
const eventStatus = document.querySelector('input[name="eventStatus"]:checked').value;
// Create new event object
const newEvent = {
id: events.length > 0 ? Math.max(...events.map(e => e.id)) + 1 : 1,
name: eventName,
artist: artistName,
date: eventDate,
venue: venueName,
price: ticketPrice,
status: eventStatus,
url: eventUrl
};
// Add to events array
events.push(newEvent);
// Reset form and close modal
eventForm.reset();
eventModal.classList.add('hidden');
// Update UI
renderCalendar();
displayEvents();
displayRecentEvents();
// For demo purposes, show success message
alert('Event added successfully!');
}
</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=privateuserh/chandelier-events" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>