Files
TimeTracker/templates/projects/client_view.html
Dries Peeters 69f9f1140d feat(i18n): add translations, locale switcher, and user language preference
- Integrate Flask-Babel and i18n utilities; initialize in app factory
- Add `preferred_language` to `User` with Alembic migration (011_add_user_preferred_language)
- Add `babel.cfg` and `scripts/extract_translations.py`
- Add `translations/` for en, de, fr, it, nl, fi
- Update templates to use `_()` and add language picker in navbar/profile
- Respect locale in routes and context processors; persist user preference
- Update requirements and Docker/Docker entrypoint for Babel/gettext support
- Minor copy and style adjustments across pages

Migration: run `alembic upgrade head`
2025-09-11 23:08:41 +02:00

89 lines
4.2 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ _('Client') }} - {{ client_name }} - {{ app_name }}{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="h3 mb-0">
<i class="fas fa-briefcase text-primary"></i> {{ client_name }}
</h1>
<a href="{{ url_for('projects.list_clients') }}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left"></i> {{ _('Back to Clients') }}
</a>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0"><i class="fas fa-list me-1"></i> {{ _('Projects') }} ({{ projects|length }})</h5>
</div>
<div class="card-body">
{% if projects %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>{{ _('Project') }}</th>
<th>{{ _('Status') }}</th>
<th>{{ _('Total Hours') }}</th>
<th>{{ _('Billable Hours') }}</th>
<th>{{ _('Actions') }}</th>
</tr>
</thead>
<tbody>
{% for project in projects %}
<tr>
<td>
<a href="{{ url_for('projects.view_project', project_id=project.id) }}">
<strong>{{ project.name }}</strong>
</a>
{% if project.description %}
<br><small class="text-muted">{{ project.description[:100] }}{% if project.description|length > 100 %}...{% endif %}</small>
{% endif %}
</td>
<td>
{% if project.status == 'active' %}
<span class="badge bg-success">{{ _('Active') }}</span>
{% else %}
<span class="badge bg-secondary">{{ _('Archived') }}</span>
{% endif %}
</td>
<td><strong>{{ "%.1f"|format(project.total_hours) }}h</strong></td>
<td>
{% if project.billable %}
<span class="text-success">{{ "%.1f"|format(project.total_billable_hours) }}h</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<a href="{{ url_for('projects.view_project', project_id=project.id) }}" class="btn btn-sm btn-outline-primary">
<i class="fas fa-eye"></i> {{ _('View') }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-5">
<i class="fas fa-folder-open fa-3x text-muted mb-3"></i>
<h4 class="text-muted">{{ _('No Projects for this Client') }}</h4>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}