Files
Raccoon-TimeKeeper/templates/settings.html

207 lines
7.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Tasks - Raccoon Timekeeper{% endblock %}
{% block tagline %}Manage your tasks{% endblock %}
{% block content %}
<section class="card">
<div class="card-header">
<h2>Your Tasks</h2>
<button class="btn btn-primary" onclick="openAddTaskModal()">
<span class="btn-icon">+</span>
Add Task
</button>
</div>
<div id="tasksList" class="tasks-list">
<div class="loading">Loading tasks...</div>
</div>
</section>
<!-- Add Task Modal -->
<div id="addTaskModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3>Add New Task</h3>
<button class="modal-close" onclick="closeModal('addTaskModal')">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="newTaskName">Task Name</label>
<input type="text" id="newTaskName" placeholder="Enter task name...">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" onclick="closeModal('addTaskModal')">Cancel</button>
<button class="btn btn-primary" onclick="saveNewTask()">Add Task</button>
</div>
</div>
</div>
<!-- Edit Task Modal -->
<div id="editTaskModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h3>Edit Task</h3>
<button class="modal-close" onclick="closeModal('editTaskModal')">×</button>
</div>
<div class="modal-body">
<input type="hidden" id="editTaskId">
<div class="form-group">
<label for="editTaskName">Task Name</label>
<input type="text" id="editTaskName" placeholder="Enter task name...">
</div>
<div class="form-group checkbox-group">
<label class="checkbox-label">
<input type="checkbox" id="editTaskActive">
<span>Active</span>
</label>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-danger" onclick="deleteTask()">Delete</button>
<button class="btn btn-secondary" onclick="closeModal('editTaskModal')">Cancel</button>
<button class="btn btn-primary" onclick="saveEditTask()">Save</button>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
document.addEventListener('DOMContentLoaded', loadTasks);
async function loadTasks() {
try {
const response = await fetch('/api/tasks?include_inactive=true');
const tasks = await response.json();
renderTasks(tasks);
} catch (error) {
showToast('Error loading tasks', 'error');
}
}
function renderTasks(tasks) {
const container = document.getElementById('tasksList');
if (!tasks.length) {
container.innerHTML = '<div class="empty-state">📋 No tasks yet. Create one!</div>';
return;
}
let html = '';
tasks.forEach(task => {
html += `
<div class="task-item ${task.active ? '' : 'inactive'}" data-id="${task.id}">
<div class="task-info">
<span class="task-name">${task.name}</span>
${!task.active ? '<span class="task-badge inactive-badge">Inactive</span>' : ''}
</div>
<button class="btn btn-icon" onclick="openEditTaskModal(${task.id}, '${task.name.replace(/'/g, "\\'")}', ${task.active})">
✏️
</button>
</div>
`;
});
container.innerHTML = html;
}
function openAddTaskModal() {
document.getElementById('addTaskModal').classList.add('active');
document.getElementById('newTaskName').value = '';
document.getElementById('newTaskName').focus();
}
function openEditTaskModal(id, name, active) {
document.getElementById('editTaskId').value = id;
document.getElementById('editTaskName').value = name;
document.getElementById('editTaskActive').checked = active;
document.getElementById('editTaskModal').classList.add('active');
}
function closeModal(modalId) {
document.getElementById(modalId).classList.remove('active');
}
async function saveNewTask() {
const name = document.getElementById('newTaskName').value.trim();
if (!name) { showToast('Enter a task name', 'error'); return; }
try {
const response = await fetch('/api/tasks', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name })
});
const result = await response.json();
if (result.success) {
showToast('Task added!', 'success');
closeModal('addTaskModal');
loadTasks();
} else {
showToast(result.message, 'error');
}
} catch (error) {
showToast('Error adding task', 'error');
}
}
async function saveEditTask() {
const id = document.getElementById('editTaskId').value;
const name = document.getElementById('editTaskName').value.trim();
const active = document.getElementById('editTaskActive').checked;
if (!name) { showToast('Enter a task name', 'error'); return; }
try {
const response = await fetch(`/api/tasks/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, active })
});
const result = await response.json();
if (result.success) {
showToast('Task updated!', 'success');
closeModal('editTaskModal');
loadTasks();
} else {
showToast(result.message, 'error');
}
} catch (error) {
showToast('Error updating task', 'error');
}
}
async function deleteTask() {
if (!confirm('Delete this task? This will also delete all time entries for this task.')) return;
const id = document.getElementById('editTaskId').value;
try {
const response = await fetch(`/api/tasks/${id}`, { method: 'DELETE' });
const result = await response.json();
if (result.success) {
showToast('Task deleted', 'success');
closeModal('editTaskModal');
loadTasks();
} else {
showToast(result.message, 'error');
}
} catch (error) {
showToast('Error deleting task', 'error');
}
}
document.getElementById('newTaskName').addEventListener('keypress', e => {
if (e.key === 'Enter') { e.preventDefault(); saveNewTask(); }
});
document.getElementById('editTaskName').addEventListener('keypress', e => {
if (e.key === 'Enter') { e.preventDefault(); saveEditTask(); }
});
</script>
{% endblock %}