poprawki w jogice js, progressbar warstwowy i fix w notatkach

This commit is contained in:
Mateusz Gruszczyński
2025-08-06 13:42:20 +02:00
parent 6bb0c97c37
commit 3abad9e151
5 changed files with 82 additions and 70 deletions

18
app.py
View File

@@ -1308,16 +1308,21 @@ def main_page():
db.session.query(
Item.list_id,
func.count(Item.id).label("total_count"),
func.sum(case((Item.purchased == True, 1), else_=0)).label(
"purchased_count"
),
func.sum(case((Item.purchased == True, 1), else_=0)).label("purchased_count"),
func.sum(case((Item.not_purchased == True, 1), else_=0)).label("not_purchased_count"),
)
.filter(Item.list_id.in_(all_ids))
.group_by(Item.list_id)
.all()
)
stats_map = {
s.list_id: (s.total_count or 0, s.purchased_count or 0) for s in stats
s.list_id: (
s.total_count or 0,
s.purchased_count or 0,
s.not_purchased_count or 0
)
for s in stats
}
latest_expenses_map = dict(
@@ -1330,9 +1335,10 @@ def main_page():
)
for l in all_lists:
total_count, purchased_count = stats_map.get(l.id, (0, 0))
total_count, purchased_count, not_purchased_count = stats_map.get(l.id, (0, 0, 0))
l.total_count = total_count
l.purchased_count = purchased_count
l.not_purchased_count = not_purchased_count
l.total_expense = latest_expenses_map.get(l.id, 0)
l.category_badges = [
@@ -1343,6 +1349,7 @@ def main_page():
for l in all_lists:
l.total_count = 0
l.purchased_count = 0
l.not_purchased_count = 0
l.total_expense = 0
l.category_badges = []
@@ -1356,6 +1363,7 @@ def main_page():
)
@app.route("/system-auth", methods=["GET", "POST"])
def system_auth():
if (

View File

@@ -22,45 +22,33 @@ function updateItemState(itemId, isChecked) {
function updateProgressBar() {
const items = document.querySelectorAll('#items li');
const total = items.length;
const purchased = Array.from(items).filter(li => li.classList.contains('bg-success')).length;
const percent = total > 0 ? Math.round((purchased / total) * 100) : 0;
const notPurchased = Array.from(items).filter(li => li.classList.contains('bg-warning')).length;
const remaining = total - purchased - notPurchased;
// Pasek postępu
const progressBar = document.getElementById('progress-bar');
if (progressBar) {
progressBar.style.width = `${percent}%`;
progressBar.setAttribute('aria-valuenow', percent);
progressBar.textContent = percent > 0 ? `${percent}%` : ''; // opcjonalnie
}
const percentPurchased = total > 0 ? (purchased / total) * 100 : 0;
const percentNotPurchased = total > 0 ? (notPurchased / total) * 100 : 0;
const percentRemaining = total > 0 ? (remaining / total) * 100 : 0;
// Label na pasku postępu
document.getElementById('progress-bar-purchased').style.width = `${percentPurchased}%`;
document.getElementById('progress-bar-not-purchased').style.width = `${percentNotPurchased}%`;
document.getElementById('progress-bar-remaining').style.width = `${percentRemaining}%`;
// etykieta
const progressLabel = document.getElementById('progress-label');
if (progressLabel) {
progressLabel.textContent = `${percent}%`;
if (percent === 0) {
progressLabel.style.display = 'inline';
} else {
progressLabel.style.display = 'none';
}
// Kolor tekstu labela
if (percent < 50) {
progressLabel.classList.remove('text-dark');
progressLabel.classList.add('text-white');
} else {
progressLabel.classList.remove('text-white');
progressLabel.classList.add('text-dark');
}
}
const percent = total > 0 ? Math.round((purchased / total) * 100) : 0;
progressLabel.textContent = `${percent}%`;
progressLabel.classList.toggle('text-white', percent < 50);
progressLabel.classList.toggle('text-dark', percent >= 50);
// Nagłówek
const purchasedCount = document.getElementById('purchased-count');
if (purchasedCount) purchasedCount.textContent = purchased;
const totalCount = document.getElementById('total-count');
if (totalCount) totalCount.textContent = total;
const percentValue = document.getElementById('percent-value');
if (percentValue) percentValue.textContent = percent;
// liczniki
document.getElementById('purchased-count').textContent = purchased;
document.getElementById('total-count').textContent = total;
document.getElementById('percent-value').textContent = percent;
}
function addItem(listId) {
const name = document.getElementById('newItem').value;
const quantityInput = document.getElementById('newQuantity');
@@ -179,7 +167,6 @@ function openList(link) {
}
function applyHidePurchased(isInit = false) {
//console.log("applyHidePurchased: wywołana, isInit =", isInit);
const toggle = document.getElementById('hidePurchasedToggle');
if (!toggle) return;
const hide = toggle.checked;
@@ -187,9 +174,11 @@ function applyHidePurchased(isInit = false) {
const items = document.querySelectorAll('#items li');
items.forEach(li => {
const isPurchased = li.classList.contains('bg-success');
const isCheckedItem =
li.classList.contains('bg-success') || // kupione
li.classList.contains('bg-warning'); // niekupione
if (isPurchased) {
if (isCheckedItem) {
if (hide) {
if (isInit) {
// Jeśli inicjalizacja: od razu ukryj
@@ -210,7 +199,7 @@ function applyHidePurchased(isInit = false) {
}, 10);
}
} else {
// Element niekupiony — zawsze pokazany
// Element nieoznaczony — zawsze pokazany
li.classList.remove('hide-purchased', 'fade-out');
}
});

View File

@@ -205,21 +205,10 @@ function setupList(listId, username) {
});
socket.on('note_updated', data => {
const idx = window.currentItems.findIndex(i => i.id === data.item_id);
if (idx !== -1) {
window.currentItems[idx].note = data.note;
const newItem = renderItem(window.currentItems[idx], true);
const oldItem = document.getElementById(`item-${data.item_id}`);
if (oldItem && newItem) {
oldItem.replaceWith(newItem);
}
}
socket.emit('request_full_list', { list_id: window.LIST_ID });
showToast('Notatka dodana/zaktualizowana', 'success');
});
socket.on('item_edited', data => {
const idx = window.currentItems.findIndex(i => i.id === data.item_id);
if (idx !== -1) {

View File

@@ -73,16 +73,14 @@
</h5>
<div class="progress progress-dark position-relative">
<div id="progress-bar" class="progress-bar bg-warning text-dark" role="progressbar" style="width: {{ percent }}%;"
aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
</div>
<div id="progress-bar-purchased" class="progress-bar bg-success" role="progressbar"></div>
<div id="progress-bar-not-purchased" class="progress-bar bg-danger" role="progressbar"></div>
<div id="progress-bar-remaining" class="progress-bar bg-transparent" role="progressbar"></div>
<span id="progress-label" class="progress-label small fw-bold
{% if percent < 50 %}text-white{% else %}text-dark{% endif %}">
{{ percent|round(0) }}%
</span>
<span id="progress-label" class="progress-label small fw-bold"></span>
</div>
{% if total_expense > 0 %}
<div id="total-expense2" class="text-success fw-bold mb-3">
💸 Łącznie wydano: {{ '%.2f'|format(total_expense) }} PLN

View File

@@ -99,17 +99,31 @@
</div>
<div class="progress progress-dark progress-thin mt-2 position-relative">
<div class="progress-bar bg-warning text-dark" role="progressbar" style="width: {{ percent }}%;"
aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
</div>
{# Kupione #}
<div class="progress-bar bg-success" role="progressbar"
style="width: {{ (purchased_count / total_count * 100) if total_count > 0 else 0 }}%" aria-valuemin="0"
aria-valuemax="100"></div>
{# Niekupione #}
{% set not_purchased_count = l.not_purchased_count if l.total_count else 0 %}
<div class="progress-bar bg-danger" role="progressbar"
style="width: {{ (not_purchased_count / total_count * 100) if total_count > 0 else 0 }}%" aria-valuemin="0"
aria-valuemax="100"></div>
{# Pozostałe #}
<div class="progress-bar bg-transparent" role="progressbar"
style="width: {{ 100 - ((purchased_count + not_purchased_count) / total_count * 100) if total_count > 0 else 100 }}%"
aria-valuemin="0" aria-valuemax="100"></div>
<span class="progress-label small fw-bold
{% if percent < 50 %}text-white{% else %}text-dark{% endif %}">
{% if percent < 50 %}text-white{% else %}text-dark{% endif %}">
Produkty: {{ purchased_count }}/{{ total_count }} ({{ percent|round(0) }}%)
{% if l.total_expense > 0 %}
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
{% endif %}
</span>
</div>
</li>
{% endfor %}
</ul>
@@ -141,17 +155,31 @@
<a href="/guest-list/{{ l.id }}" class="btn btn-sm btn-outline-light">📄 Otwórz</a>
</div>
<div class="progress progress-dark progress-thin mt-2 position-relative">
<div class="progress-bar bg-warning text-dark" role="progressbar" style="width: {{ percent }}%;"
aria-valuenow="{{ percent }}" aria-valuemin="0" aria-valuemax="100">
</div>
{# Kupione #}
<div class="progress-bar bg-success" role="progressbar"
style="width: {{ (purchased_count / total_count * 100) if total_count > 0 else 0 }}%" aria-valuemin="0"
aria-valuemax="100"></div>
{# Niekupione #}
{% set not_purchased_count = l.not_purchased_count if l.total_count else 0 %}
<div class="progress-bar bg-danger" role="progressbar"
style="width: {{ (not_purchased_count / total_count * 100) if total_count > 0 else 0 }}%" aria-valuemin="0"
aria-valuemax="100"></div>
{# Pozostałe #}
<div class="progress-bar bg-transparent" role="progressbar"
style="width: {{ 100 - ((purchased_count + not_purchased_count) / total_count * 100) if total_count > 0 else 100 }}%"
aria-valuemin="0" aria-valuemax="100"></div>
<span class="progress-label small fw-bold
{% if percent < 50 %}text-white{% else %}text-dark{% endif %}">
{% if percent < 50 %}text-white{% else %}text-dark{% endif %}">
Produkty: {{ purchased_count }}/{{ total_count }} ({{ percent|round(0) }}%)
{% if l.total_expense > 0 %}
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
— 💸 {{ '%.2f'|format(l.total_expense) }} PLN
{% endif %}
</span>
</div>
</li>
{% endfor %}
</ul>