Fix Team Summary report — all 3 pivot tables + proper Kimai layout
Some checks failed
Actions Security Analysis / Scan workflows (push) Has been cancelled
Frontend / Frontend verification (push) Has been cancelled
Lint PHP / Linting (8.2) (push) Has been cancelled
Check .lock files / Verify lock file integrity (push) Has been cancelled
Release Drafter / Verify repository (push) Has been cancelled
Release Drafter / Draft next release (push) Has been cancelled
Tests / Integration (8.2) (push) Has been cancelled
Tests / Integration (8.3) (push) Has been cancelled
Tests / Integration (8.4) (push) Has been cancelled
Tests / Integration (8.5) (push) Has been cancelled
Some checks failed
Actions Security Analysis / Scan workflows (push) Has been cancelled
Frontend / Frontend verification (push) Has been cancelled
Lint PHP / Linting (8.2) (push) Has been cancelled
Check .lock files / Verify lock file integrity (push) Has been cancelled
Release Drafter / Verify repository (push) Has been cancelled
Release Drafter / Draft next release (push) Has been cancelled
Tests / Integration (8.2) (push) Has been cancelled
Tests / Integration (8.3) (push) Has been cancelled
Tests / Integration (8.4) (push) Has been cancelled
Tests / Integration (8.5) (push) Has been cancelled
- Billable Projects (billable=1), Non-Billable (billable=0), Unproductive (billable=2) - Uses Twig macro for DRY pivot table rendering - Extends Kimai reporting/layout.html.twig for proper navbar/breadcrumb - Team selector + date range in card header
This commit is contained in:
101
templates/reporting/team_summary.html.twig
Normal file
101
templates/reporting/team_summary.html.twig
Normal file
@@ -0,0 +1,101 @@
|
||||
{% extends 'reporting/layout.html.twig' %}
|
||||
|
||||
{% block report %}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<form method="get" class="row g-2 align-items-center">
|
||||
<div class="col-auto">
|
||||
<select name="team" class="form-select form-select-sm" onchange="this.form.submit()">
|
||||
<option value="">-- Select Team --</option>
|
||||
{% for t in teams %}
|
||||
<option value="{{ t.id }}" {% if selectedTeamId == t.id %}selected{% endif %}>{{ t.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input type="date" name="from" value="{{ from }}" class="form-control form-control-sm" onchange="this.form.submit()">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input type="date" name="to" value="{{ to }}" class="form-control form-control-sm" onchange="this.form.submit()">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% if team %}
|
||||
<div class="card-body">
|
||||
<h3>Time Analysis — {{ team.name }}</h3>
|
||||
<small class="text-muted">{{ from }} – {{ to }}</small>
|
||||
|
||||
{% if rows is empty %}
|
||||
<div class="alert alert-info mt-3">No time entries found for this period.</div>
|
||||
{% else %}
|
||||
<table class="table table-striped table-hover table-sm mt-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th class="text-end">Billable</th>
|
||||
<th class="text-end">Non-Billable</th>
|
||||
<th class="text-end">Unproductive</th>
|
||||
<th class="text-end">Total Hours</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% set tb = 0 %}{% set tn = 0 %}{% set tu = 0 %}{% set tt = 0 %}
|
||||
{% for r in rows %}
|
||||
{% set tb = tb + r.billable_hours %}
|
||||
{% set tn = tn + r.nonbillable_hours %}
|
||||
{% set tu = tu + r.unproductive_hours %}
|
||||
{% set tt = tt + r.total_hours %}
|
||||
<tr>
|
||||
<td>{{ r.alias ?: r.username }}</td>
|
||||
<td class="text-end">{{ r.billable_hours|number_format(2) }}</td>
|
||||
<td class="text-end">{{ r.nonbillable_hours|number_format(2) }}</td>
|
||||
<td class="text-end">{{ r.unproductive_hours|number_format(2) }}</td>
|
||||
<td class="text-end"><strong>{{ r.total_hours|number_format(2) }}</strong></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="table-active fw-bold">
|
||||
<td>TOTAL</td>
|
||||
<td class="text-end">{{ tb|number_format(2) }}</td>
|
||||
<td class="text-end">{{ tn|number_format(2) }}</td>
|
||||
<td class="text-end">{{ tu|number_format(2) }}</td>
|
||||
<td class="text-end">{{ tt|number_format(2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% macro pivot(rows, cols, title) %}
|
||||
{% if rows is not empty %}
|
||||
<h4 class="mt-4">{{ title }}</h4>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover table-sm" style="font-size:11px">
|
||||
<thead><tr>
|
||||
<th>Company</th><th>Project</th>
|
||||
{% for uc in cols %}<th class="text-end">{{ uc }}</th>{% endfor %}
|
||||
<th class="text-end">TOTAL</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{% for pr in rows %}
|
||||
<tr>
|
||||
<td>{{ pr.company }}</td>
|
||||
<td>{{ pr.project }}</td>
|
||||
{% for uc in cols %}
|
||||
<td class="text-end">{{ pr.users[uc]|default(0) > 0 ? pr.users[uc]|number_format(1) }}</td>
|
||||
{% endfor %}
|
||||
<td class="text-end"><strong>{{ pr.total|number_format(1) }}</strong></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table></div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% import _self as self %}
|
||||
{{ self.pivot(projectRows, userColumns, 'Billable Projects') }}
|
||||
{{ self.pivot(nonbillRows, userColumnsNB, 'Non-Billable Projects') }}
|
||||
{{ self.pivot(unprodRows, userColumnsUP, 'Unproductive Projects') }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user