duzo zmian, funkcji

This commit is contained in:
Mateusz Gruszczyński
2025-07-04 15:10:05 +02:00
parent 20f1f73eb9
commit 7a3d57b111
11 changed files with 441 additions and 153 deletions

View File

@ -92,6 +92,7 @@
<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>
@ -111,6 +112,15 @@
<td class="fw-bold">
<a href="{{ url_for('view_list', list_id=l.id) }}" class="text-white">{{ l.title }}</a>
</td>
<td>
{% if l.is_archived %}
<span class="badge bg-secondary">Archiwalna</span>
{% elif l.is_temporary and l.expires_at and l.expires_at < now %}
<span class="badge bg-warning text-dark">Wygasła</span>
{% else %}
<span class="badge 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_id %}

View File

@ -19,6 +19,17 @@
<small class="form-text text-muted">Jeśli nie chcesz zmieniać kwoty, zostaw to pole bez zmian.</small>
</div>
<div class="mb-3">
<label for="owner_id" class="form-label">Nowy właściciel</label>
<select class="form-select" 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 class="form-check 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">

View File

@ -11,6 +11,7 @@
<script src="https://cdn.socket.io/4.6.1/socket.io.min.js"></script>
<script src="{{ url_for('static_bp.serve_live_js') }}?v={{ time.time() | int }}"></script>
<script src="{{ url_for('static', filename='js/toasts.js') }}"></script>
<script src="{{ url_for('static', filename='js/hide_list.js') }}"></script>
</head>
<body class="bg-dark text-white">

View File

@ -0,0 +1,12 @@
{% extends 'base.html' %}
{% block content %}
<h2>Edytuj listę: {{ list.title }}</h2>
<form method="post">
<div class="mb-3">
<label for="title" class="form-label">Nowy tytuł</label>
<input type="text" name="title" id="title" class="form-control" value="{{ list.title }}" required>
</div>
<button type="submit" class="btn btn-success">Zapisz</button>
<a href="{{ url_for('index_guest') }}" class="btn btn-secondary">Anuluj</a>
</form>
{% endblock %}

View File

