duzo zmian ux w panelu

This commit is contained in:
Mateusz Gruszczyński
2025-08-14 23:55:58 +02:00
parent 97cebbdd49
commit 4f40bb06b3
8 changed files with 301 additions and 159 deletions

View File

@@ -263,18 +263,14 @@
</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">
<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>
<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>
@@ -298,18 +294,17 @@
<!-- 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 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>
{% block scripts %}

View File

@@ -13,74 +13,90 @@
<form method="post" class="mt-3">
<input type="hidden" name="action" value="save">
<!-- Nazwa listy -->
<div class="mb-3">
<label for="title" class="form-label">Nazwa listy</label>
<label for="title" class="form-label">📝 Nazwa listy</label>
<input type="text" class="form-control bg-dark text-white border-secondary rounded" id="title" name="title"
value="{{ list.title }}" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Całkowity wydatek (PLN)</label>
<input type="number" step="0.01" min="0" class="form-control bg-dark text-white border-secondary rounded"
id="amount" name="amount" value="{{ '%.2f'|format(total_expense) }}">
<!-- Wydatek i właściciel -->
<div class="row mb-3">
<div class="col-md-6">
<label for="amount" class="form-label">💰 Całkowity wydatek (PLN)</label>
<input type="number" step="0.01" min="0" class="form-control bg-dark text-white border-secondary rounded"
id="amount" name="amount" value="{{ '%.2f'|format(total_expense) }}">
</div>
<div class="col-md-6">
<label for="owner_id" class="form-label">👤 Właściciel</label>
<select class="form-select bg-dark text-white border-secondary" id="owner_id" name="owner_id">
{% for user in users %}
<option value="{{ user.id }}" {% if list.owner_id==user.id %}selected{% endif %}>
{{ user.username }}
</option>
{% endfor %}
</select>
</div>
</div>
<div class="mb-3">
<label for="owner_id" class="form-label">Właściciel</label>
<select class="form-select bg-dark text-white border-secondary" id="owner_id" name="owner_id">
{% for user in users %}
<option value="{{ user.id }}" {% if list.owner_id==user.id %}selected{% endif %}>{{ user.username }}</option>
{% endfor %}
</select>
<!-- Statusy -->
<div class="mb-4">
<label class="form-label">⚙️ Statusy listy</label>
<div class="d-flex flex-wrap gap-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="archived" name="archived" {% if list.is_archived
%}checked{% endif %}>
<label class="form-check-label" for="archived">📦 Archiwalna</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="public" name="public" {% if list.is_public %}checked{%
endif %}>
<label class="form-check-label" for="public">🌐 Publiczna</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="temporary" name="temporary" {% if list.is_temporary
%}checked{% endif %}>
<label class="form-check-label" for="temporary">⏳ Tymczasowa (podaj date i godzine wygasania)</label>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="archived" name="archived" {% if list.is_archived %}checked{%
endif %}>
<label class="form-check-label" for="archived">Archiwalna</label>
</div>
<div class="form-check form-switch mb-4">
<input class="form-check-input" type="checkbox" id="public" name="public" {% if list.is_public %}checked{% endif
%}>
<label class="form-check-label" for="public">Publiczna</label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" id="temporary" name="temporary" {% if list.is_temporary
%}checked{% endif %}>
<label class="form-check-label" for="temporary">Tymczasowa</label>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="expires_date" class="form-label">Data wygaśnięcia</label>
<!-- Data/godzina wygaśnięcia -->
<div class="row mb-4">
<div class="col-md-6">
<label for="expires_date" class="form-label">📅 Data wygaśnięcia</label>
<input type="date" class="form-control bg-dark text-white border-secondary rounded" id="expires_date"
name="expires_date" value="{{ list.expires_at.strftime('%Y-%m-%d') if list.expires_at else '' }}">
</div>
<div class="col-md-6 mb-3">
<label for="expires_time" class="form-label">Godzina wygaśnięcia</label>
<div class="col-md-6">
<label for="expires_time" class="form-label">Godzina wygaśnięcia</label>
<input type="time" class="form-control bg-dark text-white border-secondary rounded" id="expires_time"
name="expires_time" value="{{ list.expires_at.strftime('%H:%M') if list.expires_at else '' }}">
</div>
</div>
<div class="row mb-3">
<!-- Utworzono / Zmień miesiąc -->
<div class="row mb-4">
<div class="col-md-6">
<label class="form-label">Aktualna data utworzenia listy</label>
<label class="form-label">📆 Utworzono</label>
<p class="form-control-plaintext text-white">
{{ list.created_at.strftime('%Y-%m-%d') }}
</p>
</div>
<div class="col-md-6">
<label for="created_month" class="form-label">Przenieś listę do miesiąca</label>
<label for="created_month" class="form-label">📁 Przenieś do miesiąca</label>
<input type="month" id="created_month" name="created_month"
class="form-control bg-dark text-white border-secondary rounded">
</div>
</div>
<!-- Kategorie -->
<div class="mb-4">
<label class="form-label">Kategorie</label>
<label for="categories" class="form-label">🏷️ Kategorie</label>
<select id="categories" name="categories"
class="form-select tom-dark bg-dark text-white border-secondary rounded">
<option value=""> brak </option>
@@ -92,20 +108,23 @@
</select>
</div>
<!-- Link udostępnienia -->
<div class="mb-4">
<label class="form-label">Link do udostępnienia</label>
<label class="form-label">🔗 Link do udostępnienia</label>
<input type="text" class="form-control bg-dark text-white border-secondary rounded" readonly
value="{{ request.url_root }}share/{{ list.share_token }}">
</div>
<button type="submit" class="btn btn-success me-2">💾 Zapisz zmiany</button>
</form>
</div>
</div>
<div class="card bg-dark text-white mb-5">
<div class="card-body">
<h4 class="card-title">🛒 Produkty</h4>
<h4 class="card-title">📝 Produkty</h4>
<form method="post" class="row g-2 mb-3">
<input type="hidden" name="action" value="add_item">
<div class="col-md-8">
@@ -125,10 +144,12 @@
<table class="table table-dark table-bordered align-middle">
<thead>
<tr>
<th scope="col">Nazwa</th>
<th scope="col">Status</th>
<th scope="col">Oznaczenie</th>
<th scope="col">Usuń</th>
<th>Nazwa produktu</th>
<th>Notatka</th>
<th>Ilość</th>
<th>Aktualny stan</th>
<th>Akcja</th>
<th>Usuń</th>
</tr>
</thead>
<tbody>
@@ -136,26 +157,21 @@
<tr>
<td>
<strong>{{ item.name }}</strong>
<small class="text-small text-success">(x{{ item.quantity }})</small>
</td>
<td>
{% if item.note %}
<div class="text-info small mt-1">
<strong>Notatka:</strong> {{ item.note }}
</div>
<div class="text-info small mt-1"><strong>Notatka:</strong> {{ item.note }}</div>
{% endif %}
{% if item.not_purchased_reason %}
<div class="text-warning small mt-1">
<strong>Powód:</strong> {{ item.not_purchased_reason }}
</div>
<div class="text-warning small mt-1"><strong>Powód:</strong> {{ item.not_purchased_reason }}</div>
{% endif %}
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}" class="mt-2">
</td>
<td>
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}">
<input type="hidden" name="action" value="edit_quantity">
<input type="hidden" name="item_id" value="{{ item.id }}">
<div class="input-group input-group-sm ">
<input type="number" name="quantity"
class="form-control bg-dark text-white border-secondary rounded-left" min="1"
<div class="input-group input-group-sm w-auto">
<input type="number" name="quantity" class="form-control bg-dark text-white border-secondary" min="1"
value="{{ item.quantity }}">
<button type="submit" class="btn btn-outline-light">💾</button>
</div>
@@ -165,61 +181,45 @@
{% if item.purchased %}
<span class="badge bg-success">✔️ Kupiony</span>
{% elif item.not_purchased %}
<span class="badge bg-warning text-dark">⚠️ Nie kupione</span>
<span class="badge bg-warning text-dark">⚠️ Nie kupiony</span>
{% else %}
<span class="badge bg-secondary">Nieoznaczony</span>
{% endif %}
</td>
<td>
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}" class="d-grid gap-1">
<input type="hidden" name="action" value="toggle_purchased">
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}">
<input type="hidden" name="item_id" value="{{ item.id }}">
{% if not item.not_purchased %}
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}" class="d-grid gap-1">
<input type="hidden" name="action" value="toggle_purchased">
<input type="hidden" name="item_id" value="{{ item.id }}">
{% if item.purchased %}
<button type="submit" class="btn btn-outline-warning btn-sm">🚫 Odznacz</button>
{% else %}
<button type="submit" class="btn btn-outline-success btn-sm">✅ Oznacz</button>
<div class="btn-group btn-group-sm d-flex gap-1">
{% if not item.not_purchased %}
<button type="submit" name="action" value="toggle_purchased" class="btn btn-outline-light w-100">
{{ '🚫 Odznacz' if item.purchased else '✅ Kupiony' }}
</button>
<button type="submit" name="action" value="mark_not_purchased" class="btn btn-outline-light w-100">⚠️
Nie kupiony</button>
{% endif %}
</form>
{% endif %}
{% if item.not_purchased %}
<button type="submit" name="action" value="unmark_not_purchased" class="btn btn-outline-light w-100">
Przywróć jako nieoznaczone</button>
{% endif %}
</div>
</form>
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}" class="d-grid gap-1 mt-1">
<input type="hidden" name="action" value="mark_not_purchased">
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" class="btn btn-outline-warning btn-sm">⚠️ Nie kupione</button>
</form>
{% if item.not_purchased %}
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}"
class="d-grid gap-1 mt-3 border-top pt-2">
<input type="hidden" name="action" value="unmark_not_purchased">
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" class="btn btn-outline-success btn-sm">✅ Przywróć na liste</button>
</form>
{% endif %}
</td>
<td>
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}" class="d-inline">
<form method="post" action="{{ url_for('edit_list', list_id=list.id) }}">
<input type="hidden" name="action" value="delete_item">
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" class="btn btn-danger btn-sm w-100">🗑️ Usuń</button>
<button type="submit" class="btn btn-outline-light btn-sm w-100">🗑️</button>
</form>
</td>
</tr>
{% else %}
<tr>
<td colspan="4" class="text-center text-muted">Brak produktów.</td>
<td colspan="5" class="text-center text-muted">Brak produktów.</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>

