study-scan / index.html
A3qualityo's picture
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
<!DOCTYPE html>
<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>