@ -2,60 +2,97 @@
{% block title %}Twoje listy zakupów{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center flex-wrap mb-4">
<h2 class="mb-2">Stwórz nową listę</h2>
</div>
<div class="card bg-dark text-white mb-4">
<div class="card-body">
<form action="/create" method="post">
<div class="input-group mb-3">
<input type="text" name="title" id="title" placeholder="Wprowadź nazwę nowej listy" required class="form-control">
<div class="input-group-text">
<input type="checkbox" name="temporary" class="form-check-input m-0" id="tempCheck">
<label for="tempCheck" class="ms-2 mb-0">Tymczasowa (7 dni)</label>
</div>
</div>
<button type="submit" class="btn btn-success w-100"> Utwórz nową listę</button>
</form>
{% if not current_user.is_authenticated %}
<div class="alert alert-info" role="alert">
Jesteś w trybie gościa. Możesz tylko przeglądać listy udostępnione publicznie.
</div>
</div>
<div class="d-flex justify-content-between align-items-center flex-wrap mb-4">
<h2 class="mb-2">Listy zakupów</h2>
</div>
{% if lists %}
<ul class="list-group">
{% for l in lists %}
{% set purchased_count = l.purchased_count if l.purchased_count is defined else 0 %}
{% set total_count = l.total_count if l.total_count is defined else 0 %}
{% set percent = (purchased_count / total_count * 100) if total_count > 0 else 0 %}
<li class="list-group-item bg-dark text-white">
<div class="d-flex justify-content-between align-items-center flex-wrap w-100">
<span class="fw-bold">{{ l.title }} (Autor: {{ l.owner.username }})</span>
<div class="mt-2 mt-md-0">
{% if current_user.is_authenticated %}
<a href="/list/{{ l.id }}" class="btn btn-sm btn-outline-light me-1">📄 Otwórz</a>
<a href="/copy/{{ l.id }}" class="btn btn-sm btn-outline-secondary">📋 Kopiuj</a>
{% else %}
<a href="/guest-list/{{ l.id }}" class="btn btn-sm btn-outline-light me-1">📄 Otwórz</a>
{% endif %}
</div>
</div>
<div class="progress mt-2" style="height: 20px;">
<div class="progress-bar bg-warning text-dark fw-bold" role="progressbar" style="width: {{ percent }}%" aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
Produkty: {{ purchased_count }}/{{ total_count }} ({{ percent|round(0) }}%)
{% if l.total_expense > 0 %}
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
{% endif %}
</div>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p><span class="badge bg-secondary">Nie masz jeszcze żadnych list. Utwórz pierwszą, korzystając z formularza powyżej!</span></p>
{% endif %}
{% endblock %}
{% if current_user.is_authenticated %}
<div class="d-flex justify-content-between align-items-center flex-wrap mb-4">
<h2 class="mb-2">Stwórz nową listę</h2>
</div>
<div class="card bg-dark text-white mb-4">
<div class="card-body">
<form action="/create" method="post">
<div class="input-group mb-3">
<input type="text" name="title" id="title" placeholder="Wprowadź nazwę nowej listy" required class="form-control">
<div class="input-group-text">
<input type="checkbox" name="temporary" class="form-check-input m-0" id="tempCheck">
<label for="tempCheck" class="ms-2 mb-0">Tymczasowa (7 dni)</label>
</div>
</div>
<button type="submit" class="btn btn-success w-100"> Utwórz nową listę</button>
</form>
</div>
</div>
{% endif %}
{% if current_user.is_authenticated %}
<h3 class="mt-4">Twoje listy</h3>
{% if user_lists %}
<ul class="list-group mb-4">
{% for l in user_lists %}
{% set purchased_count = l.purchased_count %}
{% set total_count = l.total_count %}
{% set percent = (purchased_count / total_count * 100) if total_count > 0 else 0 %}
<li class="list-group-item bg-dark text-white">
<div class="d-flex justify-content-between align-items-center flex-wrap w-100">
<span class="fw-bold">{{ l.title }} (Autor: Ty)</span>
<div class="mt-2 mt-md-0">
<a href="/list/{{ l.id }}" class="btn btn-sm btn-outline-light me-1">📄 Otwórz</a>
<a href="/copy/{{ l.id }}" class="btn btn-sm btn-outline-secondary me-1">📋 Kopiuj</a>
<a href="/edit_my_list/{{ l.id }}" class="btn btn-sm btn-outline-warning me-1">✏️ Edytuj</a>
<a href="/archive_my_list/{{ l.id }}" class="btn btn-sm btn-outline-danger me-1">🗄️ Archiwizuj</a>
{% if l.is_public %}
<a href="/toggle_visibility/{{ l.id }}" class="btn btn-sm btn-outline-secondary">🙈 Ukryj</a>
{% else %}
<a href="/toggle_visibility/{{ l.id }}" class="btn btn-sm btn-outline-success">👁️ Udostępnij</a>
{% endif %}
</div>
</div>
<div class="progress mt-2" style="height: 20px;">
<div class="progress-bar bg-warning text-dark fw-bold" role="progressbar" style="width: {{ percent }}%" aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
Produkty: {{ purchased_count }}/{{ total_count }} ({{ percent|round(0) }}%)
{% if l.total_expense > 0 %}
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
{% endif %}
</div>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p><span class="badge bg-secondary">Nie masz jeszcze żadnych list. Utwórz pierwszą, korzystając z formularza powyżej!</span></p>
{% endif %}
{% endif %}
<h3 class="mt-4">Publiczne listy innych użytkowników</h3>
{% if public_lists %}
<ul class="list-group">
{% for l in public_lists %}
{% set purchased_count = l.purchased_count %}
{% set total_count = l.total_count %}
{% set percent = (purchased_count / total_count * 100) if total_count > 0 else 0 %}
<li class="list-group-item bg-dark text-white">
<div class="d-flex justify-content-between align-items-center flex-wrap w-100">
<span class="fw-bold">{{ l.title }} (Autor: {{ l.owner.username }})</span>
<a href="/guest-list/{{ l.id }}" class="btn btn-sm btn-outline-light">📄 Otwórz</a>
</div>
<div class="progress mt-2" style="height: 20px;">
<div class="progress-bar bg-warning text-dark fw-bold" role="progressbar" style="width: {{ percent }}%" aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
Produkty: {{ purchased_count }}/{{ total_count }} ({{ percent|round(0) }}%)
{% if l.total_expense > 0 %}
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
{% endif %}
</div>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p><span class="badge bg-secondary">Brak dostępnych list publicznych do wyświetlenia.</span></p>
{% endif %}
{% endblock %}

View File

@ -1,5 +1,5 @@
{% extends 'base.html' %}
{% block title %}{{ list.title }}{% endblock %}
{% block title %}Lista: {{ list.title }}{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap">
@ -11,28 +11,37 @@
{% endif %}
</h2>
<a href="/" class="btn btn-outline-secondary">← Powrót do list</a>
</div>
<div class="card bg-dark text-white mb-4">
<div id="share-card" class="card bg-dark text-white mb-4">
<div class="card-body d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center gap-2">
<div>
<strong>🔗 Udostępnij link:</strong><br>
<span class="badge bg-secondary text-wrap" style="font-size: 0.7rem;">
<strong id="share-header">
{% if list.is_public %}
🔗 Udostępnij link:
{% else %}
🙈 Lista jest ukryta przed gośćmi
{% endif %}
</strong><br>
<span id="share-url" class="badge bg-secondary text-wrap" style="font-size: 0.7rem; {% if not list.is_public %}display: none;{% endif %}">
{{ request.url_root }}share/{{ list.share_token }}
</span>
</div>
{% if not list.is_archived %}
<button class="btn btn-success btn-sm mt-2 mt-md-0" onclick="copyLink('{{ request.url_root }}share/{{ list.share_token }}')">
📋 Udostępnij link
<div class="d-flex flex-column flex-md-row gap-2 mt-2 mt-md-0">
<button id="copyBtn" class="btn btn-success btn-sm"
onclick="copyLink('{{ request.url_root }}share/{{ list.share_token }}')"
{% if not list.is_public %}disabled{% endif %}>
📋 Skopiuj link
</button>
{% else %}
<button class="btn btn-secondary btn-sm mt-2 mt-md-0" disabled>
📋 Udostępnianie wyłączone (Archiwalna)
<button id="toggleVisibilityBtn" class="btn btn-outline-secondary btn-sm" onclick="toggleVisibility({{ list.id }})">
{% if list.is_public %}
🙈 Ukryj listę
{% else %}
👁️ Udostępnij ponownie
{% endif %}
</button>
{% endif %}
</div>
</div>
</div>
@ -65,32 +74,37 @@
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap {% if item.purchased %}bg-success text-white{% else %}bg-light text-white{% endif %}" id="item-{{ item.id }}">
<div class="d-flex align-items-center flex-wrap gap-2 flex-grow-1">
<input type="checkbox" {% if item.purchased %}checked{% endif %} {% if list.is_archived %}disabled{% endif %}>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">{{ item.name }}</span>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">
{{ item.name }}
{% if item.quantity and item.quantity > 1 %}
<span class="badge bg-secondary">x{{ item.quantity }}</span>
{% endif %}
</span>
{% if item.note %}
<small class="text-danger">[ Notatka: <b>{{ item.note }}</b> ] </small>
{% endif %}
</div>
<div class="mt-2 mt-md-0 d-flex gap-1">
<button class="btn btn-sm btn-outline-warning"
{% if list.is_archived %}disabled{% else %}onclick="editItem({{ item.id }}, '{{ item.name }}')"{% endif %}>
{% if list.is_archived %}disabled{% else %}onclick="editItem({{ item.id }}, '{{ item.name }}', {{ item.quantity or 1 }})"{% endif %}>
✏️ Edytuj
</button>
<button class="btn btn-sm btn-outline-danger"
{% if list.is_archived %}disabled{% else %}onclick="deleteItem({{ item.id }})"{% endif %}>
🗑️ Usuń
</button>
</div>
</li>
{% endfor %}
</ul>
{% if not list.is_archived %}
<div class="input-group mb-2 position-relative">
<input id="newItem" class="form-control" placeholder="Nowy produkt">
<button onclick="addItem({{ list.id }})" class="btn btn-success"> Dodaj</button>
</div>
<div class="input-group mb-3">
<input type="text" id="newItem" name="name" class="form-control" placeholder="Nowy produkt" required>
<input type="number" id="newQuantity" name="quantity" class="form-control" placeholder="Ilość" min="1" value="1" style="max-width: 80px;">
<button type="button" class="btn btn-success" onclick="addItem({{ list.id }})"> Dodaj</button>
</div>
{% endif %}
{% set receipt_pattern = 'list_' ~ list.id %}

View File

@ -23,7 +23,13 @@
<li class="list-group-item d-flex justify-content-between align-items-center flex-wrap clickable-item {% if item.purchased %}bg-success text-white{% else %}bg-light text-white{% endif %}" id="item-{{ item.id }}">
<div class="d-flex align-items-center gap-3 flex-grow-1">
<input type="checkbox" class="form-check-input large-checkbox" {% if item.purchased %}checked{% endif %} {% if list.is_archived %}disabled{% endif %}>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">{{ item.name }}</span>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">
{{ item.name }}
{% if item.quantity and item.quantity > 1 %}
<span class="badge bg-secondary">x{{ item.quantity }}</span>
{% endif %}
</span>
{% if item.note %}
<small class="text-danger ms-4">[ Notatka: <b>{{ item.note }}</b> ]</small>
{% endif %}
@ -39,6 +45,7 @@
{% if not list.is_archived %}
<div class="input-group mb-2">
<input id="newItem" class="form-control" placeholder="Nowy produkt">
<input id="newQuantity" type="number" class="form-control" placeholder="Ilość" min="1" value="1" style="max-width: 90px;">
<button onclick="addItem({{ list.id }})" class="btn btn-success"> Dodaj</button>
</div>
{% endif %}