View File

@@ -13,7 +13,7 @@
<div class="card-header d-flex justify-content-between align-items-center">
<h4 class="m-0">📦 Produkty (z synchronizacją sugestii)</h4>
<span class="badge bg-secondary">{{ items|length }} produktów</span>
<span class="badge bg-info">{{ items|length }} produktów</span>
</div>
<div class="card-body p-0">
<table class="table table-dark table-striped align-middle m-0">
@@ -21,21 +21,21 @@
<tr>
<th>ID</th>
<th>Nazwa</th>
<th>Dodana przez</th>
<th>Dodany przez</th>
<th>Sugestia</th>
<th>Akcje</th>
<th>Lista</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td>{{ item.id }}</td>
<td class="fw-bold">{{ item.name }}</td>
<td class="fw-bold"><span class="badge bg-primary">{{ item.name }}</span></td>
<td>
{% if item.added_by %}
{{ users_dict.get(item.added_by, 'Nieznany') }}
{% if item.added_by and users_dict.get(item.added_by) %}
👤 {{ users_dict[item.added_by] }} ({{ item.added_by }})
{% else %}
Gość
-
{% endif %}
</td>
<td>
@@ -50,8 +50,20 @@
{% endif %}
</td>
<td>
<a href="/list/{{ item.list_id }}" class="btn btn-sm btn-outline-light mb-1">📄 Zobacz listę</a>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-outline-light disabled" data-bs-toggle="tooltip"
data-bs-title="{{ item.shopping_list.title }}">
ID: {{ item.list_id }}
</button>
<a href="{{ url_for('view_list', list_id=item.list_id) }}" class="btn btn-outline-light">
📄 Otwórz
</a>
<button type="button" class="btn btn-outline-light preview-btn" data-list-id="{{ item.list_id }}">
🔍 Podgląd
</button>
</div>
</td>
</tr>
{% endfor %}
{% if items|length == 0 %}
@@ -69,7 +81,7 @@
<div class="card-body">
<div class="card-header d-flex justify-content-between align-items-center">
<h4 class="m-0">💡 Wszystkie sugestie (poza powiązanymi)</h4>
<span class="badge bg-secondary">{{ suggestions_dict|length }} sugestii</span>
<span class="badge bg-info">{{ orphan_suggestions|length }} sugestii</span>
</div>
<div class="card-body p-0">
{% set item_names = items | map(attribute='name') | map('lower') | list %}
@@ -82,11 +94,11 @@
</tr>
</thead>
<tbody>
{% for suggestion in suggestions_dict.values() %}
{% for suggestion in orphan_suggestions %}
{% if suggestion.name.lower() not in item_names %}
<tr>
<td>{{ suggestion.id }}</td>
<td class="fw-bold">{{ suggestion.name }}</td>
<td class="fw-bold"><span class="badge bg-primary">{{ suggestion.name }}</span></td>
<td>
<button class="btn btn-sm btn-outline-danger delete-suggestion-btn"
data-suggestion-id="{{ suggestion.id }}">🗑️ Usuń</button>
@@ -105,8 +117,24 @@
</div>
</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>
{% block scripts %}
<script src="{{ url_for('static_bp.serve_js', filename='product_suggestion.js') }}"></script>
<script src="{{ url_for('static_bp.serve_js', filename='preview_list_modal.js') }}"></script>
{% endblock %}
{% endblock %}

