ppspace / index.html
prempatel's picture
Add 1 files
f84d1ae verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Taskly - Smart To-Do List</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary-color: #5e72e4;
--primary-dark: #3f51b5;
--accent-color: #ff4081;
--text-primary: #2d3748;
--text-secondary: #4a5568;
--bg-color: #f8f9fa;
--card-bg: #ffffff;
--border-color: #e2e8f0;
--success-color: #48bb78;
--warning-color: #ed8936;
--danger-color: #f56565;
--low-priority: #4299e1;
--medium-priority: #ed8936;
--high-priority: #f56565;
}
[data-theme="dark"] {
--primary-color: #667eea;
--primary-dark: #5a67d8;
--text-primary: #f7fafc;
--text-secondary: #cbd5e0;
--bg-color: #1a202c;
--card-bg: #2d3748;
--border-color: #4a5568;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background-color: var(--bg-color);
color: var(--text-primary);
transition: all 0.3s ease;
}
.container {
max-width: 100%;
width: 100%;
height: 100vh;
max-height: 100vh;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* Header Styles */
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
background-color: var(--primary-color);
color: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
z-index: 100;
}
.logo {
display: flex;
align-items: center;
gap: 0.5rem;
font-weight: 700;
font-size: 1.2rem;
}
.logo i {
font-size: 1.4rem;
}
.header-actions {
display: flex;
gap: 1rem;
align-items: center;
}
.theme-toggle, .user-avatar {
width: 35px;
height: 35px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(255, 255, 255, 0.2);
cursor: pointer;
border: none;
color: white;
font-size: 1rem;
}
.user-avatar {
background-color: white;
color: var(--primary-color);
font-weight: bold;
}
/* Main Content */
.main-content {
flex: 1;
padding: 1rem;
overflow-y: auto;
padding-bottom: 80px;
}
/* Date Section */
.date-section {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.current-date h2 {
font-size: 1.5rem;
font-weight: 600;
}
.current-date p {
color: var(--text-secondary);
font-size: 0.9rem;
}
.calendar-btn {
background-color: var(--card-bg);
border: 1px solid var(--border-color);
padding: 0.7rem;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
/* Stats Section */
.stats-section {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
}
.stat-card {
flex: 1;
background-color: var(--card-bg);
border-radius: 12px;
padding: 1rem;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
}
.stat-icon {
width: 40px;
height: 40px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 0.5rem;
}
.completed .stat-icon {
background-color: rgba(73, 187, 120, 0.1);
color: var(--success-color);
}
.pending .stat-icon {
background-color: rgba(237, 137, 54, 0.1);
color: var(--warning-color);
}
.overdue .stat-icon {
background-color: rgba(245, 101, 101, 0.1);
color: var(--danger-color);
}
.stat-card h3 {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 0.3rem;
text-align: center;
}
.stat-card p {
font-size: 0.8rem;
color: var(--text-secondary);
text-align: center;
}
/* Add Task Section */
.add-task-container {
position: fixed;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
width: calc(100% - 2rem);
z-index: 50;
}
.add-task-btn {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 1rem;
background-color: var(--primary-color);
border: none;
border-radius: 12px;
color: white;
font-size: 1rem;
cursor: pointer;
box-shadow: 0 4px 12px rgba(94, 114, 228, 0.3);
font-weight: 600;
}
/* Task List */
.tasks-container {
margin-bottom: 1rem;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.section-header h3 {
font-size: 1.1rem;
font-weight: 600;
}
.section-header span {
background-color: var(--border-color);
color: var(--text-secondary);
padding: 0.2rem 0.5rem;
border-radius: 10px;
font-size: 0.8rem;
}
.task-list {
display: flex;
flex-direction: column;
gap: 0.8rem;
}
.task-item {
background-color: var(--card-bg);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 1rem;
display: flex;
align-items: center;
gap: 1rem;
transition: all 0.2s ease;
position: relative;
overflow: hidden;
}
.task-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
}
.task-checkbox {
width: 20px;
height: 20px;
border-radius: 6px;
border: 2px solid var(--border-color);
appearance: none;
cursor: pointer;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
}
.task-checkbox:checked {
background-color: var(--primary-color);
border-color: var(--primary-color);
}
.task-checkbox:checked::after {
content: "\f00c";
font-family: "Font Awesome 6 Free";
font-weight: 900;
color: white;
font-size: 0.7rem;
}
.task-content {
flex: 1;
overflow: hidden;
}
.task-title {
font-weight: 600;
margin-bottom: 0.2rem;
position: relative;
}
.task-title.completed {
text-decoration: line-through;
color: var(--text-secondary);
}
.task-details {
display: flex;
align-items: center;
gap: 0.7rem;
margin-top: 0.4rem;
}
.task-detail {
display: flex;
align-items: center;
gap: 0.3rem;
font-size: 0.8rem;
color: var(--text-secondary);
}
.task-detail i {
font-size: 0.8rem;
}
.task-priority {
width: 10px;
height: 10px;
border-radius: 50%;
display: inline-block;
}
.priority-low {
background-color: var(--low-priority);
}
.priority-medium {
background-color: var(--medium-priority);
}
.priority-high {
background-color: var(--high-priority);
}
.task-actions {
display: flex;
gap: 0.5rem;
align-items: center;
}
.task-action-btn {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 1rem;
transition: all 0.2s ease;
}
.task-action-btn:hover {
color: var(--primary-color);
}
/* Bottom Navigation */
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: var(--card-bg);
display: flex;
justify-content: space-around;
padding: 0.8rem 0;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
z-index: 100;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.2rem;
color: var(--text-secondary);
text-decoration: none;
font-size: 0.9rem;
}
.nav-item.active {
color: var(--primary-color);
}
.nav-item i {
font-size: 1.2rem;
}
/* Task Modal */
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 200;
opacity: 0;
pointer-events: none;
transition: all 0.3s ease;
}
.modal.active {
opacity: 1;
pointer-events: all;
}
.modal-content {
background-color: var(--card-bg);
width: 90%;
max-width: 500px;
border-radius: 16px;
padding: 1.5rem;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
transform: translateY(20px);
transition: all 0.3s ease;
max-height: 90vh;
overflow-y: auto;
}
.modal.active .modal-content {
transform: translateY(0);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.modal-title {
font-size: 1.3rem;
font-weight: 600;
}
.modal-close {
background: none;
border: none;
font-size: 1.5rem;
color: var(--text-secondary);
cursor: pointer;
}
.form-group {
margin-bottom: 1.2rem;
}
.form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
.form-control {
width: 100%;
padding: 0.8rem;
border: 1px solid var(--border-color);
border-radius: 10px;
background-color: var(--card-bg);
color: var(--text-primary);
font-size: 1rem;
}
.form-control:focus {
outline: none;
border-color: var(--primary-color);
}
.priority-buttons {
display: flex;
gap: 0.5rem;
}
.priority-btn {
flex: 1;
padding: 0.5rem;
border-radius: 8px;
border: 1px solid var(--border-color);
background-color: transparent;
display: flex;
align-items: center;
justify-content: center;
gap: 0.3rem;
cursor: pointer;
font-size: 0.9rem;
color: var(--text-secondary);
}
.priority-btn.active {
border-color: var(--primary-color);
color: var(--primary-color);
background-color: rgba(94, 114, 228, 0.1);
}
.priority-dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.category-tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.category-tag {
padding: 0.3rem 0.8rem;
border-radius: 20px;
font-size: 0.8rem;
background-color: var(--border-color);
color: var(--text-secondary);
border: none;
cursor: pointer;
}
.category-tag.active {
background-color: var(--primary-color);
color: white;
}
.date-time-row {
display: flex;
gap: 0.8rem;
}
.date-time-row .form-group {
flex: 1;
}
.input-with-icon {
position: relative;
}
.input-with-icon i {
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
color: var(--text-secondary);
}
.modal-footer {
display: flex;
gap: 1rem;
margin-top: 1.5rem;
}
.btn {
padding: 0.8rem 1.5rem;
border-radius: 10px;
font-weight: 500;
cursor: pointer;
font-size: 1rem;
border: none;
}
.btn-primary {
background-color: var(--primary-color);
color: white;
flex: 1;
}
.btn-outline {
background-color: transparent;
border: 1px solid var(--border-color);
color: var(--text-primary);
}
/* Animation */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.task-item {
animation: fadeIn 0.3s ease forwards;
}
/* Responsive */
@media (min-width: 768px) {
.container {
max-width: 500px;
margin: 0 auto;
height: 90vh;
max-height: 900px;
margin-top: 5vh;
border-radius: 16px;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.bottom-nav {
width: 500px;
left: 50%;
transform: translateX(-50%);
border-bottom-left-radius: 16px;
border-bottom-right-radius: 16px;
}
.add-task-container {
width: 460px;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<div class="logo">
<i class="fas fa-tasks"></i>
<span>Taskly</span>
</div>
<div class="header-actions">
<button class="theme-toggle" id="themeToggle">
<i class="fas fa-moon"></i>
</button>
<button class="user-avatar">JS</button>
</div>
</header>
<main class="main-content">
<section class="date-section">
<div class="current-date">
<h2 id="currentDate">Today, June 15</h2>
<p id="currentTodos">You have 5 tasks to complete</p>
</div>
<button class="calendar-btn">
<i class="fas fa-calendar-alt"></i>
</button>
</section>
<section class="stats-section">
<div class="stat-card completed">
<div class="stat-icon">
<i class="fas fa-check"></i>
</div>
<h3>12</h3>
<p>Completed</p>
</div>
<div class="stat-card pending">
<div class="stat-icon">
<i class="fas fa-clock"></i>
</div>
<h3>5</h3>
<p>Pending</p>
</div>
<div class="stat-card overdue">
<div class="stat-icon">
<i class="fas fa-exclamation"></i>
</div>
<h3>2</h3>
<p>Overdue</p>
</div>
</section>
<section class="tasks-container">
<div class="section-header">
<h3>Today's Tasks</h3>
<span>5 tasks</span>
</div>
<div class="task-list" id="todayTasks">
<!-- Today's tasks will be added here by JavaScript -->
</div>
</section>
<section class="tasks-container">
<div class="section-header">
<h3>Upcoming</h3>
<span>3 tasks</span>
</div>
<div class="task-list" id="upcomingTasks">
<!-- Upcoming tasks will be added here by JavaScript -->
</div>
</section>
</main>
<div class="add-task-container">
<button class="add-task-btn" id="addTaskBtn">
<i class="fas fa-plus"></i>
<span>Add Task</span>
</button>
</div>
<nav class="bottom-nav">
<a href="#" class="nav-item active">
<i class="fas fa-home"></i>
<span>Home</span>
</a>
<a href="#" class="nav-item">
<i class="fas fa-calendar"></i>
<span>Calendar</span>
</a>
<a href="#" class="nav-item">
<i class="fas fa-chart-pie"></i>
<span>Stats</span>
</a>
<a href="#" class="nav-item">
<i class="fas fa-cog"></i>
<span>Settings</span>
</a>
</nav>
</div>
<!-- Add Task Modal -->
<div class="modal" id="taskModal">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title">Add New Task</h2>
<button class="modal-close" id="closeModal">&times;</button>
</div>
<form id="taskForm">
<div class="form-group">
<label for="taskTitle">Task Title</label>
<input type="text" id="taskTitle" class="form-control" placeholder="Enter task title" required>
</div>
<div class="form-group">
<label for="taskDescription">Description</label>
<textarea id="taskDescription" class="form-control" rows="3" placeholder="Enter task description (optional)"></textarea>
</div>
<div class="form-group">
<label>Priority</label>
<div class="priority-buttons">
<button type="button" class="priority-btn" data-priority="low">
<span class="priority-dot priority-low"></span>
Low
</button>
<button type="button" class="priority-btn active" data-priority="medium">
<span class="priority-dot priority-medium"></span>
Medium
</button>
<button type="button" class="priority-btn" data-priority="high">
<span class="priority-dot priority-high"></span>
High
</button>
</div>
</div>
<div class="form-group">
<label>Category</label>
<div class="category-tags">
<button type="button" class="category-tag active" data-category="personal">Personal</button>
<button type="button" class="category-tag" data-category="work">Work</button>
<button type="button" class="category-tag" data-category="shopping">Shopping</button>
<button type="button" class="category-tag" data-category="health">Health</button>
<button type="button" class="category-tag" data-category="other">Other</button>
</div>
</div>
<div class="form-group">
<div class="date-time-row">
<div class="form-group">
<label for="taskDate">Date</label>
<div class="input-with-icon">
<input type="date" id="taskDate" class="form-control" required>
<i class="fas fa-calendar"></i>
</div>
</div>
<div class="form-group">
<label for="taskTime">Time</label>
<div class="input-with-icon">
<input type="time" id="taskTime" class="form-control">
<i class="fas fa-clock"></i>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" id="cancelTask">Cancel</button>
<button type="submit" class="btn btn-primary">Add Task</button>
</div>
</form>
</div>
</div>
<script>
// Sample tasks data
const tasks = [
{
id: 1,
title: "Complete project presentation",
description: "Finish slides and rehearse presentation",
completed: false,
priority: "high",
category: "work",
date: new Date(),
time: "15:00"
},
{
id: 2,
title: "Buy groceries",
description: "Milk, eggs, bread, fruits",
completed: false,
priority: "medium",
category: "shopping",
date: new Date(),
time: null
},
{
id: 3,
title: "Morning workout",
description: "30 minutes of cardio",
completed: true,
priority: "low",
category: "health",
date: new Date(),
time: "07:00"
},
{
id: 4,
title: "Call mom",
description: "Wish her happy birthday",
completed: false,
priority: "medium",
category: "personal",
date: new Date(),
time: "18:00"
},
{
id: 5,
title: "Read 20 pages",
description: "Current book: Atomic Habits",
completed: false,
priority: "low",
category: "personal",
date: new Date(),
time: null
},
{
id: 6,
title: "Team meeting",
description: "Discuss Q3 goals",
completed: false,
priority: "high",
category: "work",
date: new Date(new Date().getTime() + 86400000),
time: "10:30"
},
{
id: 7,
title: "Dentist appointment",
description: "Annual checkup",
completed: false,
priority: "medium",
category: "health",
date: new Date(new Date().getTime() + 2 * 86400000),
time: "14:15"
}
];
// DOM Elements
const themeToggle = document.getElementById('themeToggle');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskModal = document.getElementById('taskModal');
const closeModal = document.getElementById('closeModal');
const cancelTask = document.getElementById('cancelTask');
const taskForm = document.getElementById('taskForm');
const todayTasksContainer = document.getElementById('todayTasks');
const upcomingTasksContainer = document.getElementById('upcomingTasks');
const currentDateElement = document.getElementById('currentDate');
const currentTodosElement = document.getElementById('currentTodos');
const priorityButtons = document.querySelectorAll('.priority-btn');
const categoryButtons = document.querySelectorAll('.category-tag');
// Current date formatting
const options = { weekday: 'long', month: 'long', day: 'numeric' };
const today = new Date();
currentDateElement.textContent = today.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' });
// Filter tasks for today and upcoming
const todayTasks = tasks.filter(task => {
return task.date.toDateString() === today.toDateString();
});
const upcomingTasks = tasks.filter(task => {
return task.date > today && task.date.toDateString() !== today.toDateString();
});
// Update task count
currentTodosElement.textContent = `You have ${todayTasks.length} tasks to complete`;
// Theme toggle
themeToggle.addEventListener('click', () => {
document.body.setAttribute('data-theme',
document.body.getAttribute('data-theme') === 'dark' ? 'light' : 'dark');
const icon = themeToggle.querySelector('i');
if (document.body.getAttribute('data-theme') === 'dark') {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
} else {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
}
});
// Modal controls
addTaskBtn.addEventListener('click', () => {
taskModal.classList.add('active');
document.getElementById('taskTitle').focus();
});
closeModal.addEventListener('click', () => {
taskModal.classList.remove('active');
});
cancelTask.addEventListener('click', () => {
taskModal.classList.remove('active');
});
// Close modal when clicking outside
taskModal.addEventListener('click', (e) => {
if (e.target === taskModal) {
taskModal.classList.remove('active');
}
});
// Priority buttons
priorityButtons.forEach(button => {
button.addEventListener('click', () => {
priorityButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
});
});
// Category buttons
categoryButtons.forEach(button => {
button.addEventListener('click', () => {
categoryButtons.forEach(btn => btn.classList.remove('active'));
button.classList.add('active');
});
});
// Render tasks
function renderTasks() {
// Clear containers
todayTasksContainer.innerHTML = '';
upcomingTasksContainer.innerHTML = '';
// Render today's tasks
todayTasks.forEach(task => {
const taskElement = createTaskElement(task);
todayTasksContainer.appendChild(taskElement);
});
// Render upcoming tasks
upcomingTasks.forEach(task => {
const taskElement = createTaskElement(task);
upcomingTasksContainer.appendChild(taskElement);
});
// Add event listeners to checkboxes
document.querySelectorAll('.task-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', function() {
const taskId = parseInt(this.getAttribute('data-task-id'));
const taskItem = tasks.find(t => t.id === taskId);
if (taskItem) {
taskItem.completed = this.checked;
renderTasks();
// In a real app, you would update the task in your database here
}
});
});
// Add event listeners to action buttons
document.querySelectorAll('.task-action-btn').forEach(button => {
button.addEventListener('click', function() {
const action = this.getAttribute('data-action');
const taskId = parseInt(this.getAttribute('data-task-id'));
const taskItem = tasks.find(t => t.id === taskId);
if (action === 'delete' && confirm('Are you sure you want to delete this task?')) {
const taskIndex = tasks.findIndex(t => t.id === taskId);
if (taskIndex !== -1) {
tasks.splice(taskIndex, 1);
renderTasks();
// In a real app, you would delete the task from your database here
}
} else if (action === 'edit') {
// In a real app, you would open an edit modal here
alert('Edit functionality would be implemented here');
}
});
});
}
function createTaskElement(task) {
const taskElement = document.createElement('div');
taskElement.className = `task-item ${task.completed ? 'completed' : ''}`;
let timeDisplay = '';
if (task.time) {
const [hours, minutes] = task.time.split(':');
const time = new Date();
time.setHours(parseInt(hours));
time.setMinutes(parseInt(minutes));
timeDisplay = time.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
}
const taskDateOptions = { month: 'short', day: 'numeric' };
const taskDateDisplay = task.date.toLocaleDateString('en-US', taskDateOptions);
taskElement.innerHTML = `
<input type="checkbox" class="task-checkbox" data-task-id="${task.id}" ${task.completed ? 'checked' : ''}>
<div class="task-content">
<h3 class="task-title ${task.completed ? 'completed' : ''}">${task.title}</h3>
${task.description ? `<p class="task-description">${task.description}</p>` : ''}
<div class="task-details">
<div class="task-detail">
<span class="task-priority priority-${task.priority}"></span>
${task.priority.charAt(0).toUpperCase() + task.priority.slice(1)}
</div>
<div class="task-detail">
<i class="fas fa-tag"></i>
${task.category.charAt(0).toUpperCase() + task.category.slice(1)}
</div>
${task.time ? `
<div class="task-detail">
<i class="fas fa-clock"></i>
${timeDisplay}
</div>
` : ''}
</div>
</div>
<div class="task-actions">
<button class="task-action-btn" data-task-id="${task.id}" data-action="edit">
<i class="fas fa-edit"></i>
</button>
<button class="task-action-btn" data-task-id="${task.id}" data-action="delete">
<i class="fas fa-trash-alt"></i>
</button>
</div>
`;
return taskElement;
}
// Form submission
taskForm.addEventListener('submit', (e) => {
e.preventDefault();
// Get form values
const title = document.getElementById('taskTitle').value;
const description = document.getElementById('taskDescription').value;
const priority = document.querySelector('.priority-btn.active').getAttribute('data-priority');
const category = document.querySelector('.category-tag.active').getAttribute('data-category');
const date = document.getElementById('taskDate').value;
const time = document.getElementById('taskTime').value;
// Create new task
const newTask = {
id: tasks.length > 0 ? Math.max(...tasks.map(t => t.id)) + 1 : 1,
title,
description,
completed: false,
priority,
category,
date: new Date(date),
time: time || null
};
// Add to tasks array
tasks.push(newTask);
// Re-render tasks
renderTasks();
// Close modal and reset form
taskModal.classList.remove('active');
taskForm.reset();
// Reset priority to medium
priorityButtons.forEach(btn => btn.classList.remove('active'));
document.querySelector('.priority-btn[data-priority="medium"]').classList.add('active');
// Reset category to personal
categoryButtons.forEach(btn => btn.classList.remove('active'));
document.querySelector('.category-tag[data-category="personal"]').classList.add('active');
});
// Set today's date as default for new tasks
document.getElementById('taskDate').valueAsDate = new Date();
// Initial render
renderTasks();
</script>
</body>
</html>