|
|
|
@@ -42,12 +42,29 @@
|
|
|
|
|
<td>✅ Zakupione</td>
|
|
|
|
|
<td class="text-end fw-bold">{{ purchased_items_count }}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>🚫 Nieoznaczone jako kupione</td>
|
|
|
|
|
<td class="text-end fw-bold">{{ not_purchased_count }}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>✍️ Produkty z notatkami</td>
|
|
|
|
|
<td class="text-end fw-bold">{{ items_with_notes }}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>🕓 Śr. czas do zakupu (h)</td>
|
|
|
|
|
<td class="text-end fw-bold">{{ avg_hours_to_purchase }}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>💸 Średnia kwota na listę</td>
|
|
|
|
|
<td class="text-end fw-bold">{{ avg_list_expense }} zł</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Najczęściej kupowane -->
|
|
|
|
|
<div class="col-md-4">
|
|
|
|
|
<div class="card bg-dark text-white h-100">
|
|
|
|
@@ -79,17 +96,18 @@
|
|
|
|
|
|
|
|
|
|
<!-- Podsumowanie wydatków -->
|
|
|
|
|
<div class="col-md-4">
|
|
|
|
|
<div class="card bg-dark text-white h-100">
|
|
|
|
|
<div class="card bg-dark text-white h-100 shadow-sm">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<h5>💸 Podsumowanie wydatków:</h5>
|
|
|
|
|
<h5 class="mb-3">💸 Podsumowanie wydatków</h5>
|
|
|
|
|
|
|
|
|
|
<table class="table table-dark table-sm mb-3">
|
|
|
|
|
<thead>
|
|
|
|
|
<table class="table table-dark table-sm mb-3 align-middle">
|
|
|
|
|
<thead class="text-muted small">
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Typ listy</th>
|
|
|
|
|
<th>Miesiąc</th>
|
|
|
|
|
<th>Rok</th>
|
|
|
|
|
<th>Całkowite</th>
|
|
|
|
|
<th title="Rodzaj listy zakupowej">Typ listy</th>
|
|
|
|
|
<th title="Wydatki w bieżącym miesiącu">Miesiąc</th>
|
|
|
|
|
<th title="Wydatki w bieżącym roku">Rok</th>
|
|
|
|
|
<th title="Wydatki łączne">Całkowite</th>
|
|
|
|
|
<th title="Średnia kwota na 1 listę">Średnia</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
@@ -98,225 +116,247 @@
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.all.month) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.all.year) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.all.total) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.all.avg) }} PLN</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Aktywne</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.active.month) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.active.year) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.active.total) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.active.avg) }} PLN</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Archiwalne</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.archived.month) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.archived.year) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.archived.total) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.archived.avg) }} PLN</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Wygasłe</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.expired.month) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.expired.year) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.expired.total) }} PLN</td>
|
|
|
|
|
<td>{{ '%.2f'|format(expense_summary.expired.avg) }} PLN</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
<div class="mb-3">
|
|
|
|
|
<div class="small text-uppercase mb-1">📈 Średnie tempo tworzenia list:</div>
|
|
|
|
|
<ul class="list-unstyled small mb-0">
|
|
|
|
|
<li>📆 Tygodniowo: <strong>{{ avg_per_week }}</strong></li>
|
|
|
|
|
<li>🗓️ Miesięcznie: <strong>{{ avg_per_month }}</strong></li>
|
|
|
|
|
<li>📅 Rocznie: <strong>{{ avg_per_year }}</strong></li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<a href="{{ url_for('expenses') }}#chartTab" class="btn btn-outline-light w-100">
|
|
|
|
|
📊 Pokaż wykres wydatków
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{# panel wyboru miesiąca zawsze widoczny #}
|
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
|
|
|
|
|
|
|
|
|
|
{# LEWA STRONA — przyciski ← → TYLKO gdy nie show_all #}
|
|
|
|
|
<div class="d-flex gap-2">
|
|
|
|
|
{% if not show_all %}
|
|
|
|
|
{% set current_date = now.replace(day=1) %}
|
|
|
|
|
{% set prev_month = (current_date - timedelta(days=1)).strftime('%Y-%m') %}
|
|
|
|
|
{% set next_month = (current_date + timedelta(days=31)).replace(day=1).strftime('%Y-%m') %}
|
|
|
|
|
{# panel wyboru miesiąca zawsze widoczny #}
|
|
|
|
|
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
|
|
|
|
|
|
|
|
|
|
{% if prev_month in month_options %}
|
|
|
|
|
<a href="{{ url_for('admin_panel', m=prev_month) }}" class="btn btn-outline-light btn-sm">
|
|
|
|
|
← {{ prev_month }}
|
|
|
|
|
</a>
|
|
|
|
|
{% else %}
|
|
|
|
|
<button class="btn btn-outline-light btn-sm opacity-50" disabled>← {{ prev_month }}</button>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{# LEWA STRONA — przyciski ← → TYLKO gdy nie show_all #}
|
|
|
|
|
<div class="d-flex gap-2">
|
|
|
|
|
{% if not show_all %}
|
|
|
|
|
{% set current_date = now.replace(day=1) %}
|
|
|
|
|
{% set prev_month = (current_date - timedelta(days=1)).strftime('%Y-%m') %}
|
|
|
|
|
{% set next_month = (current_date + timedelta(days=31)).replace(day=1).strftime('%Y-%m') %}
|
|
|
|
|
|
|
|
|
|
{% if next_month in month_options %}
|
|
|
|
|
<a href="{{ url_for('admin_panel', m=next_month) }}" class="btn btn-outline-light btn-sm">
|
|
|
|
|
{{ next_month }} →
|
|
|
|
|
</a>
|
|
|
|
|
{% else %}
|
|
|
|
|
<button class="btn btn-outline-light btn-sm opacity-50" disabled>{{ next_month }} →</button>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% else %}
|
|
|
|
|
{# Tryb wszystkie miesiące — możemy pokazać skrót do bieżącego miesiąca #}
|
|
|
|
|
<a href="{{ url_for('admin_panel', m=now.strftime('%Y-%m')) }}" class="btn btn-outline-light btn-sm">
|
|
|
|
|
📅 Przejdź do bieżącego miesiąca
|
|
|
|
|
</a>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{# PRAWA STRONA — picker miesięcy zawsze widoczny #}
|
|
|
|
|
<form method="get" class="m-0">
|
|
|
|
|
<div class="input-group input-group-sm">
|
|
|
|
|
<span class="input-group-text bg-secondary text-white">📅</span>
|
|
|
|
|
<select name="m" class="form-select bg-dark text-white border-secondary" onchange="this.form.submit()">
|
|
|
|
|
<option value="all" {% if show_all %}selected{% endif %}>Wszystkie miesiące</option>
|
|
|
|
|
{% for val in month_options %}
|
|
|
|
|
{% set date_obj = (val ~ '-01') | todatetime %}
|
|
|
|
|
<option value="{{ val }}" {% if month_str==val %}selected{% endif %}>
|
|
|
|
|
{{ date_obj.strftime('%B %Y')|capitalize }}
|
|
|
|
|
</option>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="card bg-dark text-white mb-5">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<h3 class="mt-4">
|
|
|
|
|
📄 Listy zakupowe
|
|
|
|
|
{% if show_all %}
|
|
|
|
|
— <strong>wszystkie miesiące</strong>
|
|
|
|
|
{% if prev_month in month_options %}
|
|
|
|
|
<a href="{{ url_for('admin_panel', m=prev_month) }}" class="btn btn-outline-light btn-sm">
|
|
|
|
|
← {{ prev_month }}
|
|
|
|
|
</a>
|
|
|
|
|
{% else %}
|
|
|
|
|
— <strong>{{ month_str|replace('-', ' / ') }}</strong>
|
|
|
|
|
<button class="btn btn-outline-light btn-sm opacity-50" disabled>← {{ prev_month }}</button>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</h3>
|
|
|
|
|
<form method="post" action="{{ url_for('delete_selected_lists') }}">
|
|
|
|
|
<div class="table-responsive">
|
|
|
|
|
<table class="table table-dark table-striped align-middle sortable">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th><input type="checkbox" id="select-all"></th>
|
|
|
|
|
<th>ID</th>
|
|
|
|
|
<th>Tytuł</th>
|
|
|
|
|
<th>Status</th>
|
|
|
|
|
<th>Utworzono</th>
|
|
|
|
|
<th>Właściciel</th>
|
|
|
|
|
<th>Produkty</th>
|
|
|
|
|
<th>Progress</th>
|
|
|
|
|
<th>Koment.</th>
|
|
|
|
|
<th>Paragony</th>
|
|
|
|
|
<th>Wydatki</th>
|
|
|
|
|
<th>Akcje</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{% for e in enriched_lists %}
|
|
|
|
|
{% set l = e.list %}
|
|
|
|
|
<tr>
|
|
|
|
|
<td><input type="checkbox" name="list_ids" value="{{ l.id }}"></td>
|
|
|
|
|
<td>{{ l.id }}</td>
|
|
|
|
|
<td class="fw-bold align-middle">
|
|
|
|
|
<a href="{{ url_for('view_list', list_id=l.id) }}" class="text-white">{{ l.title }}</a>
|
|
|
|
|
{% if l.categories %}
|
|
|
|
|
<span class="ms-1 text-info" data-bs-toggle="tooltip"
|
|
|
|
|
title="{{ l.categories | map(attribute='name') | join(', ') }}">
|
|
|
|
|
🏷
|
|
|
|
|
</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
<td>
|
|
|
|
|
{% if l.is_archived %}
|
|
|
|
|
<span class="badge rounded-pill bg-secondary">Archiwalna</span>
|
|
|
|
|
{% elif e.expired %}
|
|
|
|
|
<span class="badge rounded-pill bg-warning text-dark">Wygasła</span>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="badge rounded-pill bg-success">Aktywna</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>{{ l.created_at.strftime('%Y-%m-%d %H:%M') if l.created_at else '-' }}</td>
|
|
|
|
|
<td>
|
|
|
|
|
{% if l.owner %}
|
|
|
|
|
👤 {{ l.owner.username }} ({{ l.owner.id }})
|
|
|
|
|
{% else %}
|
|
|
|
|
-
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>{{ e.total_count }}</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="progress bg-transparent" style=" height: 14px;">
|
|
|
|
|
<div class="progress-bar fw-bold text-black text-cente
|
|
|
|
|
{% if e.percent >= 80 %}bg-success
|
|
|
|
|
{% elif e.percent >= 40 %}bg-warning
|
|
|
|
|
{% else %}bg-danger{% endif %}" role="progressbar" style="width: {{ e.percent }}%">
|
|
|
|
|
{{ e.purchased_count }}/{{ e.total_count }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
<td><span class="badge rounded-pill bg-primary">{{ e.comments_count }}</span></td>
|
|
|
|
|
<td><span class="badge rounded-pill bg-secondary">{{ e.receipts_count }}</span></td>
|
|
|
|
|
<td class="fw-bold
|
|
|
|
|
{% if e.total_expense >= 500 %}text-danger
|
|
|
|
|
{% elif e.total_expense > 0 %}text-success{% endif %}">
|
|
|
|
|
{% if e.total_expense > 0 %}
|
|
|
|
|
{{ '%.2f'|format(e.total_expense) }} PLN
|
|
|
|
|
{% else %}
|
|
|
|
|
-
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="btn-group btn-group-sm" role="group">
|
|
|
|
|
<a href="{{ url_for('edit_list', list_id=l.id) }}" class="btn btn-sm btn-outline-light"
|
|
|
|
|
title="Edytuj">✏️</a>
|
|
|
|
|
<button type="button" class="btn btn-sm btn-outline-light preview-btn" data-list-id="{{ l.id }}"
|
|
|
|
|
title="Podgląd produktów">
|
|
|
|
|
👁️
|
|
|
|
|
</button>
|
|
|
|
|
<a href="{{ url_for('delete_list', list_id=l.id) }}" class="btn btn-sm btn-outline-light"
|
|
|
|
|
onclick="return confirm('Na pewno usunąć tę listę?')" title="Usuń">🗑️</a>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="d-flex justify-content-end mt-2">
|
|
|
|
|
<button type="submit" class="btn btn-outline-light btn-sm">🗑️ Usuń zaznaczone listy</button>
|
|
|
|
|
{% if next_month in month_options %}
|
|
|
|
|
<a href="{{ url_for('admin_panel', m=next_month) }}" class="btn btn-outline-light btn-sm">
|
|
|
|
|
{{ next_month }} →
|
|
|
|
|
</a>
|
|
|
|
|
{% else %}
|
|
|
|
|
<button class="btn btn-outline-light btn-sm opacity-50" disabled>{{ next_month }} →</button>
|
|
|
|
|
{% endif %}
|
|
|
|
|
{% else %}
|
|
|
|
|
{# Tryb wszystkie miesiące — możemy pokazać skrót do bieżącego miesiąca #}
|
|
|
|
|
<a href="{{ url_for('admin_panel', m=now.strftime('%Y-%m')) }}" class="btn btn-outline-light btn-sm">
|
|
|
|
|
📅 Przejdź do bieżącego miesiąca
|
|
|
|
|
</a>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{# PRAWA STRONA — picker miesięcy zawsze widoczny #}
|
|
|
|
|
<form method="get" class="m-0">
|
|
|
|
|
<div class="input-group input-group-sm">
|
|
|
|
|
<span class="input-group-text bg-secondary text-white">📅</span>
|
|
|
|
|
<select name="m" class="form-select bg-dark text-white border-secondary" onchange="this.form.submit()">
|
|
|
|
|
<option value="all" {% if show_all %}selected{% endif %}>Wszystkie miesiące</option>
|
|
|
|
|
{% for val in month_options %}
|
|
|
|
|
{% set date_obj = (val ~ '-01') | todatetime %}
|
|
|
|
|
<option value="{{ val }}" {% if month_str==val %}selected{% endif %}>
|
|
|
|
|
{{ date_obj.strftime('%B %Y')|capitalize }}
|
|
|
|
|
</option>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</select>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="info-bar-fixed">
|
|
|
|
|
Python: {{ python_version.split()[0] }} | {{ system_info }} | RAM app: {{ app_memory }} |
|
|
|
|
|
DB: {{ db_info.engine|upper }}{% if db_info.version %} v{{ db_info.version[0] }}{% endif %} |
|
|
|
|
|
Tabele: {{ table_count }} | Rekordy: {{ record_total }} |
|
|
|
|
|
Uptime: {{ uptime_minutes }} min
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card bg-dark text-white mb-5">
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
<h3 class="mt-4">
|
|
|
|
|
📄 Listy zakupowe
|
|
|
|
|
{% if show_all %}
|
|
|
|
|
— <strong>wszystkie miesiące</strong>
|
|
|
|
|
{% else %}
|
|
|
|
|
— <strong>{{ month_str|replace('-', ' / ') }}</strong>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</h3>
|
|
|
|
|
<form method="post" action="{{ url_for('admin_delete_list') }}">
|
|
|
|
|
<div class="table-responsive">
|
|
|
|
|
<table class="table table-dark table-striped align-middle sortable">
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th><input type="checkbox" id="select-all"></th>
|
|
|
|
|
<th>ID</th>
|
|
|
|
|
<th>Tytuł</th>
|
|
|
|
|
<th>Status</th>
|
|
|
|
|
<th>Utworzono</th>
|
|
|
|
|
<th>Właściciel</th>
|
|
|
|
|
<th>Produkty</th>
|
|
|
|
|
<th>Progress</th>
|
|
|
|
|
<th>Koment.</th>
|
|
|
|
|
<th>Paragony</th>
|
|
|
|
|
<th>Wydatki</th>
|
|
|
|
|
<th>Akcje</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
{% for e in enriched_lists %}
|
|
|
|
|
{% set l = e.list %}
|
|
|
|
|
<tr>
|
|
|
|
|
<td><input type="checkbox" name="list_ids" value="{{ l.id }}"></td>
|
|
|
|
|
<td>{{ l.id }}</td>
|
|
|
|
|
<td class="fw-bold align-middle">
|
|
|
|
|
<a href="{{ url_for('view_list', list_id=l.id) }}" class="text-white">{{ l.title }}</a>
|
|
|
|
|
{% if l.categories %}
|
|
|
|
|
<span class="ms-1 text-info" data-bs-toggle="tooltip"
|
|
|
|
|
title="{{ l.categories | map(attribute='name') | join(', ') }}">
|
|
|
|
|
🏷
|
|
|
|
|
</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
|
|
|
|
|
<!-- Modal podglądu produktów -->
|
|
|
|
|
<div class="modal fade" id="productPreviewModal" tabindex="-1" aria-labelledby="previewModalLabel" aria-hidden="true">
|
|
|
|
|
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
|
|
|
|
<div class="modal-content bg-dark text-white">
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
<h5 class="modal-title" id="previewModalLabel">Podgląd produktów</h5>
|
|
|
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Zamknij"></button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
<ul id="product-list" class="list-group list-group-flush"></ul>
|
|
|
|
|
<td>
|
|
|
|
|
{% if l.is_archived %}
|
|
|
|
|
<span class="badge rounded-pill bg-secondary">Archiwalna</span>
|
|
|
|
|
{% elif e.expired %}
|
|
|
|
|
<span class="badge rounded-pill bg-warning text-dark">Wygasła</span>
|
|
|
|
|
{% else %}
|
|
|
|
|
<span class="badge rounded-pill bg-success">Aktywna</span>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>{{ l.created_at.strftime('%Y-%m-%d %H:%M') if l.created_at else '-' }}</td>
|
|
|
|
|
<td>
|
|
|
|
|
{% if l.owner %}
|
|
|
|
|
👤 {{ l.owner.username }} ({{ l.owner.id }})
|
|
|
|
|
{% else %}
|
|
|
|
|
-
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>{{ e.total_count }}</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="progress bg-transparent" style=" height: 14px;">
|
|
|
|
|
<div class="progress-bar fw-bold text-black text-cente
|
|
|
|
|
{% if e.percent >= 80 %}bg-success
|
|
|
|
|
{% elif e.percent >= 40 %}bg-warning
|
|
|
|
|
{% else %}bg-danger{% endif %}" role="progressbar" style="width: {{ e.percent }}%">
|
|
|
|
|
{{ e.purchased_count }}/{{ e.total_count }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
<td><span class="badge rounded-pill bg-primary">{{ e.comments_count }}</span></td>
|
|
|
|
|
<td><span class="badge rounded-pill bg-secondary">{{ e.receipts_count }}</span></td>
|
|
|
|
|
<td class="fw-bold
|
|
|
|
|
{% if e.total_expense >= 500 %}text-danger
|
|
|
|
|
{% elif e.total_expense > 0 %}text-success{% endif %}">
|
|
|
|
|
{% if e.total_expense > 0 %}
|
|
|
|
|
{{ '%.2f'|format(e.total_expense) }} PLN
|
|
|
|
|
{% else %}
|
|
|
|
|
-
|
|
|
|
|
{% endif %}
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="btn-group btn-group-sm" role="group">
|
|
|
|
|
<a href="{{ url_for('edit_list', list_id=l.id) }}" class="btn btn-sm btn-outline-light"
|
|
|
|
|
title="Edytuj">✏️</a>
|
|
|
|
|
<button type="button" class="btn btn-sm btn-outline-light preview-btn" data-list-id="{{ l.id }}"
|
|
|
|
|
title="Podgląd produktów">
|
|
|
|
|
👁️
|
|
|
|
|
</button>
|
|
|
|
|
<form method="post" action="{{ url_for('admin_delete_list') }}"
|
|
|
|
|
onsubmit="return confirm('Na pewno usunąć tę listę?')" class="d-inline">
|
|
|
|
|
<input type="hidden" name="single_list_id" value="{{ l.id }}">
|
|
|
|
|
<button type="submit" class="btn btn-sm btn-outline-light" title="Usuń">🗑️</button>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
{% if enriched_lists|length == 0 %}
|
|
|
|
|
<tr>
|
|
|
|
|
<td colspan="12" class="text-center py-4">
|
|
|
|
|
Brak list zakupowych do wyświetlenia
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="d-flex justify-content-end mt-2">
|
|
|
|
|
<button type="submit" class="btn btn-outline-light btn-sm">🗑️ Usuń zaznaczone listy</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="info-bar-fixed">
|
|
|
|
|
Python: {{ python_version.split()[0] }} | {{ system_info }} | RAM app: {{ app_memory }} |
|
|
|
|
|
DB: {{ db_info.engine|upper }}{% if db_info.version %} v{{ db_info.version[0] }}{% endif %} |
|
|
|
|
|
Tabele: {{ table_count }} | Rekordy: {{ record_total }} |
|
|
|
|
|
Uptime: {{ uptime_minutes }} min
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Modal podglądu produktów -->
|
|
|
|
|
<div class="modal fade" id="productPreviewModal" tabindex="-1" aria-labelledby="previewModalLabel" aria-hidden="true">
|
|
|
|
|
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
|
|
|
|
<div class="modal-content bg-dark text-white">
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
<h5 class="modal-title" id="previewModalLabel">Podgląd produktów</h5>
|
|
|
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Zamknij"></button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
<ul id="product-list" class="list-group list-group-flush"></ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{% block scripts %}
|
|
|
|
|
<script>
|
|
|
|
|
document.getElementById('select-all').addEventListener('click', function () {
|
|
|
|
|
const checkboxes = document.querySelectorAll('input[name="list_ids"]');
|
|
|
|
|
checkboxes.forEach(cb => cb.checked = this.checked);
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
<script src="{{ url_for('static_bp.serve_js', filename='preview_list_modal.js') }}"></script>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
{% block scripts %}
|
|
|
|
|
<script>
|
|
|
|
|
document.getElementById('select-all').addEventListener('click', function () {
|
|
|
|
|
const checkboxes = document.querySelectorAll('input[name="list_ids"]');
|
|
|
|
|
checkboxes.forEach(cb => cb.checked = this.checked);
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
<script src="{{ url_for('static_bp.serve_js', filename='preview_list_modal.js') }}"></script>
|
|
|
|
|
{% endblock %}
|
|
|
|
|
|
|
|
|
|
{% endblock %}
|
|
|
|
|
{% endblock %}
|