View File

@@ -18,35 +18,51 @@
<div class="card bg-dark text-white mb-5">
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-dark table-striped table-hover align-middle mb-0 sortable">
<table class="table table-dark table-striped align-middle sortable">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Nazwa listy</th>
<th scope="col">Właściciel</th>
<th scope="col">Data utworzenia</th>
<th scope="col">Status</th>
<th scope="col">Podgląd produktów</th>
<th scope="col">Kategorie</th>
</tr>
</thead>
<tbody>
{% for lst in lists %}
{% for l in lists %}
<tr>
<td>{{ lst.id }}</td>
<td>{{ lst.title }}</td>
<td>{{ lst.owner.username if lst.owner else "?" }}</td>
<td>{{ lst.created_at.strftime('%Y-%m-%d') }}</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>
</td>
<td>
{% if l.owner %}
👤 {{ l.owner.username }} ({{ l.owner.id }})
{% else %}
-
{% endif %}
</td>
<td>{{ l.created_at.strftime('%Y-%m-%d %H:%M') if l.created_at else '-' }}</td>
<td>
{% if l.is_archived %}<span class="badge bg-secondary">Archiwalna</span>{% endif %}
{% if l.is_temporary %}<span class="badge bg-warning text-dark">Tymczasowa</span>{%
endif %}
{% if l.is_public %}<span class="badge bg-success">Publiczna</span>{% else %}
<span class="badge bg-dark">Prywatna</span>{% endif %}
</td>
<td>
<button type="button" class="btn btn-sm btn-outline-info preview-btn"
data-list-id="{{ lst.id }}">
data-list-id="{{ l.id }}">
🔍 Zobacz
</button>
</td>
<td style="min-width: 220px;">
<select name="categories_{{ lst.id }}" multiple
<select name="categories_{{ l.id }}" multiple
class="form-select tom-dark bg-dark text-white border-secondary rounded">
{% for cat in categories %}
<option value="{{ cat.id }}" {% if cat in lst.categories %}selected{% endif %}>
<option value="{{ cat.id }}" {% if cat in l.categories %}selected{% endif %}>
{{ cat.name }}
</option>
{% endfor %}

