Improve partner review board filters business display due dates and pagination

This commit is contained in:
A R R R Associates
2026-08-21 13:42:19 +05:30
parent 92f06f333a
commit 208808da6a
2 changed files with 490 additions and 176 deletions
@@ -3,7 +3,7 @@
{% include "modules/partners/templates/partners/_partner_tabs.html" %}
{% macro engagement_row(task, column, payload) %}
{% set stats = namespace(total=0, completed=0, blocked=0, review=0, rework=0, overdue=false, assignees=[]) %}
{% set stats = namespace(total=0, completed=0, blocked=0, review=0, rework=0, assignees=[]) %}
{% for stat_column in payload.columns %}
{% for item in stat_column.tasks %}
{% if item.subscription_id == task.subscription_id %}
@@ -20,9 +20,6 @@
{% if stat_column.code == 'rework_sent' %}
{% set stats.rework = stats.rework + 1 %}
{% endif %}
{% if item.is_overdue %}
{% set stats.overdue = true %}
{% endif %}
{% if item.assignee_display and item.assignee_display not in stats.assignees %}
{% set _ = stats.assignees.append(item.assignee_display) %}
{% endif %}
@@ -32,10 +29,39 @@
<tr class="align-top hover:bg-slate-50/70">
<td class="px-4 py-4 text-sm">
<a href="/partner/reviews/engagements/{{ task.subscription_id }}" class="font-semibold text-slate-900 hover:text-brand-700">{{ task.client_display }}</a>
<a href="/partner/reviews/engagements/{{ task.subscription_id }}" class="font-semibold text-slate-900 hover:text-brand-700">{{ task.business_display }}</a>
{% if task.legal_client_display %}
<div class="mt-0.5 text-xs font-medium text-slate-600">{{ task.legal_client_display }}</div>
{% endif %}
{% if task.scope_context_display %}
<div class="mt-1 text-[11px] text-slate-400">{{ task.scope_context_display }}</div>
{% endif %}
<div class="mt-1 text-xs text-slate-500">{{ task.engagement_label }}</div>
<div class="mt-1 text-[11px] text-slate-400">Engagement #{{ task.subscription_id }}</div>
</td>
<td class="px-4 py-4 text-sm">
<div class="font-semibold text-slate-800">{{ task.period_label_display }}</div>
{% if task.financial_year_display %}
<div class="mt-1 text-xs text-slate-500">FY {{ task.financial_year_display }}</div>
{% endif %}
{% if task.engagement_start_date or task.engagement_end_date %}
<div class="mt-1 text-[11px] text-slate-400">
{% if task.engagement_start_date %}{{ task.engagement_start_date }}{% endif %}
{% if task.engagement_start_date and task.engagement_end_date %} → {% endif %}
{% if task.engagement_end_date %}{{ task.engagement_end_date }}{% endif %}
</div>
{% endif %}
{% if task.engagement_due_date %}
<div class="mt-2 text-xs font-semibold {% if task.due_status_code == 'overdue' %}text-red-700{% elif task.due_status_code in ['today','soon'] %}text-amber-700{% else %}text-slate-700{% endif %}">
Due {{ task.engagement_due_date }}
</div>
<div class="mt-0.5 text-[11px] {% if task.due_status_code == 'overdue' %}text-red-600{% elif task.due_status_code in ['today','soon'] %}text-amber-600{% else %}text-slate-400{% endif %}">{{ task.due_status_label }}</div>
{% else %}
<div class="mt-2 text-xs text-slate-400">No statutory due date</div>
{% endif %}
</td>
<td class="px-4 py-4 text-sm">
{% if column.code == 'pending_review' %}
<span class="rounded-full bg-amber-100 px-2.5 py-1 text-xs font-semibold text-amber-700">Pending Review</span>
@@ -48,14 +74,13 @@
{% else %}
<span class="rounded-full bg-emerald-100 px-2.5 py-1 text-xs font-semibold text-emerald-700">Completed</span>
{% endif %}
{% if stats.overdue %}
<div class="mt-2"><span class="rounded-full bg-red-50 px-2 py-1 text-[11px] font-semibold text-red-700">Overdue item</span></div>
{% endif %}
</td>
<td class="px-4 py-4 text-sm">
<div class="font-semibold text-slate-900">{{ stats.completed }} / {{ stats.total }}</div>
<div class="mt-1 text-xs text-slate-500">closed task{{ '' if stats.completed == 1 else 's' }} / visible task{{ '' if stats.total == 1 else 's' }}</div>
</td>
<td class="px-4 py-4 text-sm">
<div class="flex flex-wrap gap-1.5">
{% if stats.review %}<span class="rounded-full bg-amber-50 px-2 py-1 text-[11px] font-semibold text-amber-700">{{ stats.review }} review</span>{% endif %}
@@ -64,26 +89,25 @@
{% if not stats.review and not stats.blocked and not stats.rework %}<span class="text-xs text-slate-500">No review exception</span>{% endif %}
</div>
</td>
<td class="px-4 py-4 text-sm text-slate-700">
{% for assignee in stats.assignees[:3] %}
<div>{{ assignee }}</div>
{% endfor %}
{% if stats.assignees|length > 3 %}
<div class="mt-1 text-xs text-slate-500">+{{ stats.assignees|length - 3 }} more</div>
{% endif %}
{% for assignee in stats.assignees[:3] %}<div>{{ assignee }}</div>{% endfor %}
{% if stats.assignees|length > 3 %}<div class="mt-1 text-xs text-slate-500">+{{ stats.assignees|length - 3 }} more</div>{% endif %}
{% if not stats.assignees %}<span class="text-slate-500">Unassigned</span>{% endif %}
</td>
<td class="px-4 py-4 text-sm">
<div class="text-xs font-semibold text-slate-700">{{ task.priority_label }}</div>
<div class="mt-1 text-xs text-slate-500">{% if task.internal_target_date %}Target {{ task.internal_target_date }}{% else %}No task target{% endif %}</div>
<div class="mt-1 text-xs text-slate-500">{% if task.internal_target_date %}Task target {{ task.internal_target_date }}{% else %}No task target{% endif %}</div>
</td>
<td class="px-4 py-4 text-right">
<a href="/partner/reviews/engagements/{{ task.subscription_id }}" class="inline-flex rounded-xl border border-slate-300 px-3 py-2 text-xs font-semibold text-slate-700 hover:bg-slate-50">Open Review</a>
</td>
</tr>
{% endmacro %}
{% macro panel(title, subtitle, ids, payload, tone, page_param, current_page, page_size, q_value) %}
{% macro panel(title, subtitle, ids, payload, tone, page_param, current_page, page_size, filter_query) %}
<section class="overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-soft">
{% set total_items = ids|length %}
{% set total_pages = ((total_items + page_size - 1) // page_size) if total_items else 1 %}
@@ -96,20 +120,23 @@
<div>
<h3 class="text-base font-semibold text-slate-900">{{ title }}</h3>
<p class="mt-1 text-xs text-slate-500">{{ subtitle }}</p>
{% if total_items %}<p class="mt-1 text-[11px] text-slate-400">Showing {{ start_index + 1 }}-{{ [start_index + page_ids|length, total_items]|min }} of {{ total_items }}</p>{% endif %}
</div>
{% if tone == 'review' %}
<span class="w-fit rounded-full bg-amber-100 px-3 py-1 text-xs font-semibold text-amber-700">{{ ids|length }} engagement{{ '' if ids|length == 1 else 's' }}</span>
<span class="w-fit rounded-full bg-amber-100 px-3 py-1 text-xs font-semibold text-amber-700">{{ total_items }} engagement{{ '' if total_items == 1 else 's' }}</span>
{% elif tone == 'progress' %}
<span class="w-fit rounded-full bg-blue-100 px-3 py-1 text-xs font-semibold text-blue-700">{{ ids|length }} engagement{{ '' if ids|length == 1 else 's' }}</span>
<span class="w-fit rounded-full bg-blue-100 px-3 py-1 text-xs font-semibold text-blue-700">{{ total_items }} engagement{{ '' if total_items == 1 else 's' }}</span>
{% else %}
<span class="w-fit rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700">{{ ids|length }} engagement{{ '' if ids|length == 1 else 's' }}</span>
<span class="w-fit rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700">{{ total_items }} engagement{{ '' if total_items == 1 else 's' }}</span>
{% endif %}
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-slate-200">
<thead class="bg-slate-50">
<tr>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Client / Engagement</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Business / Client / Engagement</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Period / Due</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Status</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Task Progress</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide text-slate-500">Review Items</th>
@@ -128,34 +155,18 @@
{% endif %}
{% endfor %}
{% endfor %}
{% if total_items == 0 %}
<tr>
<td colspan="7" class="px-6 py-10 text-center text-sm text-slate-500">No engagements in this section.</td>
</tr>
{% endif %}
{% if total_items == 0 %}<tr><td colspan="8" class="px-6 py-10 text-center text-sm text-slate-500">No engagements in this section.</td></tr>{% endif %}
</tbody>
</table>
</div>
{% if total_items > page_size %}
<div class="flex flex-col gap-3 border-t border-slate-200 px-5 py-4 text-xs text-slate-600 sm:flex-row sm:items-center sm:justify-between">
<div>
Showing {{ start_index + 1 }}-{{ [start_index + page_ids|length, total_items]|min }} of {{ total_items }} engagements
</div>
<div>Page {{ page }} of {{ total_pages }}</div>
<div class="flex items-center gap-2">
{% if page > 1 %}
<a href="?q={{ q_value }}&{{ page_param }}={{ page - 1 }}"
class="rounded-lg border border-slate-300 bg-white px-3 py-1.5 font-semibold text-slate-700 hover:bg-slate-50">Previous</a>
{% else %}
<span class="rounded-lg border border-slate-200 bg-slate-50 px-3 py-1.5 font-semibold text-slate-400">Previous</span>
{% endif %}
<span class="font-semibold text-slate-700">Page {{ page }} of {{ total_pages }}</span>
{% if page < total_pages %}
<a href="?q={{ q_value }}&{{ page_param }}={{ page + 1 }}"
class="rounded-lg border border-slate-300 bg-white px-3 py-1.5 font-semibold text-slate-700 hover:bg-slate-50">Next</a>
{% else %}
<span class="rounded-lg border border-slate-200 bg-slate-50 px-3 py-1.5 font-semibold text-slate-400">Next</span>
{% endif %}
{% if page > 1 %}<a href="?{{ filter_query }}&{{ page_param }}={{ page - 1 }}" class="rounded-lg border border-slate-300 bg-white px-3 py-1.5 font-semibold text-slate-700 hover:bg-slate-50">Previous</a>{% else %}<span class="rounded-lg border border-slate-200 bg-slate-50 px-3 py-1.5 font-semibold text-slate-400">Previous</span>{% endif %}
<span class="font-semibold text-slate-700">{{ page }} / {{ total_pages }}</span>
{% if page < total_pages %}<a href="?{{ filter_query }}&{{ page_param }}={{ page + 1 }}" class="rounded-lg border border-slate-300 bg-white px-3 py-1.5 font-semibold text-slate-700 hover:bg-slate-50">Next</a>{% else %}<span class="rounded-lg border border-slate-200 bg-slate-50 px-3 py-1.5 font-semibold text-slate-400">Next</span>{% endif %}
</div>
</div>
{% endif %}
@@ -163,139 +174,119 @@
{% endmacro %}
<div class="space-y-6">
<div class="flex flex-col gap-3 rounded-3xl border border-slate-200 bg-white p-5 shadow-soft lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-xl font-semibold">Partner Review Board</h2>
<p class="text-sm text-slate-500">Engagement-level review queue. Task-level review, rework and history remain available inside each engagement.</p>
<div class="rounded-3xl border border-slate-200 bg-white p-5 shadow-soft">
<div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 class="text-xl font-semibold">Partner Review Board</h2>
<p class="text-sm text-slate-500">Engagement-level review queue with business identity, engagement period, statutory due date and independent pagination for each section.</p>
</div>
<div class="text-xs text-slate-500">Active FY context: <span class="font-semibold text-slate-700">{{ payload.active_financial_year or 'Not set' }}</span></div>
</div>
<form method="get" class="flex gap-2">
<input name="q" value="{{ q or '' }}" placeholder="Search client, task or service" class="w-72 rounded-xl border border-slate-300 px-3 py-2 text-sm">
<button class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Search</button>
<form method="get" class="mt-5 grid gap-3 md:grid-cols-2 xl:grid-cols-4 2xl:grid-cols-8">
<div class="xl:col-span-2">
<label class="mb-1 block text-xs font-semibold text-slate-600">Search</label>
<input name="q" value="{{ q or '' }}" placeholder="Business, client, task or service" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Financial Year</label>
<select name="fy" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="all" {% if payload.filters.financial_year == 'all' %}selected{% endif %}>All FYs</option>
{% for item in payload.filter_options.financial_years %}<option value="{{ item }}" {% if payload.filters.financial_year == item %}selected{% endif %}>FY {{ item }}</option>{% endfor %}
</select>
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Period</label>
<select name="period" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All periods</option>
{% for item in payload.filter_options.periods %}<option value="{{ item }}" {% if payload.filters.period == item %}selected{% endif %}>{{ item }}</option>{% endfor %}
</select>
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Service</label>
<select name="service_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All services</option>
{% for item in payload.filter_options.services %}<option value="{{ item.id }}" {% if payload.filters.service_id == item.id %}selected{% endif %}>{{ item.name }}</option>{% endfor %}
</select>
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Due Date</label>
<select name="due" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All due dates</option>
<option value="overdue" {% if payload.filters.due_bucket == 'overdue' %}selected{% endif %}>Overdue</option>
<option value="today" {% if payload.filters.due_bucket == 'today' %}selected{% endif %}>Due today</option>
<option value="next_7" {% if payload.filters.due_bucket == 'next_7' %}selected{% endif %}>Due in next 7 days</option>
<option value="next_15" {% if payload.filters.due_bucket == 'next_15' %}selected{% endif %}>Due in next 15 days</option>
<option value="this_month" {% if payload.filters.due_bucket == 'this_month' %}selected{% endif %}>Due this month</option>
<option value="none" {% if payload.filters.due_bucket == 'none' %}selected{% endif %}>No due date</option>
</select>
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Assigned Team</label>
<select name="assignee_id" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All team members</option>
{% for item in payload.filter_options.teams %}<option value="{{ item.id }}" {% if payload.filters.assignee_id == item.id %}selected{% endif %}>{{ item.name }}</option>{% endfor %}
</select>
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Priority</label>
<select name="priority" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All priorities</option>
{% for code, label in task_priorities %}<option value="{{ code }}" {% if payload.filters.priority == code %}selected{% endif %}>{{ label }}</option>{% endfor %}
</select>
</div>
<div>
<label class="mb-1 block text-xs font-semibold text-slate-600">Rows / section</label>
<select name="page_size" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
{% for size in [10,25,50] %}<option value="{{ size }}" {% if page_size == size %}selected{% endif %}>{{ size }}</option>{% endfor %}
</select>
</div>
<div class="flex items-end gap-2 xl:col-span-2">
<button class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Apply Filters</button>
<a href="/partner/reviews" class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-sm font-semibold text-slate-700 hover:bg-slate-50">Clear</a>
</div>
</form>
</div>
{% set metrics = namespace(pending_review=[], clarification_required=[], rework_sent=[], approved=[], completed=[]) %}
{% set metrics = namespace(pending_review=[], clarification_required=[], rework_sent=[], approved=[], completed=[], overdue=[], due_soon=[]) %}
{% for column in payload.columns %}
{% for task in column.tasks %}
{% if task.subscription_id %}
{% if column.code == 'pending_review' and task.subscription_id not in metrics.pending_review %}
{% set _ = metrics.pending_review.append(task.subscription_id) %}
{% elif column.code == 'clarification_required' and task.subscription_id not in metrics.clarification_required %}
{% set _ = metrics.clarification_required.append(task.subscription_id) %}
{% elif column.code == 'rework_sent' and task.subscription_id not in metrics.rework_sent %}
{% set _ = metrics.rework_sent.append(task.subscription_id) %}
{% elif column.code == 'approved' and task.subscription_id not in metrics.approved %}
{% set _ = metrics.approved.append(task.subscription_id) %}
{% elif column.code == 'completed' and task.subscription_id not in metrics.completed %}
{% set _ = metrics.completed.append(task.subscription_id) %}
{% endif %}
{% if column.code == 'pending_review' and task.subscription_id not in metrics.pending_review %}{% set _ = metrics.pending_review.append(task.subscription_id) %}
{% elif column.code == 'clarification_required' and task.subscription_id not in metrics.clarification_required %}{% set _ = metrics.clarification_required.append(task.subscription_id) %}
{% elif column.code == 'rework_sent' and task.subscription_id not in metrics.rework_sent %}{% set _ = metrics.rework_sent.append(task.subscription_id) %}
{% elif column.code == 'approved' and task.subscription_id not in metrics.approved %}{% set _ = metrics.approved.append(task.subscription_id) %}
{% elif column.code == 'completed' and task.subscription_id not in metrics.completed %}{% set _ = metrics.completed.append(task.subscription_id) %}{% endif %}
{% if task.due_status_code == 'overdue' and task.subscription_id not in metrics.overdue %}{% set _ = metrics.overdue.append(task.subscription_id) %}{% endif %}
{% if task.due_status_code in ['today','soon'] and task.subscription_id not in metrics.due_soon %}{% set _ = metrics.due_soon.append(task.subscription_id) %}{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Pending Review</div>
<div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.pending_review|length }}</div>
<div class="mt-1 text-xs text-slate-500">Engagements with completed work awaiting review</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Clarification Required</div>
<div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.clarification_required|length }}</div>
<div class="mt-1 text-xs text-slate-500">Engagements with blocked tasks</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Rework Sent</div>
<div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.rework_sent|length }}</div>
<div class="mt-1 text-xs text-slate-500">Engagements containing rework items</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">In Progress</div>
<div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.approved|length }}</div>
<div class="mt-1 text-xs text-slate-500">Engagements currently moving with the team</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Completed</div>
<div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.completed|length }}</div>
<div class="mt-1 text-xs text-slate-500">Engagements containing closed tasks</div>
</div>
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-7">
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Pending Review</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.pending_review|length }}</div><div class="mt-1 text-xs text-slate-500">Awaiting partner review</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Clarification</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.clarification_required|length }}</div><div class="mt-1 text-xs text-slate-500">Blocked for clarification</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Rework</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.rework_sent|length }}</div><div class="mt-1 text-xs text-slate-500">Rework outstanding</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">In Progress</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.approved|length }}</div><div class="mt-1 text-xs text-slate-500">Moving with team</div></div>
<div class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Completed</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ metrics.completed|length }}</div><div class="mt-1 text-xs text-slate-500">Completed engagements</div></div>
<div class="rounded-2xl border border-red-200 bg-red-50 p-4"><div class="text-xs font-semibold uppercase tracking-wide text-red-600">Overdue</div><div class="mt-1 text-2xl font-semibold text-red-800">{{ metrics.overdue|length }}</div><div class="mt-1 text-xs text-red-600">Past engagement due date</div></div>
<div class="rounded-2xl border border-amber-200 bg-amber-50 p-4"><div class="text-xs font-semibold uppercase tracking-wide text-amber-700">Due ≤ 7 Days</div><div class="mt-1 text-2xl font-semibold text-amber-900">{{ metrics.due_soon|length }}</div><div class="mt-1 text-xs text-amber-700">Due today / next 7 days</div></div>
</div>
{# Each engagement appears in exactly one panel: review first, then in progress, then completed. #}
{# Exactly three board sections. Existing task-level states are preserved inside Review Required. #}
{% set groups = namespace(review=[], progress=[], completed=[]) %}
{% for column in payload.columns %}
{% if column.code in ['pending_review', 'clarification_required', 'rework_sent'] %}
{% for task in column.tasks %}
{% if task.subscription_id and task.subscription_id not in groups.review %}
{% set _ = groups.review.append(task.subscription_id) %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% for column in payload.columns %}
{% if column.code == 'approved' %}
{% for task in column.tasks %}
{% if task.subscription_id and task.subscription_id not in groups.review and task.subscription_id not in groups.progress %}
{% set _ = groups.progress.append(task.subscription_id) %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% for column in payload.columns %}
{% if column.code == 'completed' %}
{% for task in column.tasks %}
{% if task.subscription_id and task.subscription_id not in groups.review and task.subscription_id not in groups.progress and task.subscription_id not in groups.completed %}
{% set _ = groups.completed.append(task.subscription_id) %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% for column in payload.columns %}{% if column.code in ['pending_review', 'clarification_required', 'rework_sent'] %}{% for task in column.tasks %}{% if task.subscription_id and task.subscription_id not in groups.review %}{% set _ = groups.review.append(task.subscription_id) %}{% endif %}{% endfor %}{% endif %}{% endfor %}
{% for column in payload.columns %}{% if column.code == 'approved' %}{% for task in column.tasks %}{% if task.subscription_id and task.subscription_id not in groups.review and task.subscription_id not in groups.progress %}{% set _ = groups.progress.append(task.subscription_id) %}{% endif %}{% endfor %}{% endif %}{% endfor %}
{% for column in payload.columns %}{% if column.code == 'completed' %}{% for task in column.tasks %}{% if task.subscription_id and task.subscription_id not in groups.review and task.subscription_id not in groups.progress and task.subscription_id not in groups.completed %}{% set _ = groups.completed.append(task.subscription_id) %}{% endif %}{% endfor %}{% endif %}{% endfor %}
{% set review_page = request.query_params.get('review_page', '1')|int %}
{% set progress_page = request.query_params.get('progress_page', '1')|int %}
{% set completed_page = request.query_params.get('completed_page', '1')|int %}
{% set panel_page_size = 25 %}
{{ panel(
'Review Required',
'Pending review, clarification-required and rework engagements are shown first.',
groups.review,
payload,
'review',
'review_page',
review_page,
panel_page_size,
q or ''
) }}
{{ panel('Review Required', 'Pending review, clarification-required and rework engagements are shown first.', groups.review, payload, 'review', 'review_page', review_page, page_size, filter_query) }}
{{ panel('In Progress', 'Engagements currently moving with the team and not presently waiting in the review queue.', groups.progress, payload, 'progress', 'progress_page', progress_page, page_size, filter_query) }}
{{ panel('Completed', 'Completed engagement rows remain available separately for review history and reference.', groups.completed, payload, 'completed', 'completed_page', completed_page, page_size, filter_query) }}
{{ panel(
'In Progress',
'Engagements currently moving with the team and not presently waiting in the review queue.',
groups.progress,
payload,
'progress',
'progress_page',
progress_page,
panel_page_size,
q or ''
) }}
{{ panel(
'Completed',
'Completed engagement rows remain available separately for review history and reference.',
groups.completed,
payload,
'completed',
'completed_page',
completed_page,
panel_page_size,
q or ''
) }}
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-xs text-slate-500">
Review remains task-level inside the engagement. This board only groups the existing task records into one engagement row for easier partner navigation.
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-xs text-slate-500">Review remains task-level inside the engagement. This board only groups the existing task records into one engagement row for easier partner navigation.</div>
</div>
{% endblock %}