{% extends "client_portal/base.html" %} {% from "components/ui.html" import page_header %} {% block title %}{{ _('Reports') }} - {{ _('Client Portal') }}{% endblock %} {% block content %} {% set breadcrumbs = [ {'text': _('Client Portal'), 'url': url_for('client_portal.dashboard')}, {'text': _('Reports')} ] %} {{ page_header( icon_class='fas fa-chart-bar', title_text=_('Reports'), subtitle_text=_('Project and invoice summaries') + (' — ' + (_('Last %(days)s days') % {'days': date_range_days}) if (date_range_days is defined and date_range_days) else ''), breadcrumbs=breadcrumbs ) }}
{{ _('Total Hours') }}
{{ "%.1f"|format(total_hours) }}
{{ _('Hours tracked') }}
{{ _('Total Invoiced') }}
{{ "%.2f"|format(invoice_summary.total) }}
EUR
{{ _('Paid') }}
{{ "%.2f"|format(invoice_summary.paid) }}
EUR
{{ _('Outstanding') }}
{{ "%.2f"|format(invoice_summary.unpaid) }}
EUR
| {{ _('Project') }} | {{ _('Status') }} | {{ _('Total Hours') }} | {{ _('Billable Hours') }} | {{ _('Est. / Budget') }} |
|---|---|---|---|---|
|
{{ ph.project.name if ph.project else _('N/A') }}
|
{{ (ph.project.status if ph.project else 'active')|capitalize }} | {{ "%.2f"|format(ph.hours) }}h | {{ "%.2f"|format(ph.billable_hours) }}h | {% if ph.get('estimated_hours') %}{{ "%.1f"|format(ph.estimated_hours) }}h{% endif %} {% if ph.get('estimated_hours') and ph.get('budget_amount') %} / {% endif %} {% if ph.get('budget_amount') %}{{ "%.2f"|format(ph.budget_amount) }} EUR{% endif %} {% if not ph.get('estimated_hours') and not ph.get('budget_amount') %}—{% endif %} |
{{ _('No project hours data available.') }}
{{ _('Total tasks: %(count)s', count=task_summary.total) }}
{% if task_summary.by_status %}{{ _('No tasks yet.') }}
{% endif %}| {{ _('Date') }} | {{ _('Hours') }} |
|---|---|
| {{ row.date }} | {{ "%.2f"|format(row.hours) }}h |
| {{ _('Date') }} | {{ _('Project') }} | {{ _('Duration') }} | {{ _('User') }} |
|---|---|---|---|
|
{{ entry.start_time|user_date if entry.start_time else _('N/A') }}
|
{{ entry.project.name if entry.project else _('N/A') }}
|
{{ "%.2f"|format(entry.duration_hours) }}h |
|
{{ _('No recent time entries.') }}