HH/templates/projects/my_tasks.html
ismail badb6a9ebf
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m41s
feat: QI Projects — team-member task management + My Tasks + notifications
Fixed 3 gaps in the QI Projects module:

Gap 1 (critical): team members couldn't manage their own tasks — the toggle
checkbox/edit/delete were gated behind admin-only can_edit. Now:
- _can_manage_task() helper: admins OR the task assignee OR project team members
- task_toggle_status + htmx_task_toggle_status use the new helper
- task_row.html shows the toggle for assignees (task.assigned_to.user_id check)

Gap 2: no "My QI Tasks" view — added /projects/my-tasks/ showing tasks assigned
to the current user across all projects, with toggle links + stats. Sidebar link.

Gap 3: no notification on task assignment — added apps/projects/signals.py
(post_save on QIProjectTask → create_in_app_notification). apps.py ready() wired.

Tested (headed, 11 PASS / 1 FAIL):
- Cross-department team members (Contact Center + different dept) can VIEW the
  project AND toggle their assigned tasks (both PASS)
- My Tasks view loads for team members
- Excel export returns 500 (real bug, reported)
- Project close via edit form needs correct hospital UUID (test harness issue)

Also bundles accumulated in-progress work across complaints, observations,
organizations, templates, and other modules.

Harness: seed_e2e_project + get_e2e_project_state CLI + qi-projects-workflow.spec.ts
2026-06-16 23:55:58 +03:00

88 lines
4.3 KiB
HTML

{% extends "layouts/base.html" %}
{% load i18n %}
{% block title %}{% trans "My QI Tasks" %} - PX360{% endblock %}
{% block content %}
<header class="mb-6">
<div class="flex items-center gap-2 text-sm text-slate mb-2">
<a href="{% url 'projects:project_list' %}" class="hover:text-navy">{% trans "QI Projects" %}</a>
<i data-lucide="chevron-right" class="w-4 h-4"></i>
<span class="font-bold text-navy">{% trans "My Tasks" %}</span>
</div>
<h1 class="text-2xl font-bold text-navy">{% trans "My QI Tasks" %}</h1>
</header>
<div class="grid grid-cols-3 gap-4 mb-6">
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-5">
<p class="text-[10px] uppercase font-bold text-slate-500 mb-1">{% trans "Total" %}</p>
<p class="text-3xl font-bold text-navy">{{ total }}</p>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-5">
<p class="text-[10px] uppercase font-bold text-slate-500 mb-1">{% trans "Pending" %}</p>
<p class="text-3xl font-bold text-amber-600">{{ pending }}</p>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-5">
<p class="text-[10px] uppercase font-bold text-slate-500 mb-1">{% trans "Completed" %}</p>
<p class="text-3xl font-bold text-green-600">{{ completed }}</p>
</div>
</div>
{% if grouped %}
{% for project, tasks in grouped.items %}
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-6 mb-4">
<div class="flex items-center gap-2 mb-4">
<i data-lucide="folder-kanban" class="w-5 h-5 text-navy"></i>
<a href="{% url 'projects:project_detail' pk=project.pk %}" class="text-lg font-bold text-navy hover:text-blue-600">
{{ project.name }}
</a>
<span class="text-xs px-2 py-0.5 rounded-full font-bold
{% if project.status == 'completed' %}bg-green-100 text-green-700
{% elif project.status == 'in_progress' %}bg-blue-100 text-blue-700
{% else %}bg-slate-100 text-slate-600{% endif %}">
{{ project.get_status_display }}
</span>
</div>
<div class="space-y-2">
{% for task in tasks %}
<div class="flex items-center gap-3 p-3 rounded-xl {% if task.status == 'completed' %}bg-green-50{% else %}bg-slate-50{% endif %}">
<form method="post" action="{% url 'projects:task_toggle_status' project_pk=project.pk task_pk=task.pk %}" class="inline">
{% csrf_token %}
<button type="submit" class="p-1 bg-transparent border-none cursor-pointer">
{% if task.status == 'completed' %}
<i data-lucide="check-square" class="w-5 h-5 text-green-600"></i>
{% else %}
<i data-lucide="square" class="w-5 h-5 text-slate-300 hover:text-blue-500"></i>
{% endif %}
</button>
</form>
<div class="flex-1">
<span class="text-sm font-semibold {% if task.status == 'completed' %}line-through text-slate-400{% else %}text-navy{% endif %}">
{{ task.title }}
</span>
{% if task.description %}
<p class="text-xs text-slate-500 mt-0.5">{{ task.description|truncatewords:20 }}</p>
{% endif %}
</div>
{% if task.due_date %}
<span class="text-xs {% if task.due_date < today and task.status != 'completed' %}text-red-600 font-bold{% else %}text-slate-500{% endif %}">
{{ task.due_date|date:"M d" }}
</span>
{% endif %}
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-[10px] font-bold uppercase
{% if task.status == 'completed' %}bg-green-100 text-green-700{% else %}bg-amber-100 text-amber-700{% endif %}">
{{ task.get_status_display }}
</span>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
{% else %}
<div class="bg-white rounded-2xl shadow-sm border border-slate-100 p-12 text-center">
<i data-lucide="check-circle" class="w-12 h-12 text-green-500 mx-auto mb-3"></i>
<p class="text-slate-600 font-semibold">{% trans "You have no QI tasks assigned." %}</p>
</div>
{% endif %}
{% endblock %}