Spaces:
Running
Running
I want to make an professional clock and revision alarm app for students. So jitna jyada achchha ho sake utna bana do - Initial Deployment
2c63486
verified
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>StudySync | Student Clock & Revision Alarms</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> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: '#6366F1', | |
| secondary: '#8B5CF6', | |
| darkbg: '#0F172A', | |
| panelbg: '#1E293B' | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| </head> | |
| <body class="bg-gray-100 dark:bg-darkbg text-gray-900 dark:text-gray-100 min-h-screen transition-colors duration-200"> | |
| <div class="max-w-6xl mx-auto px-4 py-8"> | |
| <!-- Header --> | |
| <header class="flex flex-col md:flex-row justify-between items-center gap-6 mb-10"> | |
| <div class="flex items-center gap-3"> | |
| <div class="bg-primary p-3 rounded-xl"> | |
| <i class="fa-solid fa-clock text-white text-2xl"></i> | |
| </div> | |
| <div> | |
| <h1 class="text-2xl md:text-3xl font-bold">StudySync</h1> | |
| <p class="text-gray-600 dark:text-gray-400">Clock & Revision Alarm System</p> | |
| </div> | |
| </div> | |
| <div class="flex items-center gap-4"> | |
| <button id="theme-toggle" class="bg-gray-200 dark:bg-panelbg p-2 rounded-full"> | |
| <i class="fa-solid fa-sun dark:hidden text-amber-500"></i> | |
| <i class="fa-solid fa-moon hidden dark:block text-indigo-400"></i> | |
| </button> | |
| <div class="flex gap-2"> | |
| <button class="bg-gray-200 dark:bg-panelbg p-2 rounded-lg"> | |
| <i class="fa-solid fa-book text-primary"></i> | |
| </button> | |
| <button class="bg-gray-200 dark:bg-panelbg p-2 rounded-lg"> | |
| <i class="fa-solid fa-gear text-primary"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <div class="grid grid-cols-1 lg:grid-cols-3 gap-8"> | |
| <!-- Left Column - Clock and Alarms --> | |
| <div class="lg:col-span-2"> | |
| <!-- Digital Clock --> | |
| <div class="bg-white dark:bg-panelbg rounded-2xl shadow-lg p-6 mb-8"> | |
| <div class="text-center mb-6"> | |
| <h2 class="text-xl font-semibold text-gray-600 dark:text-gray-300 mb-1">Today is</h2> | |
| <div id="date-display" class="text-lg"></div> | |
| </div> | |
| <div class="flex justify-center"> | |
| <div class="bg-gradient-to-r from-primary to-secondary rounded-xl px-8 py-6 shadow-lg inline-block"> | |
| <div id="digital-clock" class="text-6xl font-bold tracking-wider text-white"></div> | |
| </div> | |
| </div> | |
| <div class="mt-8"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold">Set Revision Alarm</h3> | |
| <span class="text-sm text-gray-500">All times in 24h format</span> | |
| </div> | |
| <div class="bg-gray-50 dark:bg-gray-800 rounded-xl p-4"> | |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-4"> | |
| <div> | |
| <label class="block text-sm font-medium mb-1" for="hour">Hour</label> | |
| <select id="hour" class="w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2"> | |
| <option value="">--</option> | |
| <script> | |
| for (let i = 0; i < 24; i++) { | |
| document.write(`<option value="${i}">${i.toString().padStart(2, '0')}</option>`); | |
| } | |
| </script> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1" for="minute">Minute</label> | |
| <select id="minute" class="w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2"> | |
| <option value="">--</option> | |
| <script> | |
| for (let i = 0; i < 60; i++) { | |
| document.write(`<option value="${i}">${i.toString().padStart(2, '0')}</option>`); | |
| } | |
| </script> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1" for="interval">Repeat</label> | |
| <select id="interval" class="w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2"> | |
| <option value="once">Once</option> | |
| <option value="daily">Daily</option> | |
| <option value="weekdays">Weekdays</option> | |
| <option value="weekends">Weekends</option> | |
| </select> | |
| </div> | |
| <div> | |
| <label class="block text-sm font-medium mb-1" for="subject">Subject</label> | |
| <input id="subject" type="text" placeholder="e.g., Math" class="w-full bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-lg px-3 py-2"> | |
| </div> | |
| </div> | |
| <div class="flex justify-between"> | |
| <button id="test-alarm" class="bg-gray-200 dark:bg-gray-700 hover:bg-gray-300 dark:hover:bg-gray-600 transition py-2 px-4 rounded-lg"> | |
| <i class="fa-solid fa-bell mr-2"></i> Test Sound | |
| </button> | |
| <button id="add-alarm" class="bg-primary hover:bg-indigo-700 text-white py-2 px-6 rounded-lg transition flex items-center"> | |
| <i class="fa-solid fa-plus mr-2"></i> Add Alarm | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Active Alarms --> | |
| <div class="bg-white dark:bg-panelbg rounded-2xl shadow-lg p-6"> | |
| <div class="flex justify-between items-center mb-4"> | |
| <h3 class="text-xl font-bold">Active Revision Alarms</h3> | |
| <span id="active-alarm-count" class="bg-gray-200 dark:bg-gray-700 rounded-full text-sm w-8 h-8 flex items-center justify-center">0</span> | |
| </div> | |
| <div id="alarms-container" class="space-y-4"> | |
| <!-- Alarms will be added here dynamically --> | |
| <div class="flex items-center justify-center p-8 text-gray-500"> | |
| <div class="text-center"> | |
| <i class="fa-solid fa-bell-slash text-3xl mb-2"></i> | |
| <p>No alarms set yet</p> | |
| <p class="text-sm mt-2">Add your first revision reminder!</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Right Column - Statistics & Tips --> | |
| <div> | |
| <!-- Productivity Stats --> | |
| <div class="bg-white dark:bg-panelbg rounded-2xl shadow-lg p-6 mb-8"> | |
| <h3 class="text-xl font-bold mb-6">Today's Focus</h3> | |
| <div class="grid grid-cols-2 gap-4"> | |
| <div class="bg-indigo-50 dark:bg-gray-800 rounded-xl p-4"> | |
| <div class="text-2xl font-bold text-primary mb-1">3h 42m</div> | |
| <div class="text-sm text-gray-600 dark:text-gray-400">Study Time</div> | |
| </div> | |
| <div class="bg-indigo-50 dark:bg-gray-800 rounded-xl p-4"> | |
| <div class="text-2xl font-bold text-primary mb-1">6</div> | |
| <div class="text-sm text-gray-600 dark:text-gray-400">Sessions</div> | |
| </div> | |
| <div class="bg-violet-50 dark:bg-gray-800 rounded-xl p-4"> | |
| <div class="text-2xl font-bold text-secondary mb-1">12</div> | |
| <div class="text-sm text-gray-600 dark:text-gray-400">Alarms</div> | |
| </div> | |
| <div class="bg-violet-50 dark:bg-gray-800 rounded-xl p-4"> | |
| <div class="text-2xl font-bold text-secondary mb-1">83%</div> | |
| <div class="text-sm text-gray-600 dark:text-gray-400">Completion</div> | |
| </div> | |
| </div> | |
| <div class="mt-6"> | |
| <h4 class="font-semibold mb-2">Top Subjects</h4> | |
| <div class="space-y-3"> | |
| <div> | |
| <div class="flex justify-between text-sm mb-1"> | |
| <span>Mathematics</span> | |
| <span>48%</span> | |
| </div> | |
| <div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full"> | |
| <div class="h-2 bg-primary rounded-full" style="width:48%"></div> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="flex justify-between text-sm mb-1"> | |
| <span>Physics</span> | |
| <span>32%</span> | |
| </div> | |
| <div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full"> | |
| <div class="h-2 bg-secondary rounded-full" style="width:32%"></div> | |
| </div> | |
| </div> | |
| <div> | |
| <div class="flex justify-between text-sm mb-1"> | |
| <span>Chemistry</span> | |
| <span>20%</span> | |
| </div> | |
| <div class="h-2 bg-gray-200 dark:bg-gray-700 rounded-full"> | |
| <div class="h-2 bg-purple-500 rounded-full" style="width:20%"></div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Study Tips --> | |
| <div class="bg-gradient-to-br from-primary to-secondary rounded-2xl shadow-lg p-6"> | |
| <div class="text-white mb-4"> | |
| <h3 class="text-xl font-bold mb-1">Revision Tips</h3> | |
| <p class="text-indigo-200 text-sm">Expert advice for effective studying</p> | |
| </div> | |
| <div class="space-y-4"> | |
| <div class="bg-white/20 backdrop-blur-sm rounded-xl p-4"> | |
| <div class="text-white font-medium flex items-center gap-2 mb-1"> | |
| <i class="fa-solid fa-brain"></i> | |
| <span>Spaced Repetition</span> | |
| </div> | |
| <p class="text-indigo-100 text-sm">Review material at increasing intervals to improve long-term retention</p> | |
| </div> | |
| <div class="bg-white/20 backdrop-blur-sm rounded-xl p-4"> | |
| <div class="text-white font-medium flex items-center gap-2 mb-1"> | |
| <i class="fa-solid fa-clock"></i> | |
| <span>Pomodoro Technique</span> | |
| </div> | |
| <p class="text-indigo-100 text-sm">Study for 25 minutes, then take a 5-minute break. Repeat for optimal focus</p> | |
| </div> | |
| <div class="bg-white/20 backdrop-blur-sm rounded-xl p-4"> | |
| <div class="text-white font-medium flex items-center gap-2 mb-1"> | |
| <i class="fa-solid fa-book"></i> | |
| <span>Active Recall</span> | |
| </div> | |
| <p class="text-indigo-100 text-sm">Test yourself instead of passively re-reading material</p> | |
| </div> | |
| </div> | |
| <button class="w-full bg-white hover:bg-gray-100 text-primary mt-4 py-2 rounded-lg font-medium"> | |
| <i class="fa-solid fa-book-open mr-2"></i> View Study Plan | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Alarm Alert Modal --> | |
| <div id="alarm-modal" class="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center hidden"> | |
| <div class="bg-white dark:bg-panelbg rounded-2xl w-full max-w-md mx-4 p-8 text-center transform scale-95 transition-transform duration-300"> | |
| <div class="text-6xl text-primary mb-4"> | |
| <i class="fa-solid fa-bell"></i> | |
| </div> | |
| <h3 class="text-2xl font-bold mb-1">Time to Study!</h3> | |
| <p id="alarm-subject" class="text-xl text-secondary mb-4">Subject Name</p> | |
| <p class="text-gray-600 dark:text-gray-300 mb-6">Your scheduled revision time has started. Begin your study session now!</p> | |
| <button id="close-alarm" class="bg-primary hover:bg-indigo-700 text-white font-medium py-2 px-6 rounded-lg transition"> | |
| I'll start studying now | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Audio for alarm --> | |
| <audio id="alarm-sound" preload="auto"> | |
| <source src="https://assets.mixkit.co/sfx/preview/mixkit-alarm-digital-clock-beep-989.mp3" type="audio/mp3"> | |
| </audio> | |
| <script> | |
| // Elements | |
| const themeToggle = document.getElementById('theme-toggle'); | |
| const digitalClock = document.getElementById('digital-clock'); | |
| const dateDisplay = document.getElementById('date-display'); | |
| const hourSelect = document.getElementById('hour'); | |
| const minuteSelect = document.getElementById('minute'); | |
| const intervalSelect = document.getElementById('interval'); | |
| const subjectInput = document.getElementById('subject'); | |
| const addAlarmBtn = document.getElementById('add-alarm'); | |
| const testAlarmBtn = document.getElementById('test-alarm'); | |
| const alarmsContainer = document.getElementById('alarms-container'); | |
| const activeAlarmCount = document.getElementById('active-alarm-count'); | |
| const alarmModal = document.getElementById('alarm-modal'); | |
| const closeAlarmBtn = document.getElementById('close-alarm'); | |
| const alarmSound = document.getElementById('alarm-sound'); | |
| const alarmSubjectDisplay = document.getElementById('alarm-subject'); | |
| // Theme toggle | |
| themeToggle.addEventListener('click', () => { | |
| document.documentElement.classList.toggle('dark'); | |
| themeToggle.querySelector('.fa-sun').classList.toggle('hidden'); | |
| themeToggle.querySelector('.fa-moon').classList.toggle('hidden'); | |
| // Save theme preference | |
| if (document.documentElement.classList.contains('dark')) { | |
| localStorage.setItem('theme', 'dark'); | |
| } else { | |
| localStorage.setItem('theme', 'light'); | |
| } | |
| }); | |
| // Apply saved theme | |
| if (localStorage.getItem('theme') === 'dark') { | |
| document.documentElement.classList.add('dark'); | |
| themeToggle.querySelector('.fa-sun').classList.add('hidden'); | |
| themeToggle.querySelector('.fa-moon').classList.remove('hidden'); | |
| } else { | |
| document.documentElement.classList.remove('dark'); | |
| themeToggle.querySelector('.fa-sun').classList.remove('hidden'); | |
| themeToggle.querySelector('.fa-moon').classList.add('hidden'); | |
| } | |
| // Update clock and date | |
| function updateTime() { | |
| const now = new Date(); | |
| const timeString = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); | |
| const dateString = now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); | |
| digitalClock.textContent = timeString; | |
| dateDisplay.textContent = dateString; | |
| checkAlarms(now); | |
| } | |
| // Alarm data | |
| let alarms = JSON.parse(localStorage.getItem('alarms')) || []; | |
| let activeAlarms = 0; | |
| // Render alarms | |
| function renderAlarms() { | |
| alarmsContainer.innerHTML = ''; | |
| activeAlarms = 0; | |
| if (alarms.length === 0) { | |
| alarmsContainer.innerHTML = ` | |
| <div class="flex items-center justify-center p-8 text-gray-500"> | |
| <div class="text-center"> | |
| <i class="fa-solid fa-bell-slash text-3xl mb-2"></i> | |
| <p>No alarms set yet</p> | |
| <p class="text-sm mt-2">Add your first revision reminder!</p> | |
| </div> | |
| </div> | |
| `; | |
| } else { | |
| alarms.forEach((alarm, index) => { | |
| const time = new Date(); | |
| time.setHours(alarm.hour, alarm.minute, 0, 0); | |
| const isFuture = time > new Date(); | |
| if (isFuture) activeAlarms++; | |
| const alarmElement = document.createElement('div'); | |
| alarmElement.className = `bg-gray-50 dark:bg-gray-800 rounded-xl p-4 border-l-4 ${isFuture ? 'border-green-500' : 'border-gray-400'}`; | |
| alarmElement.innerHTML = ` | |
| <div class="flex justify-between items-center"> | |
| <div> | |
| <div class="font-bold text-xl">${alarm.hour.toString().padStart(2, '0')}:${alarm.minute.toString().padStart(2, '0')}</div> | |
| <div class="text-sm text-gray-600 dark:text-gray-400 mt-1"> | |
| ${alarm.subject ? alarm.subject : 'General Revision'} | |
| <span class="bg-gray-200 dark:bg-gray-700 text-xs px-2 py-1 rounded-md ml-2"> | |
| ${alarm.interval === 'once' ? 'Once' : | |
| alarm.interval === 'daily' ? 'Daily' : | |
| alarm.interval === 'weekdays' ? 'Mon-Fri' : | |
| 'Weekends'} | |
| </span> | |
| </div> | |
| </div> | |
| <button class="delete-alarm text-red-500 hover:text-red-700 transition" data-index="${index}"> | |
| <i class="fa-solid fa-trash"></i> | |
| </button> | |
| </div> | |
| `; | |
| alarmsContainer.appendChild(alarmElement); | |
| }); | |
| } | |
| activeAlarmCount.textContent = activeAlarms; | |
| localStorage.setItem('alarms', JSON.stringify(alarms)); | |
| } | |
| // Initial render | |
| renderAlarms(); | |
| // Check for active alarms | |
| function checkAlarms(now) { | |
| const currentTime = now.getHours() * 100 + now.getMinutes(); // hhmm as number | |
| alarms.forEach(alarm => { | |
| const alarmTime = alarm.hour * 100 + alarm.minute; | |
| const wasTriggered = alarm.lastTriggered === `${now.getFullYear()}-${now.getMonth()}-${now.getDate()}`; | |
| if (currentTime === alarmTime && !wasTriggered) { | |
| // Check if it should trigger based on interval | |
| const shouldTrigger = | |
| alarm.interval === 'daily' || | |
| (alarm.interval === 'weekdays' && now.getDay() >= 1 && now.getDay() <= 5) || | |
| (alarm.interval === 'weekends' && (now.getDay() === 0 || now.getDay() === 6)) || | |
| alarm.interval === 'once'; | |
| if (shouldTrigger) { | |
| // Trigger alarm | |
| alarmSubjectDisplay.textContent = alarm.subject || 'Study Time'; | |
| alarmModal.classList.remove('hidden'); | |
| document.body.classList.add('overflow-hidden'); | |
| // Play alarm sound | |
| alarmSound.play(); | |
| // Mark as triggered | |
| alarm.lastTriggered = `${now.getFullYear()}-${now.getMonth()}-${now.getDate()}`; | |
| localStorage.setItem('alarms', JSON.stringify(alarms)); | |
| if (alarm.interval === 'once') { | |
| // Remove one-time alarms after triggering | |
| alarms = alarms.filter(a => a !== alarm); | |
| renderAlarms(); | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // Add new alarm | |
| addAlarmBtn.addEventListener('click', () => { | |
| const hour = parseInt(hourSelect.value); | |
| const minute = parseInt(minuteSelect.value); | |
| const interval = intervalSelect.value; | |
| const subject = subjectInput.value.trim(); | |
| if (isNaN(hour) || isNaN(minute)) { | |
| alert('Please select a valid time'); | |
| return; | |
| } | |
| const newAlarm = { | |
| hour, | |
| minute, | |
| interval, | |
| subject: subject || 'Study Time', | |
| lastTriggered: null | |
| }; | |
| alarms.push(newAlarm); | |
| renderAlarms(); | |
| // Reset form | |
| hourSelect.value = ''; | |
| minuteSelect.value = ''; | |
| intervalSelect.value = 'once'; | |
| subjectInput.value = ''; | |
| }); | |
| // Test alarm sound | |
| testAlarmBtn.addEventListener('click', () => { | |
| alarmSound.play(); | |
| }); | |
| // Close alarm modal | |
| closeAlarmBtn.addEventListener('click', () => { | |
| alarmModal.classList.add('hidden'); | |
| document.body.classList.remove('overflow-hidden'); | |
| alarmSound.pause(); | |
| alarmSound.currentTime = 0; | |
| }); | |
| // Delete alarm | |
| document.addEventListener('click', (e) => { | |
| if (e.target.closest('.delete-alarm')) { | |
| const index = e.target.closest('.delete-alarm').dataset.index; | |
| alarms.splice(index, 1); | |
| renderAlarms(); | |
| } | |
| }); | |
| // Initial time update and interval | |
| updateTime(); | |
| setInterval(updateTime, 1000); | |
| </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=A3qualityo/study-scan" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
| </html> |