HH/templates/complaints/partials/timeline_panel.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

46 lines
2.2 KiB
HTML

{% load i18n %}
<section class="bg-white rounded-2xl p-4 shadow-sm border border-slate-100">
<h3 class="text-lg font-bold text-navy mb-4">{% trans "Timeline" %}</h3>
{% if not stage_timeline.stages %}
<div class="text-center py-12">
<i data-lucide="clock-history" class="w-16 h-16 mx-auto text-slate-300 mb-4"></i>
<p class="text-slate">{% trans "No activity recorded yet" %}</p>
</div>
{% else %}
<div class="relative">
{% for stage in stage_timeline.stages %}
<div class="relative pl-10 pb-6 {% if not forloop.last %}border-l-2 border-slate-200 ml-[5px]{% else %}ml-[5px]{% endif %}">
<div class="absolute left-0 top-0 w-7 h-7 rounded-full {{ stage.color }} ring-4 ring-white -translate-x-[11px] flex items-center justify-center">
<i data-lucide="{{ stage.icon }}" class="w-4 h-4 text-white"></i>
</div>
<div class="flex items-baseline justify-between gap-4">
<div>
<p class="text-sm font-semibold text-navy">{{ stage.label }}</p>
<p class="text-xs text-slate">{{ stage.timestamp|date:"d M Y, h:i A" }}</p>
{% if stage.performed_by %}
<p class="text-[10px] text-slate-400 mt-0.5 flex items-center gap-1">
<i data-lucide="user" class="w-3 h-3"></i> {{ stage.performed_by }}
</p>
{% endif %}
</div>
{% if stage.duration_from_prev %}
<span class="shrink-0 px-2 py-0.5 rounded-md text-[11px] font-bold bg-slate-100 text-slate-500">
{{ stage.duration_from_prev }}
</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% if stage_timeline.total_time %}
<div class="mt-2 pt-4 border-t-2 border-slate-200 flex items-center justify-between">
<span class="text-sm font-bold text-navy">{% trans "Total Time" %}</span>
<span class="px-3 py-1 rounded-lg text-sm font-bold bg-navy text-white">
{{ stage_timeline.total_time }}
</span>
</div>
{% endif %}
{% endif %}
</section>