some fixes

This commit is contained in:
Mateusz Gruszczyński
2026-03-15 22:10:33 +01:00
parent ad5dbcc24b
commit 14a544c9c4
8 changed files with 822 additions and 74 deletions

View File

@@ -257,12 +257,13 @@ input[type="checkbox"].large-checkbox {
input[type="checkbox"].large-checkbox::before {
content: '✗';
color: #dc3545;
font-size: 1.5em;
font-weight: bold;
font-size: 1.6em;
font-weight: 700;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
inset: 0;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
transition: color .2s;
}
@@ -2659,9 +2660,14 @@ input[type="checkbox"].form-check-input,
height: .95rem !important;
}
.large-checkbox {
transform: scale(.92);
transform: none;
transform-origin: center;
}
.shopping-item-main > .large-checkbox {
flex: 0 0 1.5em;
align-self: center;
}
.list-item-actions {
display: flex;
align-items: center;
@@ -3562,7 +3568,7 @@ input[type="checkbox"].form-check-input,
.shopping-item-main {
display: flex;
align-items: flex-start;
align-items: center;
gap: .75rem;
width: 100%;
}
@@ -3589,12 +3595,15 @@ input[type="checkbox"].form-check-input,
.shopping-item-name {
min-width: 0;
word-break: break-word;
overflow-wrap: break-word;
word-break: normal;
}
.shopping-item-text .info-line {
flex-basis: 100%;
margin-top: .1rem;
overflow-wrap: break-word;
word-break: normal;
}
.shopping-item-actions {
@@ -4012,3 +4021,724 @@ input[type="checkbox"].form-check-input,
#progress-bar-remaining {
background: rgba(255,255,255,0.08) !important;
}
/* v10.2 item row consistency and mobile share fixes */
.shopping-item-text {
line-height: 1.35;
}
.shopping-item-text .info-line {
display: inline;
flex-basis: auto;
margin-top: 0;
white-space: normal;
}
.shopping-item-text .info-line > span {
display: inline;
}
.shopping-item-name,
.shopping-item-text .info-line {
overflow-wrap: break-word;
word-break: normal;
}
.shopping-item-actions {
flex: 0 0 auto;
}
@media (max-width: 575.98px) {
.shopping-item-head {
flex-wrap: wrap;
align-items: flex-start;
}
.shopping-item-text {
flex: 1 1 100%;
min-width: 0;
}
.shopping-item-actions {
width: 100%;
margin-left: 0;
justify-content: flex-end;
}
}
/* v10.3 alignment fixes for list/share */
.hide-purchased-switch--right {
display: inline-flex !important;
align-items: center;
justify-content: flex-end;
gap: .6rem;
width: auto;
margin-left: auto;
padding: 0 !important;
border: 0 !important;
background: transparent !important;
box-shadow: none !important;
}
.hide-purchased-switch--right::before,
.hide-purchased-switch--right::after {
display: none !important;
}
.hide-purchased-switch--right .form-check-input {
order: 1;
margin: 0;
float: none;
flex: 0 0 auto;
}
.hide-purchased-switch--right .form-check-label {
order: 0;
margin: 0 !important;
white-space: nowrap;
}
.list-action-row {
display: flex;
flex-wrap: nowrap;
align-items: stretch;
gap: .65rem;
}
.list-action-row__form {
display: flex;
flex: 1 1 50%;
}
.list-action-row__btn {
width: 100%;
}
.list-action-row > .list-action-row__btn {
flex: 1 1 50%;
}
.shopping-item-head {
flex-wrap: nowrap;
align-items: center;
}
.shopping-item-text {
flex: 1 1 auto;
min-width: 0;
}
.shopping-item-text .info-line {
flex-basis: auto;
}
.shopping-item-actions {
align-items: center;
justify-content: flex-end;
flex: 0 0 auto;
white-space: nowrap;
}
.shopping-item-actions .btn {
flex: 0 0 auto;
}
@media (max-width: 575.98px) {
.shopping-item-main {
align-items: center;
}
.shopping-item-head {
flex-wrap: nowrap;
align-items: center;
gap: .4rem;
}
.shopping-item-text {
flex: 1 1 auto;
min-width: 0;
gap: .25rem;
}
.shopping-item-actions {
width: auto;
margin-left: auto;
gap: .25rem;
}
.shopping-item-actions .btn {
min-width: 2rem;
padding: .3rem .42rem;
}
.hide-purchased-switch--right {
width: auto;
max-width: 100%;
}
.list-action-row {
gap: .5rem;
}
.list-action-row > .list-action-row__btn,
.list-action-row__form {
flex: 1 1 50%;
min-width: 0;
}
.list-action-row__btn {
padding-left: .55rem;
padding-right: .55rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
/* layout polish 2026-03-15: toolbar, sorting and item alignment */
.list-header-toolbar {
width: 100%;
}
.list-header-toolbar > h2 {
flex: 1 1 auto;
min-width: 0;
}
.list-header-toolbar .list-toolbar {
flex: 0 0 auto;
width: auto;
margin-left: auto;
}
.list-toolbar__sort.btn {
display: inline-flex;
align-items: center;
justify-content: center;
white-space: nowrap;
border-width: 1px !important;
}
.drag-handle {
display: none !important;
cursor: grab;
}
body.sorting-active .drag-handle {
display: inline-flex !important;
}
body.sorting-active .shopping-item-row {
cursor: grab;
}
body.sorting-active .shopping-item-row:active,
body.sorting-active .drag-handle:active {
cursor: grabbing;
}
body.sorting-active .shopping-item-row .large-checkbox {
pointer-events: none;
}
.endpoint-list_share .shopping-item-name,
.endpoint-list_share .shopping-item-text .info-line,
.endpoint-shared_list .shopping-item-name,
.endpoint-shared_list .shopping-item-text .info-line {
overflow-wrap: break-word;
word-break: normal;
}
.endpoint-list_share input[type="checkbox"].large-checkbox::before,
.endpoint-shared_list input[type="checkbox"].large-checkbox::before,
.endpoint-view_list input[type="checkbox"].large-checkbox::before {
font-size: 1.7em;
}
@media (max-width: 575.98px) {
.endpoint-view_list .list-toolbar {
display: grid !important;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center !important;
gap: .4rem !important;
flex-wrap: nowrap !important;
}
.endpoint-view_list .list-toolbar__sort.btn {
min-width: 0;
padding: .35rem .55rem;
font-size: .82rem;
}
.endpoint-view_list .hide-purchased-switch--right {
min-width: 0;
gap: .25rem;
font-size: .82rem;
}
.endpoint-view_list .hide-purchased-switch--right .form-check-label {
margin-left: .25rem !important;
white-space: nowrap;
}
.endpoint-view_list .hide-purchased-switch--right .form-check-input {
transform: scale(.92);
transform-origin: center;
}
.list-header-toolbar {
align-items: flex-start !important;
}
.list-header-toolbar .list-toolbar {
width: 100%;
justify-content: flex-end !important;
}
}
/* hotfix 2026-03-15 v3: /share item layout parity with /list */
.endpoint-list_share .shopping-item-row,
.endpoint-shared_list .shopping-item-row {
overflow: hidden;
}
.endpoint-list_share .shopping-item-main,
.endpoint-shared_list .shopping-item-main {
align-items: center;
}
.endpoint-list_share .shopping-item-content,
.endpoint-shared_list .shopping-item-content {
flex: 1 1 auto;
min-width: 0;
width: 100%;
}
.endpoint-list_share .shopping-item-head,
.endpoint-shared_list .shopping-item-head {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
align-items: center;
column-gap: .65rem;
row-gap: .35rem;
}
.endpoint-list_share .shopping-item-text,
.endpoint-shared_list .shopping-item-text {
display: flex;
flex-wrap: wrap;
align-items: center;
align-content: center;
min-width: 0;
width: 100%;
gap: .35rem;
}
.endpoint-list_share .shopping-item-name,
.endpoint-shared_list .shopping-item-name {
display: inline;
min-width: 0;
max-width: 100%;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
}
.endpoint-list_share .shopping-item-text .info-line,
.endpoint-shared_list .shopping-item-text .info-line {
display: block;
flex: 0 0 100%;
width: 100%;
margin-top: .15rem;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
}
.endpoint-list_share .shopping-item-actions,
.endpoint-shared_list .shopping-item-actions {
display: inline-flex;
flex-wrap: nowrap;
align-items: center;
align-self: center;
justify-content: flex-end;
margin-left: 0;
white-space: nowrap;
}
.endpoint-list_share .shopping-item-actions .btn,
.endpoint-shared_list .shopping-item-actions .btn {
display: inline-flex;
align-items: center;
justify-content: center;
}
.endpoint-list_share .shopping-item-main > .large-checkbox,
.endpoint-shared_list .shopping-item-main > .large-checkbox,
.endpoint-view_list .shopping-item-main > .large-checkbox {
align-self: center;
}
@media (max-width: 575.98px) {
.endpoint-list_share .shopping-item-head,
.endpoint-shared_list .shopping-item-head {
grid-template-columns: minmax(0, 1fr) auto;
align-items: start;
}
.endpoint-list_share .shopping-item-actions,
.endpoint-shared_list .shopping-item-actions {
align-self: start;
gap: .3rem;
}
.endpoint-list_share .shopping-item-actions .btn,
.endpoint-shared_list .shopping-item-actions .btn {
min-width: 2.15rem;
padding: .32rem .45rem;
}
}
/* hotfix 2026-03-15 v4: /share parity with /list */
.endpoint-list_share .shopping-item-row,
.endpoint-shared_list .shopping-item-row {
padding: .8rem .95rem;
}
.endpoint-list_share .shopping-item-main,
.endpoint-shared_list .shopping-item-main {
display: flex;
align-items: center;
gap: .75rem;
width: 100%;
}
.endpoint-list_share .shopping-item-content,
.endpoint-shared_list .shopping-item-content {
flex: 1 1 auto;
min-width: 0;
width: auto;
}
.endpoint-list_share .shopping-item-head,
.endpoint-shared_list .shopping-item-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: .75rem;
}
.endpoint-list_share .shopping-item-text,
.endpoint-shared_list .shopping-item-text {
flex: 1 1 auto;
min-width: 0;
display: flex;
align-items: center;
align-content: center;
gap: .35rem;
flex-wrap: wrap;
}
.endpoint-list_share .shopping-item-name,
.endpoint-shared_list .shopping-item-name {
display: inline;
min-width: 0;
max-width: 100%;
white-space: normal;
overflow-wrap: break-word;
word-break: normal;
}
.endpoint-list_share .shopping-item-text .badge,
.endpoint-shared_list .shopping-item-text .badge,
.endpoint-list_share .shopping-item-text .info-line,
.endpoint-shared_list .shopping-item-text .info-line {
align-self: center;
}
.endpoint-list_share .shopping-item-text .info-line,
.endpoint-shared_list .shopping-item-text .info-line {
display: block;
flex: 0 0 100%;
width: 100%;
margin-top: .1rem;
white-space: normal;
overflow-wrap: break-word;
word-break: normal;
}
.endpoint-list_share .shopping-item-actions,
.endpoint-shared_list .shopping-item-actions {
display: inline-flex;
flex: 0 0 auto;
flex-wrap: nowrap;
align-items: center;
justify-content: flex-end;
gap: .35rem;
white-space: nowrap;
}
.endpoint-list_share .shopping-item-actions .btn,
.endpoint-shared_list .shopping-item-actions .btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 2.25rem;
padding: .34rem .48rem;
}
.endpoint-list_share .shopping-item-main > .large-checkbox,
.endpoint-shared_list .shopping-item-main > .large-checkbox {
flex: 0 0 auto;
align-self: center;
}
.endpoint-list_share input[type="checkbox"].large-checkbox::before,
.endpoint-shared_list input[type="checkbox"].large-checkbox::before {
font-size: 1.75em;
}
@media (max-width: 575.98px) {
.endpoint-list_share .shopping-item-main,
.endpoint-shared_list .shopping-item-main {
gap: .55rem;
}
.endpoint-list_share .shopping-item-head,
.endpoint-shared_list .shopping-item-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: .45rem;
}
.endpoint-list_share .shopping-item-text,
.endpoint-shared_list .shopping-item-text {
flex: 1 1 auto;
min-width: 0;
gap: .25rem;
}
.endpoint-list_share .shopping-item-actions,
.endpoint-shared_list .shopping-item-actions {
width: auto;
margin-left: auto;
gap: .25rem;
}
.endpoint-list_share .shopping-item-actions .btn,
.endpoint-shared_list .shopping-item-actions .btn {
min-width: 2rem;
padding: .3rem .42rem;
}
}
/* mobile menu simplification 2026-03-15 */
.app-mobile-menu {
display: flex;
align-items: center;
}
.app-mobile-menu__toggle {
display: inline-flex;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
border-radius: 14px;
background: rgba(255,255,255,0.04);
}
.app-mobile-menu__panel {
min-width: 14rem;
padding: .4rem;
border-radius: 16px;
background: linear-gradient(180deg, rgba(14,22,35,0.98), rgba(9,15,26,0.98)) !important;
border: 1px solid rgba(255,255,255,0.1);
box-shadow: 0 18px 36px rgba(0,0,0,0.28);
}
.app-mobile-menu__item {
display: flex;
align-items: center;
gap: .55rem;
min-height: 2.6rem;
padding: .55rem .75rem;
color: #fff;
border-radius: 12px;
}
.app-mobile-menu__item:hover,
.app-mobile-menu__item:focus {
background: rgba(255,255,255,0.08);
color: #fff;
}
@media (min-width: 992px) {
.app-mobile-menu {
display: none !important;
}
}
/* v5.1 create-list temp toggle mobile/Desktop fix */
.create-list-input-group {
display: flex;
flex-wrap: nowrap !important;
align-items: stretch;
gap: 0 !important;
}
.create-list-input-group > .form-control {
flex: 1 1 auto !important;
width: 1% !important;
min-width: 0 !important;
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.create-list-input-group > .create-list-temp-toggle,
.create-list-input-group > #tempToggle {
flex: 0 0 auto !important;
width: auto !important;
min-width: 10rem;
margin-left: -1px;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-top-right-radius: 14px !important;
border-bottom-right-radius: 14px !important;
background: rgba(255,255,255,0.03) !important;
border-color: var(--app-border) !important;
color: var(--app-text) !important;
transition: background-color .18s ease, border-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.create-list-input-group > .create-list-temp-toggle.is-active,
.create-list-input-group > #tempToggle.is-active {
background: rgba(41, 209, 125, 0.16) !important;
border-color: rgba(41, 209, 125, 0.72) !important;
color: #9bf0c1 !important;
box-shadow: inset 0 0 0 1px rgba(41, 209, 125, 0.15);
}
.create-list-input-group > .create-list-temp-toggle:hover,
.create-list-input-group > #tempToggle:hover,
.create-list-input-group > .create-list-temp-toggle:focus,
.create-list-input-group > #tempToggle:focus {
background: rgba(255,255,255,0.06) !important;
color: var(--app-text) !important;
}
.create-list-input-group > .create-list-temp-toggle.is-active:hover,
.create-list-input-group > #tempToggle.is-active:hover,
.create-list-input-group > .create-list-temp-toggle.is-active:focus,
.create-list-input-group > #tempToggle.is-active:focus {
background: rgba(41, 209, 125, 0.2) !important;
color: #b7f7d2 !important;
}
@media (max-width: 767.98px) {
.create-list-input-group {
gap: 0 !important;
}
.create-list-input-group > .form-control {
padding-left: .9rem;
padding-right: .75rem;
}
.create-list-input-group > .create-list-temp-toggle,
.create-list-input-group > #tempToggle {
min-width: 8.75rem;
padding-left: .85rem;
padding-right: .85rem;
font-size: .92rem;
letter-spacing: 0;
}
}
/* Login/auth password field fixes */
.endpoint-login form .form-control,
.endpoint-system_auth form .form-control {
min-height: 42px;
border-radius: 14px !important;
}
.endpoint-login .ui-password-group,
.endpoint-system_auth .ui-password-group {
display: flex !important;
flex-wrap: nowrap !important;
align-items: stretch !important;
gap: 0 !important;
}
.endpoint-login .ui-password-group > .form-control,
.endpoint-system_auth .ui-password-group > .form-control {
width: auto !important;
flex: 1 1 auto !important;
max-width: none !important;
border-radius: 14px 0 0 14px !important;
border-right: 0 !important;
}
.endpoint-login .ui-password-group > .ui-password-toggle,
.endpoint-system_auth .ui-password-group > .ui-password-toggle {
appearance: none;
-webkit-appearance: none;
display: inline-flex !important;
align-items: center;
justify-content: center;
flex: 0 0 46px !important;
width: 46px !important;
min-width: 46px !important;
padding: 0 !important;
margin: 0 !important;
color: rgba(255,255,255,.78);
background: #1f2738 !important;
border: 1px solid var(--bs-border-color, #495057) !important;
border-left: 0 !important;
border-radius: 0 14px 14px 0 !important;
outline: none !important;
box-shadow: none !important;
line-height: 1;
font-size: 1rem;
}
.endpoint-login .ui-password-group > .ui-password-toggle:hover,
.endpoint-login .ui-password-group > .ui-password-toggle:focus,
.endpoint-system_auth .ui-password-group > .ui-password-toggle:hover,
.endpoint-system_auth .ui-password-group > .ui-password-toggle:focus {
color: #fff;
background: #253047 !important;
outline: none !important;
box-shadow: none !important;
}
.endpoint-login .ui-password-group > .ui-password-toggle.is-active,
.endpoint-system_auth .ui-password-group > .ui-password-toggle.is-active {
background: #2a3550 !important;
}
@media (max-width: 575.98px) {
.endpoint-login .ui-password-group,
.endpoint-system_auth .ui-password-group {
width: 100%;
}
.endpoint-login .ui-password-group > .form-control,
.endpoint-system_auth .ui-password-group > .form-control {
width: auto !important;
flex: 1 1 auto !important;
}
.endpoint-login .ui-password-group > .ui-password-toggle,
.endpoint-system_auth .ui-password-group > .ui-password-toggle {
flex: 0 0 44px !important;
width: 44px !important;
min-width: 44px !important;
}
}

View File

@@ -15,7 +15,7 @@ function enhancePasswordFields() {
const btn = document.createElement('button');
btn.type = 'button';
btn.className = 'btn btn-outline-light ui-password-toggle';
btn.className = 'ui-password-toggle';
btn.setAttribute('aria-label', 'Pokaż lub ukryj hasło');
btn.textContent = '👁';

View File

@@ -311,16 +311,21 @@ function renderItem(item, isShare = window.IS_SHARE, showEditOnly = false) {
if (item.not_purchased_reason) {
infoParts.push(`<span class="text-dark">[ <b>Powód: ${escapeHtml(item.not_purchased_reason)}</b> ]</span>`);
}
const addedByDisplay = item.added_by_display || item.added_by;
if (addedByDisplay && item.owner_id && item.added_by_id && item.added_by_id !== item.owner_id) {
const addedByDisplay = item.added_by_display;
if (addedByDisplay) {
infoParts.push(`<span class="text-info">[ Dodał/a: <b>${escapeHtml(addedByDisplay)}</b> ]</span>`);
}
const infoHtml = infoParts.length
? `<div class="info-line small d-flex flex-wrap gap-2" id="info-${item.id}">${infoParts.join(' ')}</div>`
? `<span class="info-line small" id="info-${item.id}">${infoParts.join(' ')}</span>`
: '';
let actionButtons = '';
if (!isShare) {
actionButtons += `
<button type="button" class="btn btn-outline-light btn-sm drag-handle" title="Przesuń produkt" aria-label="Przesuń produkt">☰</button>`;
}
if (allowEdit) {
actionButtons += `
<button type="button" class="btn btn-outline-light btn-sm"

View File

@@ -22,7 +22,7 @@ function enableSortMode() {
animation: 150,
handle: '.drag-handle',
ghostClass: 'drag-ghost',
filter: 'input, button',
filter: 'input, button:not(.drag-handle)',
preventOnFilter: false,
onEnd: () => {
const order = Array.from(itemsContainer.children)
@@ -73,6 +73,7 @@ function toggleSortMode() {
function updateSortButtonUI(active) {
const btn = document.getElementById('sort-toggle-btn');
document.body.classList.toggle('sorting-active', !!active);
if (!btn) return;
if (active) {

View File

@@ -8,19 +8,16 @@ document.addEventListener("DOMContentLoaded", function () {
}
function updateToggle(isActive) {
if (isActive) {
toggleBtn.classList.remove("btn-outline-secondary");
toggleBtn.classList.add("btn-success");
toggleBtn.textContent = "Tymczasowa ✔️";
} else {
toggleBtn.classList.remove("btn-success");
toggleBtn.classList.add("btn-outline-secondary");
toggleBtn.textContent = "Tymczasowa";
}
toggleBtn.classList.toggle("is-active", isActive);
toggleBtn.textContent = isActive ? "Tymczasowa ✔" : "Tymczasowa";
toggleBtn.setAttribute("aria-pressed", isActive ? "true" : "false");
toggleBtn.setAttribute("title", isActive
? "Lista tymczasowa będzie ważna przez 7 dni"
: "Po zaznaczeniu lista będzie ważna tylko 7 dni");
}
let active = toggleBtn.getAttribute("data-active") === "1";
hiddenInput.value = active ? "1" : "0";
updateToggle(active);
toggleBtn.addEventListener("click", function (event) {

View File

@@ -58,11 +58,27 @@
{% endif %}
</div>
<button class="navbar-toggler app-navbar-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#appNavbarMenu" aria-controls="appNavbarMenu" aria-expanded="false" aria-label="Przełącz nawigację">
<span class="navbar-toggler-icon"></span>
</button>
<div class="dropdown d-lg-none app-mobile-menu ms-auto">
<button class="btn app-navbar-toggler app-mobile-menu__toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-label="Otwórz menu">
<span class="navbar-toggler-icon"></span>
</button>
<div class="dropdown-menu dropdown-menu-end app-mobile-menu__panel">
{% if not is_blocked and request.endpoint and request.endpoint != 'system_auth' %}
{% if current_user.is_authenticated %}
{% if current_user.is_admin %}
<a href="{{ url_for('admin_panel') }}" class="dropdown-item app-mobile-menu__item">⚙️ <span>Panel</span></a>
{% endif %}
<a href="{{ url_for('expenses') }}" class="dropdown-item app-mobile-menu__item">📊 <span>Wydatki</span></a>
<a href="{{ url_for('my_templates') }}" class="dropdown-item app-mobile-menu__item">🧩 <span>Szablony</span></a>
<a href="{{ url_for('logout') }}" class="dropdown-item app-mobile-menu__item">🚪 <span>Wyloguj</span></a>
{% else %}
<a href="{{ url_for('login') }}" class="dropdown-item app-mobile-menu__item">🔑 <span>Zaloguj</span></a>
{% endif %}
{% endif %}
</div>
</div>
<div class="collapse navbar-collapse justify-content-end order-4 order-lg-3" id="appNavbarMenu">
<div class="d-none d-lg-flex justify-content-end order-lg-3" id="appNavbarMenu">
<div class="app-navbar__actions">
{% if not is_blocked and request.endpoint and request.endpoint != 'system_auth' %}
{% if current_user.is_authenticated %}

View File

@@ -94,9 +94,9 @@
</div>
{% endif %}
<div class="list-toolbar d-flex justify-content-between align-items-start mb-3 flex-wrap gap-2">
<div class="list-toolbar d-flex justify-content-between align-items-center mb-3 flex-wrap gap-2">
<button id="sort-toggle-btn" class="btn btn-sm btn-outline-warning list-toolbar__sort" onclick="toggleSortMode()">✳️ Zmień kolejność</button>
<div class="form-check form-switch form-check-spaced app-switch hide-purchased-switch hide-purchased-switch--minimal">
<div class="form-check form-switch form-check-spaced app-switch hide-purchased-switch hide-purchased-switch--minimal hide-purchased-switch--right">
<input class="form-check-input" type="checkbox" id="hidePurchasedToggle">
<label class="form-check-label ms-2" for="hidePurchasedToggle">Ukryj zaznaczone</label>
</div>
@@ -124,22 +124,23 @@
{% if item.not_purchased_reason %}{% set _ = info_parts.append('<span class="text-dark">[ <b>Powód: ' ~ item.not_purchased_reason ~ '</b> ]</span>') %}{% endif %}
{% if item.added_by_display %}{% set _ = info_parts.append('<span class="text-info">[ Dodał/a: <b>' ~ item.added_by_display ~ '</b> ]</span>') %}{% endif %}
{% if info_parts %}
<div class="info-line small d-flex flex-wrap gap-2" id="info-{{ item.id }}">{{ info_parts | join(' ') | safe }}</div>
<span class="info-line small" id="info-{{ item.id }}">{{ info_parts | join(' ') | safe }}</span>
{% endif %}
</div>
<div class="btn-group btn-group-sm list-item-actions shopping-item-actions" role="group">
<div class="list-item-actions shopping-item-actions" role="group">
{% if not is_share %}
<button type="button" class="btn btn-outline-light" {% if list.is_archived %}disabled{% else
<button type="button" class="btn btn-outline-light btn-sm drag-handle" title="Przesuń produkt" aria-label="Przesuń produkt" {% if list.is_archived %}disabled{% endif %}></button>
<button type="button" class="btn btn-outline-light btn-sm" {% if list.is_archived %}disabled{% else
%}onclick="editItem({{ item.id }}, '{{ item.name }}', {{ item.quantity or 1 }})" {% endif %}>✏️</button>
<button type="button" class="btn btn-outline-light" {% if list.is_archived %}disabled{% else
<button type="button" class="btn btn-outline-light btn-sm" {% if list.is_archived %}disabled{% else
%}onclick="deleteItem({{ item.id }})" {% endif %}>🗑️</button>
{% endif %}
{% if item.not_purchased %}
<button type="button" class="btn btn-outline-light" {% if list.is_archived %}disabled{% else
<button type="button" class="btn btn-outline-light btn-sm" {% if list.is_archived %}disabled{% else
%}onclick="unmarkNotPurchased({{ item.id }})" {% endif %}>✅ Przywróć</button>
{% elif not item.not_purchased %}
<button type="button" class="btn btn-outline-light" {% if list.is_archived %}disabled{% else
<button type="button" class="btn btn-outline-light btn-sm" {% if list.is_archived %}disabled{% else
%}onclick="markNotPurchasedModal(event, {{ item.id }})" {% endif %}>⚠️</button>
{% endif %}
</div>
@@ -155,17 +156,15 @@
{% if not list.is_archived %}
<div class="list-action-block mb-3">
<div class="d-flex flex-wrap gap-2 mb-2">
<form method="post" action="{{ url_for('create_template_from_user_list', list_id=list.id) }}" class="d-inline">
<div class="list-action-row mb-2">
<button class="btn btn-outline-light btn-sm list-action-row__btn" data-bs-toggle="modal" data-bs-target="#massAddModal">
Dodaj produkty masowo
</button>
<form method="post" action="{{ url_for('create_template_from_user_list', list_id=list.id) }}" class="list-action-row__form">
<input type="hidden" name="template_name" value="{{ list.title }} - szablon">
<button type="submit" class="btn btn-outline-primary btn-sm">🧩 Zapisz jako szablon</button>
<button type="submit" class="btn btn-outline-primary btn-sm list-action-row__btn">🧩 Zapisz jako szablon</button>
</form>
</div>
<div class="mb-2">
<button class="btn btn-outline-light w-100" data-bs-toggle="modal" data-bs-target="#massAddModal">
Dodaj produkty masowo
</button>
</div>
<div class="input-group mb-2 shopping-compact-input-group shopping-product-input-group">
<input type="text" id="newItem" name="name"

View File

@@ -2,40 +2,40 @@
{% block title %}Lista: {{ list.title }}{% endblock %}
{% block content %}
<h2 class="mb-2">
🛍️ {{ list.title }}
<div class="list-header-toolbar d-flex justify-content-between align-items-start mb-3 flex-wrap gap-2">
<h2 class="mb-0">
🛍️ {{ list.title }}
{% if list.is_archived %}
<span class="badge rounded-pill bg-secondary ms-2">(Archiwalna)</span>
{% endif %}
{% if list.is_archived %}
<span class="badge rounded-pill bg-secondary ms-2">(Archiwalna)</span>
{% endif %}
{% if total_expense > 0 %}
<span id="total-expense1" class="badge rounded-pill bg-success ms-2">
💸 {{ '%.2f'|format(total_expense) }} PLN
</span>
{% else %}
<span id="total-expense" class="badge rounded-pill bg-secondary ms-2" style="display: none;">
💸 0.00 PLN
</span>
{% endif %}
{% if total_expense > 0 %}
<span id="total-expense1" class="badge rounded-pill bg-success ms-2">
💸 {{ '%.2f'|format(total_expense) }} PLN
</span>
{% else %}
<span id="total-expense" class="badge rounded-pill bg-secondary ms-2" style="display: none;">
💸 0.00 PLN
</span>
{% endif %}
{% if list.category_badges %}
{% for cat in list.category_badges %}
<span class="badge rounded-pill rounded-pill text-dark ms-1" style="background-color: {{ cat.color }};
font-size: 0.75rem;
opacity: 0.85;">
{{ cat.name }}
</span>
{% endfor %}
{% endif %}
{% if list.category_badges %}
{% for cat in list.category_badges %}
<span class="badge rounded-pill rounded-pill text-dark ms-1" style="background-color: {{ cat.color }};
font-size: 0.75rem;
opacity: 0.85;">
{{ cat.name }}
</span>
{% endfor %}
{% endif %}
</h2>
</h2>
<div class="list-toolbar list-toolbar--share d-flex justify-content-end align-items-start mb-3 gap-2 share-page-toolbar">
<div class="form-check form-switch form-check-spaced app-switch hide-purchased-switch hide-purchased-switch--minimal">
<input class="form-check-input" type="checkbox" id="hidePurchasedToggle">
<label class="form-check-label ms-2" for="hidePurchasedToggle">Ukryj zaznaczone</label>
<div class="list-toolbar list-toolbar--share d-flex justify-content-end align-items-center gap-2 share-page-toolbar">
<div class="form-check form-switch form-check-spaced app-switch hide-purchased-switch hide-purchased-switch--minimal hide-purchased-switch--right">
<input class="form-check-input" type="checkbox" id="hidePurchasedToggle">
<label class="form-check-label ms-2" for="hidePurchasedToggle">Ukryj zaznaczone</label>
</div>
</div>
</div>
@@ -61,10 +61,10 @@
{% if item.not_purchased_reason %}{% set _ = info_parts.append('<span class="text-dark">[ <b>Powód: ' ~ item.not_purchased_reason ~ '</b> ]</span>') %}{% endif %}
{% if item.added_by_display %}{% set _ = info_parts.append('<span class="text-info">[ Dodał/a: <b>' ~ item.added_by_display ~ '</b> ]</span>') %}{% endif %}
{% if info_parts %}
<div class="info-line small d-flex flex-wrap gap-2" id="info-{{ item.id }}">{{ info_parts | join(' ') | safe }}</div>
<span class="info-line small" id="info-{{ item.id }}">{{ info_parts | join(' ') | safe }}</span>
{% endif %}
</div>
<div class="d-flex align-items-center list-item-actions shopping-item-actions" role="group">
<div class="list-item-actions shopping-item-actions" role="group">
{% if item.not_purchased %}
<button type="button" class="btn btn-outline-light btn-sm" {% if list.is_archived %}disabled{% else %}
onclick="unmarkNotPurchased({{ item.id }})" {% endif %}>