| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>EventFlow Dashboard</title> |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
| <script src="https://unpkg.com/feather-icons"></script> |
| <script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script> |
| <script> |
| tailwind.config = { |
| theme: { |
| extend: { |
| colors: { |
| primary: '#6366f1', |
| secondary: '#8b5cf6', |
| } |
| } |
| } |
| } |
| </script> |
| <style> |
| .card-shadow { |
| box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); |
| } |
| .event-card { |
| transition: transform 0.2s ease, box-shadow 0.2s ease; |
| } |
| .event-card:hover { |
| transform: translateY(-2px); |
| box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); |
| } |
| .urgent-pulse { |
| animation: pulse 2s infinite; |
| } |
| @keyframes pulse { |
| 0% { |
| box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); |
| } |
| 70% { |
| box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); |
| } |
| 100% { |
| box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); |
| } |
| } |
| .drop-zone { |
| min-height: 200px; |
| transition: all 0.3s ease; |
| } |
| .drop-zone.active { |
| background-color: rgba(199, 210, 254, 0.3); |
| border-color: #6366f1; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-50 min-h-screen font-sans"> |
| <div class="container mx-auto px-4 py-8"> |
| |
| <header class="mb-8"> |
| <div class="flex justify-between items-center"> |
| <h1 class="text-3xl font-bold text-gray-800"> |
| <span class="text-primary">Event</span><span class="text-secondary">Flow</span> |
| </h1> |
| <button id="themeToggle" class="p-2 rounded-full bg-gray-200 hover:bg-gray-300 transition"> |
| <i data-feather="moon" class="text-gray-700"></i> |
| </button> |
| </div> |
| <p class="text-gray-600 mt-2">Keep your team in sync with seamless event management</p> |
| </header> |
|
|
| |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-6"> |
| |
| <div class="lg:col-span-1 bg-white rounded-xl p-6 card-shadow"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Create New Event</h2> |
| <form id="eventForm" class="space-y-4"> |
| <div> |
| <label for="name" class="block text-sm font-medium text-gray-700 mb-1">Your Name</label> |
| <input type="text" id="name" required class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-primary focus:border-primary"> |
| </div> |
| <div> |
| <label for="activity" class="block text-sm font-medium text-gray-700 mb-1">Activity</label> |
| <input type="text" id="activity" required class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-primary focus:border-primary"> |
| </div> |
| <div class="grid grid-cols-2 gap-4"> |
| <div> |
| <label for="date" class="block text-sm font-medium text-gray-700 mb-1">Date</label> |
| <input type="date" id="date" required class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-primary focus:border-primary"> |
| </div> |
| <div> |
| <label for="time" class="block text-sm font-medium text-gray-700 mb-1">Time</label> |
| <input type="time" id="time" required class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-primary focus:border-primary"> |
| </div> |
| </div> |
| <div class="flex items-center"> |
| <input type="checkbox" id="urgent" class="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded"> |
| <label for="urgent" class="ml-2 block text-sm text-gray-700">Mark as urgent</label> |
| </div> |
| <button type="submit" class="w-full bg-primary hover:bg-primary-600 text-white py-2 px-4 rounded-md transition duration-300 flex items-center justify-center"> |
| <i data-feather="plus" class="mr-2"></i> Create Event |
| </button> |
| </form> |
| </div> |
|
|
| |
| <div class="lg:col-span-2"> |
| <div class="bg-white rounded-xl p-6 card-shadow"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-4">Team Event Board</h2> |
| <div class="grid grid-cols-1 md:grid-cols-3 gap-4"> |
| |
| <div class="bg-gray-50 p-4 rounded-lg drop-zone" id="todo"> |
| <div class="flex items-center justify-between mb-3"> |
| <h3 class="font-medium text-gray-700">To Do</h3> |
| <span class="px-2 py-1 bg-gray-200 text-gray-700 rounded-full text-xs">0</span> |
| </div> |
| <div class="space-y-3" id="todo-events"></div> |
| </div> |
|
|
| |
| <div class="bg-gray-50 p-4 rounded-lg drop-zone" id="inprogress"> |
| <div class="flex items-center justify-between mb-3"> |
| <h3 class="font-medium text-gray-700">In Progress</h3> |
| <span class="px-2 py-1 bg-gray-200 text-gray-700 rounded-full text-xs">0</span> |
| </div> |
| <div class="space-y-3" id="inprogress-events"></div> |
| </div> |
|
|
| |
| <div class="bg-gray-50 p-4 rounded-lg drop-zone" id="done"> |
| <div class="flex items-center justify-between mb-3"> |
| <h3 class="font-medium text-gray-700">Done</h3> |
| <span class="px-2 py-1 bg-gray-200 text-gray-700 rounded-full text-xs">0</span> |
| </div> |
| <div class="space-y-3" id="done-events"></div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <template id="eventCardTemplate"> |
| <div class="bg-white p-4 rounded-lg border border-gray-200 cursor-move card-shadow"> |
| <div class="flex justify-between items-start"> |
| <div> |
| <h4 class="font-medium text-gray-800" data-field="activity"></h4> |
| <p class="text-sm text-gray-500 mt-1" data-field="datetime"></p> |
| </div> |
| <span class="urgent-badge px-2 py-1 rounded-full text-xs font-medium hidden">URGENT</span> |
| </div> |
| <div class="mt-2 flex items-center"> |
| <div class="w-6 h-6 rounded-full bg-gray-200 flex items-center justify-center"> |
| <span class="text-xs font-medium text-gray-700" data-field="initials"></span> |
| </div> |
| <span class="ml-2 text-sm text-gray-600" data-field="name"></span> |
| </div> |
| </div> |
| </template> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| feather.replace(); |
| |
| |
| const themeToggle = document.getElementById('themeToggle'); |
| themeToggle.addEventListener('click', function() { |
| document.documentElement.classList.toggle('dark'); |
| const icon = themeToggle.querySelector('i'); |
| if (document.documentElement.classList.contains('dark')) { |
| icon.setAttribute('data-feather', 'sun'); |
| document.body.classList.add('bg-gray-900'); |
| document.body.classList.remove('bg-gray-50'); |
| } else { |
| icon.setAttribute('data-feather', 'moon'); |
| document.body.classList.add('bg-gray-50'); |
| document.body.classList.remove('bg-gray-900'); |
| } |
| feather.replace(); |
| }); |
| |
| |
| const eventForm = document.getElementById('eventForm'); |
| eventForm.addEventListener('submit', function(e) { |
| e.preventDefault(); |
| |
| const name = document.getElementById('name').value; |
| const activity = document.getElementById('activity').value; |
| const date = document.getElementById('date').value; |
| const time = document.getElementById('time').value; |
| const urgent = document.getElementById('urgent').checked; |
| |
| |
| const formattedDate = new Date(date).toLocaleDateString('en-US', { |
| weekday: 'short', month: 'short', day: 'numeric' |
| }); |
| const formattedTime = new Date(`1970-01-01T${time}`).toLocaleTimeString('en-US', { |
| hour: '2-digit', minute: '2-digit', hour12: true |
| }); |
| |
| |
| const template = document.getElementById('eventCardTemplate'); |
| const card = template.content.cloneNode(true); |
| |
| |
| card.querySelector('[data-field="activity"]').textContent = activity; |
| card.querySelector('[data-field="datetime"]').textContent = `${formattedDate} at ${formattedTime}`; |
| card.querySelector('[data-field="name"]').textContent = name; |
| |
| |
| const initials = name.split(' ').map(n => n[0]).join('').toUpperCase(); |
| card.querySelector('[data-field="initials"]').textContent = initials; |
| |
| |
| if (urgent) { |
| const badge = card.querySelector('.urgent-badge'); |
| badge.classList.remove('hidden'); |
| badge.classList.add('bg-red-100', 'text-red-800'); |
| badge.textContent = 'URGENT'; |
| card.querySelector('div').classList.add('urgent-pulse', 'border-red-200'); |
| } |
| |
| const todoEvents = document.getElementById('todo-events'); |
| const eventElement = document.createElement('div'); |
| eventElement.classList.add('event-card'); |
| eventElement.appendChild(card); |
| todoEvents.appendChild(eventElement); |
| |
| |
| new Sortable(eventElement, { |
| group: 'shared', |
| animation: 150, |
| ghostClass: 'bg-blue-50' |
| }); |
| |
| |
| updateColumnCount('todo'); |
| |
| |
| eventForm.reset(); |
| |
| |
| const submitButton = eventForm.querySelector('button[type="submit"]'); |
| const originalText = submitButton.innerHTML; |
| submitButton.innerHTML = '<i data-feather="check" class="mr-2"></i> Event Created!'; |
| feather.replace(); |
| |
| setTimeout(() => { |
| submitButton.innerHTML = originalText; |
| feather.replace(); |
| }, 2000); |
| }); |
| |
| |
| const todoZone = document.getElementById('todo'); |
| const inProgressZone = document.getElementById('inprogress'); |
| const doneZone = document.getElementById('done'); |
| new Sortable(todoZone, { |
| group: 'shared', |
| animation: 150, |
| ghostClass: 'bg-blue-50', |
| filter: '.event-card', |
| onEnd: function() { |
| updateColumnCount('todo'); |
| } |
| }); |
| new Sortable(inProgressZone, { |
| group: 'shared', |
| animation: 150, |
| ghostClass: 'bg-yellow-50', |
| filter: '.event-card', |
| onEnd: function() { |
| updateColumnCount('inprogress'); |
| } |
| }); |
| new Sortable(doneZone, { |
| group: 'shared', |
| animation: 150, |
| ghostClass: 'bg-green-50', |
| filter: '.event-card', |
| onEnd: function() { |
| updateColumnCount('done'); |
| } |
| }); |
| |
| function updateColumnCount(columnId) { |
| const column = document.getElementById(columnId); |
| const countElement = column.querySelector('span'); |
| const eventsContainer = document.getElementById(`${columnId}-events`); |
| const count = eventsContainer.children.length; |
| countElement.textContent = count; |
| } |
| |
| |
| const dropZones = document.querySelectorAll('.drop-zone'); |
| |
| dropZones.forEach(zone => { |
| zone.addEventListener('dragover', function(e) { |
| e.preventDefault(); |
| this.classList.add('active'); |
| }); |
| |
| zone.addEventListener('dragleave', function() { |
| this.classList.remove('active'); |
| }); |
| |
| zone.addEventListener('drop', function() { |
| this.classList.remove('active'); |
| }); |
| }); |
| }); |
| </script> |
| </body> |
| </html> |
|
|