Internal
Public Access
Offline mode had tag chips and per-task tag assignment, but was missing the dashboard sidebar's Tags section entirely: filtering the task list by tag, per-tag task counts, and tag create/rename/delete. Ports that section over (reusing the same tag modal pattern as the online create/edit flow), combinable with the existing status filters the same way it works online. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
167 lines
8.5 KiB
HTML
167 lines
8.5 KiB
HTML
{% load static %}<!DOCTYPE html>
|
|
<html lang="en" data-theme="light">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Offline - KeepItGoing</title>
|
|
<link rel="icon" type="image/svg+xml" href="{% static 'favicons/favicon.svg' %}">
|
|
<link rel="stylesheet" href="{% static 'css/app.css' %}">
|
|
<script>
|
|
(function() {
|
|
var saved = localStorage.getItem('theme');
|
|
var systemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
if (saved === 'dark' || (!saved && systemDark)) {
|
|
document.documentElement.setAttribute('data-theme', 'dark');
|
|
}
|
|
})();
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div class="app-layout detail-closed" id="app">
|
|
<!-- Header (offline-tinted so it's unmistakable which mode you're in) -->
|
|
<header class="app-header" style="background-color: #d97706; color: #fff; border-bottom-color: #b45309;">
|
|
<div style="display: flex; align-items: center; gap: var(--space-md);">
|
|
<button class="sidebar-toggle" onclick="toggleOfflineSidebar()" aria-label="Toggle sidebar" style="color: #fff;">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 12h18M3 6h18M3 18h18"/>
|
|
</svg>
|
|
</button>
|
|
<span class="app-brand" style="color: #fff;">KeepItGoing</span>
|
|
<span style="font-size: var(--font-sm); font-weight: 600;">⚠ Offline — changes sync automatically once you're back online</span>
|
|
</div>
|
|
<div class="app-header-actions">
|
|
<button class="theme-toggle" onclick="toggleOfflineTheme()" aria-label="Toggle theme" title="Toggle dark/light mode" style="color: #fff;">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="5"/>
|
|
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Sidebar -->
|
|
<aside class="app-sidebar" id="sidebar">
|
|
<div class="sidebar-section">
|
|
<div class="sidebar-section-title">Filters</div>
|
|
<nav class="sidebar-nav" id="offline-filter-nav">
|
|
<a href="#" class="sidebar-item active" data-filter="all">
|
|
<svg class="sidebar-item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 12h18M3 6h18M3 18h18"/>
|
|
</svg>
|
|
All Tasks
|
|
</a>
|
|
<a href="#" class="sidebar-item" data-filter="today">
|
|
<svg class="sidebar-item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 6v6l4 2"/>
|
|
</svg>
|
|
Today
|
|
</a>
|
|
<a href="#" class="sidebar-item" data-filter="upcoming">
|
|
<svg class="sidebar-item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
|
<path d="M16 2v4M8 2v4M3 10h18"/>
|
|
</svg>
|
|
Upcoming
|
|
</a>
|
|
<a href="#" class="sidebar-item" data-filter="overdue">
|
|
<svg class="sidebar-item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M12 8v4M12 16h.01"/>
|
|
</svg>
|
|
Overdue
|
|
</a>
|
|
<a href="#" class="sidebar-item" data-filter="completed">
|
|
<svg class="sidebar-item-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
|
|
<path d="M22 4L12 14.01l-3-3"/>
|
|
</svg>
|
|
Completed
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="sidebar-section">
|
|
<div class="sidebar-section-title">Tags</div>
|
|
<nav class="sidebar-nav" id="offline-tag-nav"></nav>
|
|
<button type="button" class="sidebar-add-btn" id="offline-add-tag-btn">
|
|
<svg style="width: 14px; height: 14px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M12 5v14M5 12h14"/>
|
|
</svg>
|
|
Add Tag
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main Task Pane -->
|
|
<main class="task-pane">
|
|
<div class="task-pane-header">
|
|
<h1 class="task-pane-title" id="offline-page-title">All Tasks</h1>
|
|
<select id="offline-sort-select" class="form-select" style="width: auto;">
|
|
<option value="due_date">Due Date (Earliest)</option>
|
|
<option value="due_date_desc">Due Date (Latest)</option>
|
|
<option value="priority">Priority (High to Low)</option>
|
|
<option value="priority_low">Priority (Low to High)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<form id="offline-add-task-form" class="quick-add">
|
|
<input type="text" id="offline-task-title" class="quick-add-input" placeholder="Add a new task..." required>
|
|
<button type="submit" class="btn btn-primary">Add</button>
|
|
</form>
|
|
|
|
<div id="offline-empty-state" class="empty-state" hidden>
|
|
<p>Loading...</p>
|
|
</div>
|
|
<div class="task-list" id="offline-task-list"></div>
|
|
</main>
|
|
|
|
<!-- Detail Panel -->
|
|
<aside class="detail-pane hidden" id="detail-pane">
|
|
<div class="empty-state">
|
|
<p>Select a task to view details</p>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Mobile overlay -->
|
|
<div class="mobile-overlay" id="mobile-overlay" onclick="closeOfflineMobileMenus()"></div>
|
|
</div>
|
|
|
|
<!-- Tag Edit/Create Modal (outside app-layout for proper fixed positioning) -->
|
|
<div class="modal-backdrop" id="tag-modal-backdrop">
|
|
<div class="modal" onclick="event.stopPropagation()">
|
|
<div class="modal-header">
|
|
<h2 class="modal-title" id="tag-modal-title">New Tag</h2>
|
|
<button type="button" class="modal-close" id="tag-modal-close-btn">
|
|
<svg style="width: 20px; height: 20px;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M18 6L6 18M6 6l12 12"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<form id="tag-edit-form">
|
|
<div class="form-group">
|
|
<label class="form-label" for="tag-modal-name">Name</label>
|
|
<input type="text" class="form-input" id="tag-modal-name" required placeholder="Tag name">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">Color</label>
|
|
<div class="color-presets" id="tag-modal-color-presets"></div>
|
|
<div class="color-custom-row">
|
|
<label class="color-custom-label">Custom:</label>
|
|
<input type="color" id="tag-modal-color" class="color-custom-input" value="#3b82f6">
|
|
</div>
|
|
</div>
|
|
<div class="modal-actions">
|
|
<button type="button" class="btn btn-secondary" id="tag-modal-cancel-btn">Cancel</button>
|
|
<button type="button" class="btn btn-danger" id="tag-modal-delete-btn" style="display: none;">Delete</button>
|
|
<button type="submit" class="btn btn-primary" id="tag-modal-submit-btn">Create</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="{% static 'js/offline-db.js' %}"></script>
|
|
<script src="{% static 'js/offline-tasks.js' %}"></script>
|
|
</body>
|
|
</html>
|