Jj81support's picture
Manual changes saved
749a846 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tomato Time Tracker Pro - Pomodoro Timer</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
}
.timer-circle {
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
transition: stroke-dashoffset 1s linear;
}
.pulse-animation {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
.slide-in {
animation: slideIn 0.5s ease-out;
}
@keyframes slideIn {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
</style>
</head>
<body class="bg-gradient-to-br from-red-50 to-orange-100 min-h-screen">
<!-- Navigation -->
<nav class="bg-white/80 backdrop-blur-md border-b border-red-100 sticky top-0 z-50">
<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center py-4">
<div class="flex items-center space-x-2">
<div
class="w-8 h-8 bg-gradient-to-r from-red-500 to-orange-500 rounded-full flex items-center justify-center">
<i data-feather="clock" class="text-white w-4 h-4"></i>
</div>
<span class="text-xl font-bold bg-gradient-to-r from-red-600 to-orange-600 bg-clip-text text-transparent">TomatoTime Pro</span>
</div>
<div class="flex space-x-1">
<button id="timerTab" class="px-4 py-2 rounded-lg font-medium transition-all duration-300 bg-red-500 text-white shadow-lg">
<i data-feather="clock" class="w-4 h-4 mr-2 inline"></i>Timer
</button>
<button id="historyTab" class="px-4 py-2 rounded-lg font-medium transition-all duration-300 text-gray-600 hover:bg-red-50">
<i data-feather="archive" class="w-4 h-4 mr-2 inline"></i>History
</button>
</div>
</div>
</div>
</nav>
<!-- Main Content -->
<main class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<!-- Timer Section -->
<section id="timerSection" class="space-y-8">
<!-- Timer Display -->
<div class="bg-white rounded-3xl shadow-2xl p-8 max-w-2xl mx-auto">
<div class="text-center mb-8">
<h2 class="text-3xl font-bold text-gray-800 mb-2">Focus Session</h2>
<p class="text-gray-600">Stay productive with the Pomodoro technique</p>
</div>
<div class="relative flex items-center justify-center mb-8">
<div class="relative">
<svg width="300" height="300" class="transform -rotate-90">
<circle cx="150" cy="150" r="140" stroke="#f3f4f6" stroke-width="8" fill="none" />
<circle id="progressCircle" cx="150" cy="150" r="140" stroke="#ef4444" stroke-width="8"
fill="none" class="timer-circle" stroke-linecap="round" />
</svg>
<div class="absolute inset-0 flex flex-col items-center justify-center">
<div id="timerDisplay" class="text-5xl font-bold text-gray-800 mb-2">25:00</div>
<div id="sessionType" class="text-lg font-medium text-gray-600">Work Session</div>
</div>
</div>
</div>
<!-- Controls -->
<div class="flex justify-center space-x-4 mb-6">
<button id="startBtn" class="bg-green-500 hover:bg-green-600 text-white px-8 py-3 rounded-xl font-semibold transition-all duration-300 transform hover:scale-105 shadow-lg flex items-center">
<i data-feather="play" class="w-5 h-5 mr-2"></i>Start
</button>
<button id="pauseBtn" class="bg-yellow-500 hover:bg-yellow-600 text-white px-8 py-3 rounded-xl font-semibold transition-all duration-300 transform hover:scale-105 shadow-lg flex items-center hidden">
<i data-feather="pause" class="w-5 h-5 mr-2"></i>Pause
</button>
<button id="resetBtn" class="bg-gray-500 hover:bg-gray-600 text-white px-8 py-3 rounded-xl font-semibold transition-all duration-300 transform hover:scale-105 shadow-lg flex items-center">
<i data-feather="refresh-cw" class="w-5 h-5 mr-2"></i>Reset
</button>
</div>
<!-- Session Settings -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 text-center">
<div class="bg-red-50 rounded-xl p-4">
<div class="text-2xl font-bold text-red-600">25</div>
<div class="text-sm text-gray-600">Work Minutes</div>
</div>
<div class="bg-green-50 rounded-xl p-4">
<div class="text-2xl font-bold text-green-600">5</div>
<div class="text-sm text-gray-600">Break Minutes</div>
</div>
<div class="bg-blue-50 rounded-xl p-4">
<div class="text-2xl font-bold text-blue-600">4</div>
<div class="text-sm text-gray-600">Sessions</div>
</div>
</div>
</div>
<!-- Quick Stats -->
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 max-w-2xl mx-auto">
<div class="bg-white rounded-xl p-4 text-center shadow-lg">
<i data-feather="check-circle" class="w-8 h-8 text-green-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-gray-800">0</div>
<div class="text-sm text-gray-600">Completed</div>
</div>
<div class="bg-white rounded-xl p-4 text-center shadow-lg">
<i data-feather="clock" class="w-8 h-8 text-blue-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-gray-800">0</div>
<div class="text-sm text-gray-600">Total Time</div>
</div>
<div class="bg-white rounded-xl p-4 text-center shadow-lg">
<i data-feather="target" class="w-8 h-8 text-purple-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-gray-800">0</div>
<div class="text-sm text-gray-600">Focus Rate</div>
</div>
<div class="bg-white rounded-xl p-4 text-center shadow-lg">
<i data-feather="trending-up" class="w-8 h-8 text-orange-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-gray-800">0</div>
<div class="text-sm text-gray-600">Streak</div>
</div>
</div>
</section>
<!-- History Section -->
<section id="historySection" class="space-y-8 hidden">
<div class="bg-white rounded-3xl shadow-2xl p-8">
<div class="flex justify-between items-center mb-6">
<h2 class="text-3xl font-bold text-gray-800">Session History</h2>
<button class="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded-lg font-medium transition-all duration-300 flex items-center">
<i data-feather="filter" class="w-4 h-4 mr-2"></i>Filter
</button>
</div>
<div id="historyList" class="space-y-4">
<!-- History items will be dynamically added here -->
<div class="text-center py-12 text-gray-500">
<i data-feather="archive" class="w-16 h-16 mx-auto mb-4 opacity-50"></i>
<p>No sessions completed yet. Start your first Pomodoro!</p>
</div>
</div>
</div>
<!-- Statistics -->
<div class="bg-white rounded-3xl shadow-2xl p-8">
<h2 class="text-3xl font-bold text-gray-800 mb-6">Your Progress</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="text-center">
<div class="w-20 h-20 mx-auto mb-4 relative">
<svg width="80" height="80" class="transform -rotate-90">
<circle cx="40" cy="40" r="35" stroke="#f3f4f6" stroke-width="6" fill="none" />
<circle cx="40" cy="40" r="35" stroke="#10b981" stroke-width="6" fill="none"
stroke-dasharray="220" stroke-dashoffset="66" />
</svg>
<div class="absolute inset-0 flex items-center justify-center">
<span class="text-lg font-bold text-gray-800">70%</span>
</div>
</div>
<div class="text-sm text-gray-600">Focus Rate</div>
</div>
<div class="text-center">
<div class="text-4xl font-bold text-red-600 mb-2">12</div>
<div class="text-sm text-gray-600">Sessions Today</div>
</div>
<div class="text-center">
<div class="text-4xl font-bold text-blue-600 mb-2">5h 30m</div>
<div class="text-sm text-gray-600">Total Focus Time</div>
</div>
<div class="text-center">
<div class="text-4xl font-bold text-green-600 mb-2">7</div>
<div class="text-sm text-gray-600">Day Streak</div>
</div>
</div>
</div>
</section>
</main>
<!-- Notification Sound -->
<audio id="notificationSound" preload="auto">
<source src="https://assets.mixkit.co/sfx/preview/mixkit-alarm-digital-clock-beep-989.mp3" type="audio/mpeg">
</audio>
<script>
// Timer functionality
let timer;
let timeLeft = 25 * 60; // 25 minutes in seconds
let isRunning = false;
let isWorkSession = true;
let sessionsCompleted = 0;
const timerDisplay = document.getElementById('timerDisplay');
const progressCircle = document.getElementById('progressCircle');
const sessionType = document.getElementById('sessionType');
const startBtn = document.getElementById('startBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resetBtn = document.getElementById('resetBtn');
const notificationSound = document.getElementById('notificationSound');
// Tab switching
const timerTab = document.getElementById('timerTab');
const historyTab = document.getElementById('historyTab');
const timerSection = document.getElementById('timerSection');
const historySection = document.getElementById('historySection');
function updateDisplay() {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
timerDisplay.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
// Update progress circle
const totalTime = isWorkSession ? 25 * 60 : 5 * 60;
const progress = ((totalTime - timeLeft) / totalTime) * 1000;
progressCircle.style.strokeDashoffset = 1000 - progress;
}
function startTimer() {
if (!isRunning) {
isRunning = true;
startBtn.classList.add('hidden');
pauseBtn.classList.remove('hidden');
timer = setInterval(() => {
timeLeft--;
updateDisplay();
if (timeLeft === 0) {
clearInterval(timer);
isRunning = false;
notificationSound.play();
sessionsCompleted++;
addHistoryItem();
// Switch between work and break sessions
if (isWorkSession) {
isWorkSession = false;
timeLeft = 5 * 60; // 5 minute break
sessionType.textContent = 'Break Time';
progressCircle.style.stroke = '#10b981';
} else {
isWorkSession = true;
timeLeft = 25 * 60; // 25 minute work session
sessionType.textContent = 'Work Session';
progressCircle.style.stroke = '#ef4444';
}
startBtn.classList.remove('hidden');
pauseBtn.classList.add('hidden');
updateDisplay();
}
}, 1000);
}
}
function pauseTimer() {
if (isRunning) {
clearInterval(timer);
isRunning = false;
startBtn.classList.remove('hidden');
pauseBtn.classList.add('hidden');
}
}
function resetTimer() {
clearInterval(timer);
isRunning = false;
isWorkSession = true;
timeLeft = 25 * 60;
sessionType.textContent = 'Work Session';
progressCircle.style.stroke = '#ef4444';
startBtn.classList.remove('hidden');
pauseBtn.classList.add('hidden');
updateDisplay();
}
function addHistoryItem() {
const historyList = document.getElementById('historyList');
const emptyState = historyList.querySelector('.text-center');
if (emptyState) {
emptyState.remove();
}
const now = new Date();
const timeString = now.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
const dateString = now.toLocaleDateString();
const historyItem = document.createElement('div');
historyItem.className = 'bg-gradient-to-r from-red-50 to-orange-50 rounded-xl p-4 border-l-4 border-red-500 slide-in';
historyItem.innerHTML = `
<div class="flex justify-between items-center">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 bg-red-500 rounded-full flex items-center justify-center">
<i data-feather="check" class="text-white w-5 h-5"></i>
</div>
<div>
<div class="font-semibold text-gray-800">${isWorkSession ? 'Break Session' : 'Work Session'}</div>
<div class="text-sm text-gray-600">${dateString} at ${timeString}</div>
</div>
</div>
<div class="text-right">
<div class="font-bold text-gray-800">${isWorkSession ? '5:00' : '25:00'}</div>
<div class="text-sm text-green-600">Completed</div>
</div>
</div>
`;
historyList.insertBefore(historyItem, historyList.firstChild);
feather.replace();
}
// Event listeners
startBtn.addEventListener('click', startTimer);
pauseBtn.addEventListener('click', pauseTimer);
resetBtn.addEventListener('click', resetTimer);
timerTab.addEventListener('click', () => {
timerSection.classList.remove('hidden');
historySection.classList.add('hidden');
timerTab.classList.add('bg-red-500', 'text-white', 'shadow-lg');
timerTab.classList.remove('text-gray-600', 'hover:bg-red-50');
historyTab.classList.remove('bg-red-500', 'text-white', 'shadow-lg');
historyTab.classList.add('text-gray-600', 'hover:bg-red-50');
});
historyTab.addEventListener('click', () => {
historySection.classList.remove('hidden');
timerSection.classList.add('hidden');
historyTab.classList.add('bg-red-500', 'text-white', 'shadow-lg');
historyTab.classList.remove('text-gray-600', 'hover:bg-red-50');
timerTab.classList.remove('bg-red-500', 'text-white', 'shadow-lg');
timerTab.classList.add('text-gray-600', 'hover:bg-red-50');
});
// Initialize
updateDisplay();
feather.replace();
</script>
</body>
</html>