View File

@@ -38,14 +38,14 @@
<div class="d-none d-md-flex justify-content-end align-items-center flex-wrap gap-2 mb-3">
<label for="monthSelect" class="text-white small mb-0">📅 Wybierz miesiąc:</label>
<select id="monthSelect" class="form-select form-select-sm bg-dark text-white border-secondary"
style="min-width: 180px;">
style="min-width: 180px;">
{% for m in month_options %}
{% set year, month = m.split('-') %}
<option value="{{ m }}" {% if selected_month == m %}selected{% endif %}>
{{ month_names[month|int - 1] }} {{ year }}
</option>
{% set year, month = m.split('-') %}
<option value="{{ m }}" {% if selected_month==m %}selected{% endif %}>
{{ month_names[month|int - 1] }} {{ year }}
</option>
{% endfor %}
<option value="all" {% if selected_month == 'all' %}selected{% endif %}>
<option value="all" {% if selected_month=='all' %}selected{% endif %}>
Wyświetl wszystko
</option>
</select>
@@ -228,11 +228,11 @@
<div class="modal-body">
<div class="d-grid gap-2">
{% for m in month_options %}
{% set year, month = m.split('-') %}
<a href="{{ url_for('main_page', m=m) }}"
class="btn btn-outline-light {% if selected_month == m %}active{% endif %}">
{{ month_names[month|int - 1] }} {{ year }}
</a>
{% set year, month = m.split('-') %}
<a href="{{ url_for('main_page', m=m) }}"
class="btn btn-outline-light {% if selected_month == m %}active{% endif %}">
{{ month_names[month|int - 1] }} {{ year }}
</a>
{% endfor %}
<a href="{{ url_for('main_page', m='all') }}"
class="btn btn-outline-secondary {% if selected_month == 'all' %}active{% endif %}">