duzo zmian i funkcji

This commit is contained in:
Mateusz Gruszczyński
2025-07-02 23:51:19 +02:00
parent 36cdcf175a
commit b02bd27aa1
10 changed files with 285 additions and 125 deletions

View File

@ -28,7 +28,8 @@
<tr>
<th>ID</th>
<th>Tytuł</th>
<th>Właściciel (ID)</th>
<th>Utworzono</th>
<th>Właściciel (ID / nazwa)</th>
<th>Akcje</th>
</tr>
</thead>
@ -37,7 +38,14 @@
<tr>
<td>{{ l.id }}</td>
<td class="fw-bold">{{ l.title }}</td>
<td>{{ l.owner_id }}</td>
<td>{{ l.created_at.strftime('%Y-%m-%d %H:%M') if l.created_at else '-' }}</td>
<td>
{% if l.owner_id %}
{{ l.owner_id }} / {{ l.owner.username if l.owner else 'Brak użytkownika' }}
{% else %}
-
{% endif %}
</td>
<td>
<a href="{{ url_for('delete_list', list_id=l.id) }}" class="btn btn-sm btn-outline-danger">🗑️ Usuń</a>
</td>

View File

@ -6,7 +6,8 @@
<title>{% block title %}Live Lista Zakupów{% endblock %}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://cdn.socket.io/4.6.1/socket.io.min.js"></script>
<script src="{{ url_for('static', filename='js/live.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>
</head>
<body class="bg-dark text-white">
@ -25,10 +26,26 @@
</div>
</div>
</nav>
<div id="toast-container" class="toast-container position-fixed bottom-0 end-0 p-3"></div>
<div class="container px-2">
{% block content %}{% endblock %}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
{% with messages = get_flashed_messages(with_categories=true) %}
{% for category, message in messages %}
{% set cat = 'info' if not category else ('danger' if category == 'error' else category) %}
{% if message == 'Please log in to access this page.' %}
showToast("Aby uzyskać dostęp do tej strony, musisz być zalogowany.", "danger");
{% else %}
showToast({{ message|tojson }}, "{{ cat }}");
{% endif %}
{% endfor %}
{% endwith %}
});
</script>
</body>
</html>

View File

@ -1,44 +0,0 @@
{% extends 'base.html' %}
{% block title %}Twoje listy{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center flex-wrap mb-4">
<h2 class="mb-2">📝 Twoje listy zakupowe</h2>
<div class="d-flex flex-wrap gap-2">
<a href="{{ url_for('index_guest') }}" class="btn btn-outline-light">👀 Tryb gościa</a>
<a href="{{ url_for('index_guest') }}" class="btn btn-success"> Utwórz nową listę</a>
<a href="{{ url_for('logout') }}" class="btn btn-secondary">🚪 Wyloguj</a>
</div>
</div>
{% if lists %}
<div class="table-responsive">
<table class="table table-dark table-striped align-middle">
<thead>
<tr>
<th>ID</th>
<th>Tytuł</th>
<th>Data utworzenia</th>
<th>Akcje</th>
</tr>
</thead>
<tbody>
{% for l in lists %}
<tr>
<td>{{ l.id }}</td>
<td class="fw-bold">{{ l.title }}</td>
<td>{{ l.created_at.strftime('%Y-%m-%d %H:%M') }}</td>
<td>
<a href="{{ url_for('view_list', list_id=l.id) }}" class="btn btn-sm btn-outline-light me-1">📄 Otwórz</a>
<a href="{{ url_for('copy_list', list_id=l.id) }}" class="btn btn-sm btn-outline-secondary">📋 Kopiuj</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p>Nie masz jeszcze żadnych list. Kliknij „Utwórz nową listę”, aby dodać pierwszą!</p>
{% endif %}
{% endblock %}

View File

@ -4,24 +4,21 @@
<div class="d-flex justify-content-between align-items-center flex-wrap mb-4">
<h2 class="mb-2">Twoje listy zakupów</h2>
<a href="{{ url_for('dashboard') }}" class="btn btn-outline-secondary">← Powrót do panelu</a>
<a href="{{ url_for('index_guest') }}" class="btn btn-outline-secondary">← Powrót do panelu</a>
</div>
<div class="card bg-dark text-white mb-4">
<div class="card-body">
<form action="/create" method="post" class="row g-2 align-items-center">
<div class="col-sm-5">
<input type="text" name="title" placeholder="Nazwa listy" required class="form-control">
<form action="/create" method="post">
<div class="mb-3">
<label for="title" class="form-label">Nazwa listy</label>
<input type="text" name="title" id="title" placeholder="Wprowadź nazwę listy" required class="form-control">
</div>
<div class="col-auto">
<div class="form-check">
<input type="checkbox" name="temporary" class="form-check-input" id="tempCheck">
<label for="tempCheck" class="form-check-label">Tymczasowa (7 dni)</label>
</div>
</div>
<div class="col-auto">
<button type="submit" class="btn btn-success"> Utwórz nową listę</button>
<div class="form-check mb-3">
<input type="checkbox" name="temporary" class="form-check-input" id="tempCheck">
<label for="tempCheck" class="form-check-label">Tymczasowa (7 dni)</label>
</div>
<button type="submit" class="btn btn-success w-100"> Utwórz nową listę</button>
</form>
</div>
</div>
@ -29,15 +26,23 @@
{% if lists %}
<ul class="list-group">
{% for l in lists %}
<li class="list-group-item bg-dark text-white d-flex justify-content-between align-items-center flex-wrap">
<span class="fw-bold">{{ l.title }}</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 %}
{% 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 }}</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-success" role="progressbar" style="width: {{ percent }}%" aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">{{ purchased_count }}/{{ total_count }} ({{ percent|round(0) }}%)</div>
</div>
</li>
{% endfor %}
@ -46,4 +51,4 @@
<p>Nie masz jeszcze żadnych list. Utwórz pierwszą, korzystając z formularza powyżej!</p>
{% endif %}
{% endblock %}
{% endblock %}

