Add settings/task management template
This commit is contained in:
206
templates/settings.html
Normal file
206
templates/settings.html
Normal file
@@ -0,0 +1,206 @@
|
||||
{% 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 %}
|
||||
Reference in New Issue
Block a user