-
+
+
+
-
{% if not column.is_system %}
-
{% if not columns %}
-
-
- {{ _('No kanban columns found. Create your first column to get started.') }}
+
+
+ {{ _('No kanban columns found. Create your first column to get started.') }}
{% endif %}
-
-
-
- {{ _('Tips:') }}
-
- - {{ _('Drag and drop rows to reorder columns') }}
- - {{ _('System columns (todo, in_progress, done) cannot be deleted but can be customized') }}
- - {{ _('Columns marked as "Complete" will mark tasks as completed when dragged to that column') }}
- - {{ _('Inactive columns are hidden from the kanban board but tasks with that status remain accessible') }}
-
+
+ {{ _('Tips:') }}
+
+ - {{ _('Drag and drop rows to reorder columns') }}
+ - {{ _('System columns (todo, in_progress, done) cannot be deleted but can be customized') }}
+ - {{ _('Columns marked as "Complete" will mark tasks as completed when dragged to that column') }}
+ - {{ _('Inactive columns are hidden from the kanban board but tasks with that status remain accessible') }}
+
+
+
+
+
+
+
+ {{ _('Delete Kanban Column') }}
+
+ ×
+
+
+
+
+
+ {{ _('Warning:') }} {{ _('This action cannot be undone.') }}
+
+
+ {{ _('Are you sure you want to delete the column?') }}
+
+ {{ _('Key:') }}
+
+
+ {{ _('Note: Tasks with this status will remain accessible but the column will no longer appear on the kanban board.') }}
+
+
+
+
+ {{ _('Cancel') }}
+
+
+
+
+
@@ -177,30 +198,22 @@
+
+{% block scripts_extra %}
-
{% endblock %}
diff --git a/app/templates/projects/_kanban_tailwind.html b/app/templates/projects/_kanban_tailwind.html
new file mode 100644
index 0000000..900798e
--- /dev/null
+++ b/app/templates/projects/_kanban_tailwind.html
@@ -0,0 +1,86 @@
+{# Reusable Kanban board for tasks. Expects `tasks` and `kanban_columns` in context. #}
+
+
+
+ {% for col in kanban_columns %}
+
+
+
+
+ {{ col.label }}
+
+
+
+ {{ tasks|selectattr('status', 'equalto', col.key)|list|length }}
+
+ {% if current_user.is_admin %}
+
+
+
+ {% endif %}
+
+
+
+ {% set column_tasks = tasks|selectattr('status', 'equalto', col.key)|list %}
+ {% if column_tasks %}
+ {% for task in column_tasks %}
+
+ {% endfor %}
+ {% else %}
+
+ {{ _('No tasks in this column.') }}
+
+ {% endif %}
+
+
+ {% endfor %}
+
+
+
+
diff --git a/app/templates/projects/list.html b/app/templates/projects/list.html
new file mode 100644
index 0000000..3f3a3b8
--- /dev/null
+++ b/app/templates/projects/list.html
@@ -0,0 +1,112 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
+ Projects
+ Manage your projects here.
+
+ {% if current_user.is_admin %}
+ Create Project
+ {% endif %}
+
+
+
+
+
+
+
+
+ | Name |
+ Client |
+ Status |
+ Billable |
+ Rate |
+ Budget |
+ Actions |
+
+
+
+ {% for project in projects %}
+
+ | {{ project.name }} |
+ {{ project.client.name }} |
+
+ {% if project.status == 'active' %}
+ Active
+ {% else %}
+ Archived
+ {% endif %}
+ |
+
+ {% if project.billable %}
+ Billable
+ {% else %}
+ Non‑billable
+ {% endif %}
+ |
+
+ {% if project.hourly_rate %}
+ {{ '%.2f'|format(project.hourly_rate|float) }}/h
+ {% else %}
+ —
+ {% endif %}
+ |
+
+ {% if project.budget_amount %}
+ {% set consumed = (project.budget_consumed_amount or 0.0) %}
+ {% set total = project.budget_amount|float %}
+ {% set pct = (consumed / total * 100) if total > 0 else 0 %}
+ {% if pct >= 90 %}
+ {% set badge_classes = 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300' %}
+ {% elif pct >= 70 %}
+ {% set badge_classes = 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300' %}
+ {% else %}
+ {% set badge_classes = 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-300' %}
+ {% endif %}
+ {{ pct|round(0) }}%
+ {% else %}
+ —
+ {% endif %}
+ |
+
+ View
+ |
+
+ {% else %}
+
+ | No projects found. |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/app/templates/projects/view.html b/app/templates/projects/view.html
new file mode 100644
index 0000000..332cfda
--- /dev/null
+++ b/app/templates/projects/view.html
@@ -0,0 +1,115 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
+ {{ project.name }}
+ {{ project.client.name }}
+
+ {% if current_user.is_admin %}
+ Edit Project
+ {% endif %}
+
+
+
+
+
+
+ Details
+
+
+ Description
+ {{ project.description or 'No description provided.' }}
+
+
+ Status
+ {{ project.status | capitalize }}
+
+
+ Billing
+ {{ 'Billable' if project.billable else 'Not Billable' }} {% if project.hourly_rate %}({{ "%.2f"|format(project.hourly_rate) }}/hr){% endif %}
+
+
+
+
+ User Contributions
+
+ {% for user_total in user_totals %}
+ -
+ {{ user_total.username }}
+ {{ "%.2f"|format(user_total.total_hours) }} hrs
+
+ {% else %}
+ - No hours logged yet.
+ {% endfor %}
+
+
+
+
+
+
+
+ {{ _('Tasks for this project') }}
+
+
+
+ | {{ _('Name') }} |
+ {{ _('Priority') }} |
+ {{ _('Status') }} |
+ {{ _('Due') }} |
+ {{ _('Progress') }} |
+ {{ _('Actions') }} |
+
+
+
+ {% for task in tasks %}
+
+ | {{ task.name }} |
+
+ {% set p = task.priority %}
+ {% set pcls = {'low':'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300',
+ 'medium':'bg-sky-100 text-sky-700 dark:bg-sky-900/30 dark:text-sky-300',
+ 'high':'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
+ 'urgent':'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-300'}[p] if p in ['low','medium','high','urgent'] else 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300' %}
+ {{ task.priority_display }}
+ |
+
+ {% set s = task.status %}
+ {% set scls = {'todo':'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300',
+ 'in_progress':'bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-300',
+ 'review':'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
+ 'done':'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-300',
+ 'cancelled':'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-200'}[s] if s in ['todo','in_progress','review','done','cancelled'] else 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300' %}
+ {{ task.status_display }}
+ |
+
+ {% if task.due_date %}
+ {% set overdue = task.is_overdue %}
+ {{ task.due_date.strftime('%Y-%m-%d') }}
+ {% else %}
+ —
+ {% endif %}
+ |
+
+ {% set pct = task.progress_percentage or 0 %}
+
+ |
+
+ {{ _('View') }}
+ |
+
+ {% else %}
+
+ | {{ _('No tasks for this project.') }} |
+
+ {% endfor %}
+
+
+
+
+
+{% endblock %}
+
+{% block scripts_extra %}{% endblock %}
diff --git a/app/templates/reports/index.html b/app/templates/reports/index.html
new file mode 100644
index 0000000..361faa9
--- /dev/null
+++ b/app/templates/reports/index.html
@@ -0,0 +1,52 @@
+{% extends "base.html" %}
+{% from "components/cards.html" import info_card %}
+
+{% block content %}
+
+ Reports
+
+
+
+ {{ info_card("Total Hours", "%.2f"|format(summary.total_hours), "All time") }}
+ {{ info_card("Billable Hours", "%.2f"|format(summary.billable_hours), "All time") }}
+ {{ info_card("Active Projects", summary.active_projects, "Currently active") }}
+ {{ info_card("Active Users", summary.total_users, "Currently active") }}
+
+
+
+
+
+ Recent Entries
+
+
+
+ | Project |
+ Duration |
+ Date |
+
+
+
+ {% for entry in recent_entries %}
+
+ | {{ entry.project.name }} |
+ {{ entry.duration }} |
+ {{ entry.start_time.strftime('%Y-%m-%d') }} |
+
+ {% else %}
+
+ | No recent entries. |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/app/templates/reports/project_report.html b/app/templates/reports/project_report.html
new file mode 100644
index 0000000..854c538
--- /dev/null
+++ b/app/templates/reports/project_report.html
@@ -0,0 +1,68 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+ Project Report
+
+
+
+
+
+
+
+
+ | Project |
+ Total Hours |
+ Billable Hours |
+ Billable Amount |
+
+
+
+ {% for project in projects_data %}
+
+ | {{ project.name }} |
+ {{ "%.2f"|format(project.total_hours) }} |
+ {{ "%.2f"|format(project.billable_hours) }} |
+ {{ "%.2f"|format(project.billable_amount) }} |
+
+ {% else %}
+
+ | No data for the selected period. |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/app/templates/reports/summary.html b/app/templates/reports/summary.html
new file mode 100644
index 0000000..2342287
--- /dev/null
+++ b/app/templates/reports/summary.html
@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+{% from "components/cards.html" import info_card %}
+
+{% block content %}
+
+ Summary Report
+
+
+
+ {{ info_card("Today's Hours", "%.2f"|format(today_hours), "Logged today") }}
+ {{ info_card("Week's Hours", "%.2f"|format(week_hours), "Logged this week") }}
+ {{ info_card("Month's Hours", "%.2f"|format(month_hours), "Logged this month") }}
+
+
+
+ Top Projects (Last 30 Days)
+
+
+
+ | Project |
+ Total Hours |
+
+
+
+ {% for stat in project_stats %}
+
+ | {{ stat.project.name }} |
+ {{ "%.2f"|format(stat.hours) }} |
+
+ {% else %}
+
+ | No project data for the last 30 days. |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/app/templates/reports/task_report.html b/app/templates/reports/task_report.html
new file mode 100644
index 0000000..54d88eb
--- /dev/null
+++ b/app/templates/reports/task_report.html
@@ -0,0 +1,68 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+ Task Report
+
+
+
+
+
+
+
+
+ | Task |
+ Project |
+ Completed At |
+ Hours |
+
+
+
+ {% for task_row in tasks %}
+
+ | {{ task_row.task.name }} |
+ {{ task_row.project.name }} |
+ {{ task_row.completed_at.strftime('%Y-%m-%d') }} |
+ {{ "%.2f"|format(task_row.hours) }} |
+
+ {% else %}
+
+ | No completed tasks for the selected period. |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/app/templates/reports/user_report.html b/app/templates/reports/user_report.html
new file mode 100644
index 0000000..5124b89
--- /dev/null
+++ b/app/templates/reports/user_report.html
@@ -0,0 +1,66 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+ User Report
+
+
+
+
+
+
+
+
+ | User |
+ Total Hours |
+ Billable Hours |
+
+
+
+ {% for username, totals in user_totals.items() %}
+
+ | {{ username }} |
+ {{ "%.2f"|format(totals.hours) }} |
+ {{ "%.2f"|format(totals.billable_hours) }} |
+
+ {% else %}
+
+ | No data for the selected period. |
+
+ {% endfor %}
+
+
+
+{% endblock %}
diff --git a/app/templates/tasks/create.html b/app/templates/tasks/create.html
index 0fb9509..2266980 100644
--- a/app/templates/tasks/create.html
+++ b/app/templates/tasks/create.html
@@ -8,95 +8,65 @@
{% endblock %}
{% block content %}
-
-
-
-
-
-
-
-
-
-
-
- {{ _('Create New Task') }}
- {{ _('Add a new task to your project to break down work into manageable components') }}
-
-
-
-
-
+
+
+ {{ _('Create Task') }}
+ {{ _('Add a new task to your project to break down work into manageable components') }}
+
+ {{ _('Back to Tasks') }}
-
- |