View File

@ -19,12 +19,17 @@
</div>
</div>
<!-- Progress bar (dynamic) -->
<div class="progress mb-3">
<div id="progress-bar" class="progress-bar bg-success" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
</div>
<ul id="items" class="list-group mb-3">
{% for item in items %}
<li class="list-group-item bg-dark text-white d-flex justify-content-between align-items-center flex-wrap" id="item-{{ item.id }}">
<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">
<input type="checkbox">
<span id="name-{{ item.id }}">{{ item.name }}</span>
<input type="checkbox" {% if item.purchased %}checked{% endif %}>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">{{ item.name }}</span>
</div>
<div class="mt-2 mt-md-0">
<button class="btn btn-sm btn-outline-warning me-1" onclick="editItem({{ item.id }}, '{{ item.name }}')">✏️ Edytuj</button>
@ -34,7 +39,7 @@
{% endfor %}
</ul>
<div class="input-group mb-2">
<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>
@ -44,4 +49,13 @@
<script>
setupList({{ list.id }}, '{{ current_user.username if current_user.is_authenticated else 'Gość' }}');
</script>
<style>
.bg-success {
background-color: #1e7e34 !important;
}
.bg-light {
background-color: #2c2f33 !important;
}
</style>
{% endblock %}

View File

@ -9,10 +9,10 @@
<ul id="items" class="list-group mb-3">
{% for item in items %}
<li class="list-group-item bg-dark text-white d-flex justify-content-between align-items-center flex-wrap clickable-item" id="item-{{ item.id }}">
<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 %}>
<span id="name-{{ item.id }}" class="flex-grow-1">{{ item.name }}</span>
<span id="name-{{ item.id }}" class="{% if item.purchased %}text-white{% else %}text-white{% endif %}">{{ item.name }}</span>
</div>
</li>
{% endfor %}
@ -28,14 +28,32 @@
<script>
setupList({{ list.id }}, 'Gość');
// Dodanie kliknięcia na cały wiersz
document.querySelectorAll('.clickable-item').forEach(item => {
item.addEventListener('click', function(e) {
// Ignoruj kliknięcia w input (żeby nie duplikować akcji)
if (e.target.tagName.toLowerCase() !== 'input') {
const checkbox = this.querySelector('input[type="checkbox"]');
checkbox.checked = !checkbox.checked;
checkbox.dispatchEvent(new Event('change'));
if (checkbox.disabled) {
return;
}
if (checkbox.checked) {
socket.emit('uncheck_item', { item_id: parseInt(this.id.replace('item-', ''), 10) });
} else {
socket.emit('check_item', { item_id: parseInt(this.id.replace('item-', ''), 10) });
}
checkbox.disabled = true;
this.classList.add('opacity-50');
let existingSpinner = this.querySelector('.spinner-border');
if (!existingSpinner) {
const spinner = document.createElement('span');
spinner.className = 'spinner-border spinner-border-sm ms-2';
spinner.setAttribute('role', 'status');
spinner.setAttribute('aria-hidden', 'true');
checkbox.parentElement.appendChild(spinner);
}
}
});
});
@ -49,6 +67,11 @@
.clickable-item {
cursor: pointer;
}
.bg-success {
background-color: #1e7e34 !important;
}
.bg-light {
background-color: #2c2f33 !important;
}
</style>
{% endblock %}