small fixes in css

This commit is contained in:
Mateusz Gruszczyński
2026-03-15 14:01:54 +01:00
parent 3a57f2f1d7
commit ad5dbcc24b
4 changed files with 398 additions and 92 deletions

View File

@@ -3619,6 +3619,28 @@ input[type="checkbox"].form-check-input,
flex: 0 0 auto;
}
.endpoint-list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-product-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-expense-input-group > .shopping-compact-submit {
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-top-right-radius: .9rem !important;
border-bottom-right-radius: .9rem !important;
margin-left: 0;
}
.endpoint-list .shopping-product-input-group,
.endpoint-list_share .shopping-product-input-group,
.endpoint-shared_list .shopping-product-input-group,
.endpoint-list .shopping-expense-input-group,
.endpoint-list_share .shopping-expense-input-group,
.endpoint-shared_list .shopping-expense-input-group {
flex-wrap: nowrap;
}
@media (max-width: 991.98px) {
.navbar-collapse .app-navbar__actions {
padding-top: .6rem;
@@ -3658,17 +3680,26 @@ input[type="checkbox"].form-check-input,
.shopping-product-input-group > .shopping-product-name-input,
.shopping-expense-input-group > .shopping-expense-amount-input {
flex: 1 1 auto;
flex: 0 0 60%;
min-width: 0;
}
.shopping-product-input-group > .shopping-qty-input {
flex: 0 0 3.8rem;
max-width: 3.8rem;
flex: 0 0 15%;
max-width: 15%;
min-width: 0;
}
.shopping-expense-input-group > .shopping-compact-submit,
.shopping-product-input-group > .shopping-compact-submit {
flex: 0 0 25%;
width: 25%;
min-width: 0;
padding-left: .55rem;
padding-right: .55rem;
font-size: .95rem;
}
.shopping-expense-input-group > .shopping-compact-submit {
padding-left: .7rem;
padding-right: .7rem;
}
@@ -3712,3 +3743,272 @@ input[type="checkbox"].form-check-input,
display: inline !important;
}
}
/* form input/button unification fix 2026-03-15 */
.endpoint-list .shopping-product-input-group,
.endpoint-list_share .shopping-product-input-group,
.endpoint-shared_list .shopping-product-input-group,
.endpoint-list .shopping-expense-input-group,
.endpoint-list_share .shopping-expense-input-group,
.endpoint-shared_list .shopping-expense-input-group {
display: flex;
flex-wrap: nowrap !important;
align-items: stretch;
gap: 0 !important;
}
.endpoint-list .shopping-product-input-group > .form-control,
.endpoint-list_share .shopping-product-input-group > .form-control,
.endpoint-shared_list .shopping-product-input-group > .form-control,
.endpoint-list .shopping-expense-input-group > .form-control,
.endpoint-list_share .shopping-expense-input-group > .form-control,
.endpoint-shared_list .shopping-expense-input-group > .form-control,
.endpoint-list .shopping-product-input-group > .btn,
.endpoint-list_share .shopping-product-input-group > .btn,
.endpoint-shared_list .shopping-product-input-group > .btn,
.endpoint-list .shopping-expense-input-group > .btn,
.endpoint-list_share .shopping-expense-input-group > .btn,
.endpoint-shared_list .shopping-expense-input-group > .btn {
position: relative;
min-height: 46px;
box-shadow: none;
}
.endpoint-list .shopping-product-input-group > .shopping-product-name-input,
.endpoint-list_share .shopping-product-input-group > .shopping-product-name-input,
.endpoint-shared_list .shopping-product-input-group > .shopping-product-name-input,
.endpoint-list .shopping-expense-input-group > .shopping-expense-amount-input,
.endpoint-list_share .shopping-expense-input-group > .shopping-expense-amount-input,
.endpoint-shared_list .shopping-expense-input-group > .shopping-expense-amount-input {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.endpoint-list .shopping-product-input-group > .shopping-qty-input,
.endpoint-list_share .shopping-product-input-group > .shopping-qty-input,
.endpoint-shared_list .shopping-product-input-group > .shopping-qty-input {
border-radius: 0 !important;
border-left-width: 0 !important;
}
.endpoint-list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-product-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-expense-input-group > .shopping-compact-submit {
display: inline-flex;
align-items: center;
justify-content: center;
gap: .35rem;
margin-left: 0 !important;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-top-right-radius: .9rem !important;
border-bottom-right-radius: .9rem !important;
border-left-width: 0 !important;
}
.endpoint-list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-list .share-submit-btn,
.endpoint-list_share .share-submit-btn,
.endpoint-shared_list .share-submit-btn {
min-width: 7.25rem;
}
.shopping-btn-icon {
line-height: 1;
}
.shopping-btn-label {
line-height: 1;
}
@media (max-width: 767.98px) {
.endpoint-list .shopping-product-input-group,
.endpoint-list_share .shopping-product-input-group,
.endpoint-shared_list .shopping-product-input-group,
.endpoint-list .shopping-expense-input-group,
.endpoint-list_share .shopping-expense-input-group,
.endpoint-shared_list .shopping-expense-input-group {
width: 100%;
}
.endpoint-list .shopping-product-input-group > .shopping-product-name-input,
.endpoint-list_share .shopping-product-input-group > .shopping-product-name-input,
.endpoint-shared_list .shopping-product-input-group > .shopping-product-name-input {
flex: 0 0 60% !important;
max-width: 60% !important;
min-width: 0;
}
.endpoint-list .shopping-product-input-group > .shopping-qty-input,
.endpoint-list_share .shopping-product-input-group > .shopping-qty-input,
.endpoint-shared_list .shopping-product-input-group > .shopping-qty-input {
flex: 0 0 15% !important;
max-width: 15% !important;
min-width: 0;
padding-left: .35rem;
padding-right: .35rem;
}
.endpoint-list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-product-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-product-input-group > .shopping-compact-submit {
flex: 0 0 25% !important;
width: 25% !important;
min-width: 0 !important;
padding-left: .4rem;
padding-right: .4rem;
}
.endpoint-list .shopping-expense-input-group > .shopping-expense-amount-input,
.endpoint-list_share .shopping-expense-input-group > .shopping-expense-amount-input,
.endpoint-shared_list .shopping-expense-input-group > .shopping-expense-amount-input {
flex: 1 1 auto !important;
min-width: 0;
}
.endpoint-list .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-list_share .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-shared_list .shopping-expense-input-group > .shopping-compact-submit {
flex: 0 0 5rem !important;
width: 5rem !important;
min-width: 5rem !important;
padding-left: .35rem;
padding-right: .35rem;
}
.endpoint-list .shopping-product-input-group > .shopping-compact-submit .shopping-btn-label,
.endpoint-list_share .shopping-product-input-group > .shopping-compact-submit .shopping-btn-label,
.endpoint-shared_list .shopping-product-input-group > .shopping-compact-submit .shopping-btn-label,
.endpoint-list .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-label,
.endpoint-list_share .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-label,
.endpoint-shared_list .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-label {
display: none;
}
.endpoint-list .shopping-product-input-group > .shopping-compact-submit .shopping-btn-icon,
.endpoint-list_share .shopping-product-input-group > .shopping-compact-submit .shopping-btn-icon,
.endpoint-shared_list .shopping-product-input-group > .shopping-compact-submit .shopping-btn-icon,
.endpoint-list .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-icon,
.endpoint-list_share .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-icon,
.endpoint-shared_list .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-icon {
margin: 0;
font-size: 1rem;
}
}
/* endpoint fix for /list route */
.endpoint-view_list .shopping-product-input-group,
.endpoint-view_list .shopping-expense-input-group {
display: flex;
flex-wrap: nowrap !important;
align-items: stretch;
gap: 0 !important;
width: 100%;
}
.endpoint-view_list .shopping-product-input-group > .form-control,
.endpoint-view_list .shopping-expense-input-group > .form-control,
.endpoint-view_list .shopping-product-input-group > .btn,
.endpoint-view_list .shopping-expense-input-group > .btn {
position: relative;
min-height: 46px;
box-shadow: none;
}
.endpoint-view_list .shopping-product-input-group > .shopping-product-name-input,
.endpoint-view_list .shopping-expense-input-group > .shopping-expense-amount-input {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.endpoint-view_list .shopping-product-input-group > .shopping-qty-input {
border-radius: 0 !important;
border-left-width: 0 !important;
}
.endpoint-view_list .shopping-product-input-group > .shopping-compact-submit,
.endpoint-view_list .shopping-expense-input-group > .shopping-compact-submit,
.endpoint-view_list .share-submit-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: .35rem;
margin-left: 0 !important;
min-width: 7.25rem;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-top-right-radius: .9rem !important;
border-bottom-right-radius: .9rem !important;
border-left-width: 0 !important;
}
@media (max-width: 767.98px) {
.endpoint-view_list .shopping-product-input-group > .shopping-product-name-input {
flex: 0 0 60% !important;
max-width: 60% !important;
min-width: 0;
}
.endpoint-view_list .shopping-product-input-group > .shopping-qty-input {
flex: 0 0 15% !important;
max-width: 15% !important;
min-width: 0;
padding-left: .35rem;
padding-right: .35rem;
}
.endpoint-view_list .shopping-product-input-group > .shopping-compact-submit {
flex: 0 0 25% !important;
width: 25% !important;
min-width: 0 !important;
padding-left: .4rem;
padding-right: .4rem;
}
.endpoint-view_list .shopping-expense-input-group > .shopping-expense-amount-input {
flex: 1 1 auto !important;
min-width: 0;
}
.endpoint-view_list .shopping-expense-input-group > .shopping-compact-submit {
flex: 0 0 5rem !important;
width: 5rem !important;
min-width: 5rem !important;
padding-left: .35rem;
padding-right: .35rem;
}
.endpoint-view_list .shopping-product-input-group > .shopping-compact-submit .shopping-btn-label,
.endpoint-view_list .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-label {
display: none;
}
.endpoint-view_list .shopping-product-input-group > .shopping-compact-submit .shopping-btn-icon,
.endpoint-view_list .shopping-expense-input-group > .shopping-compact-submit .shopping-btn-icon {
margin: 0;
font-size: 1rem;
}
}
/* --- JS render + progress bar consistency patch --- */
#progress-bar-purchased {
background: linear-gradient(135deg, rgba(39,208,125,0.96), rgba(22,150,91,0.98)) !important;
}
#progress-bar-not-purchased {
background: linear-gradient(135deg, rgba(246,196,83,0.96), rgba(224,164,26,0.98)) !important;
}
#progress-bar-remaining {
background: rgba(255,255,255,0.08) !important;
}

View File

@@ -257,6 +257,17 @@ function showToast(message, type = 'primary') {
setTimeout(() => { toast.remove(); }, 1750);
}
function escapeHtml(value) {
return String(value ?? '')
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
}
function isListDifferent(oldItems, newItems) {
if (oldItems.length !== newItems.length) return true;
@@ -271,96 +282,85 @@ function isListDifferent(oldItems, newItems) {
return false;
}
function renderItem(item, isShare = window.IS_SHARE, showEditOnly = false) {
const li = document.createElement('li');
li.id = `item-${item.id}`;
li.dataset.name = item.name.toLowerCase();
li.className = `list-group-item d-flex justify-content-between align-items-center flex-wrap clickable-item ${item.purchased ? 'bg-success text-white'
li.dataset.name = String(item.name || '').toLowerCase();
li.dataset.isShare = isShare ? 'true' : 'false';
li.className = `list-group-item shopping-item-row clickable-item ${item.purchased ? 'bg-success text-white'
: item.not_purchased ? 'bg-warning text-dark'
: 'item-not-checked'
}`;
const isOwner = window.IS_OWNER === true || window.IS_OWNER === 'true';
const allowEdit = !isShare || showEditOnly || isOwner;
const safeName = escapeHtml(item.name || '');
const nameForEdit = JSON.stringify(String(item.name || ''));
const quantity = Number.isInteger(item.quantity) ? item.quantity : parseInt(item.quantity, 10) || 1;
const quantityBadge = quantity > 1
? `<span class="badge rounded-pill bg-secondary">x${quantity}</span>`
: '';
let quantityBadge = '';
if (item.quantity && item.quantity > 1) {
quantityBadge = `<span class="badge bg-secondary">x${item.quantity}</span>`;
const checkboxHtml = `<input id="checkbox-${item.id}" class="large-checkbox" type="checkbox" ${item.purchased ? 'checked' : ''} ${item.not_purchased ? 'disabled' : ''}>`;
const infoParts = [];
if (item.note) {
infoParts.push(`<span class="text-danger">[ <b>${escapeHtml(item.note)}</b> ]</span>`);
}
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) {
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>`
: '';
let checkboxOrIcon = item.not_purchased
? `<span class="ms-1 block-icon">🚫</span>`
: `<input id="checkbox-${item.id}" class="large-checkbox" type="checkbox" ${item.purchased ? 'checked' : ''}>`;
let actionButtons = '';
let noteHTML = item.note
? `<small class="text-danger ms-4">[ <b>${item.note}</b> ]</small>` : '';
let reasonHTML = item.not_purchased_reason
? `<small class="text-dark ms-4">[ <b>Powód: ${item.not_purchased_reason}</b> ]</small>` : '';
let dragHandle = window.isSorting ? `<span class="drag-handle me-2 text-danger" style="cursor: grab;">☰</span>` : '';
let left = `
<div class="d-flex align-items-center gap-2 flex-grow-1">
${dragHandle}
${checkboxOrIcon}
<span id="name-${item.id}" class="text-white">${item.name} ${quantityBadge}</span>
${noteHTML}
${reasonHTML}
</div>`;
let rightButtons = '';
// ✏️ i 🗑️ — tylko jeśli nie jesteśmy w trybie /share lub jesteśmy w 15s (tymczasowo) lub jesteśmy właścicielem
if (allowEdit) {
rightButtons += `
<button type="button" class="btn btn-outline-light"
onclick="editItem(${item.id}, '${item.name.replace(/'/g, "\\'")}', ${item.quantity || 1})">
✏️
</button>
<button type="button" class="btn btn-outline-light"
onclick="deleteItem(${item.id})">
🗑️
</button>`;
actionButtons += `
<button type="button" class="btn btn-outline-light btn-sm"
onclick="editItem(${item.id}, ${nameForEdit}, ${quantity})">✏️</button>
<button type="button" class="btn btn-outline-light btn-sm"
onclick="deleteItem(${item.id})">🗑️</button>`;
}
// ✅ Jeśli element jest oznaczony jako niekupiony — pokaż "Przywróć"
if (item.not_purchased) {
rightButtons += `
<button type="button" class="btn btn-outline-light me-auto"
onclick="unmarkNotPurchased(${item.id})">
✅ Przywróć
</button>`;
actionButtons += `
<button type="button" class="btn btn-outline-light btn-sm"
onclick="unmarkNotPurchased(${item.id})">✅ Przywróć</button>`;
} else if (isOwner || (isShare && !showEditOnly)) {
actionButtons += `
<button type="button" class="btn btn-outline-light btn-sm"
onclick="markNotPurchasedModal(event, ${item.id})">⚠️</button>`;
}
// ⚠️ tylko jeśli NIE jest oznaczony jako niekupiony i nie jesteśmy w 15s
if (!item.not_purchased && (isOwner || (isShare && !showEditOnly))) {
rightButtons += `
<button type="button" class="btn btn-outline-light"
onclick="markNotPurchasedModal(event, ${item.id})">
⚠️
</button>`;
}
// 📝 tylko jeśli jesteśmy w /share i nie jesteśmy w 15s
if (isShare && !showEditOnly && !isOwner) {
rightButtons += `
<button type="button" class="btn btn-outline-light"
onclick="openNoteModal(event, ${item.id})">
📝
</button>`;
actionButtons += `
<button type="button" class="btn btn-outline-light btn-sm"
onclick="openNoteModal(event, ${item.id})">📝</button>`;
}
li.innerHTML = `${left}<div class="btn-group btn-group-sm" role="group">${rightButtons}</div>`;
if (item.added_by && item.owner_id && item.added_by_id && item.added_by_id !== item.owner_id) {
const infoEl = document.createElement('small');
infoEl.className = 'text-info ms-4';
infoEl.innerHTML = `[Dodał/a: <b>${item.added_by}</b>]`;
li.querySelector('.d-flex.align-items-center')?.appendChild(infoEl);
}
li.innerHTML = `
<div class="shopping-item-main">
${checkboxHtml}
<div class="shopping-item-content">
<div class="shopping-item-head">
<div class="shopping-item-text">
<span id="name-${item.id}" class="shopping-item-name text-white">${safeName}</span>
${quantityBadge}
${infoHtml}
</div>
<div class="d-flex align-items-center list-item-actions shopping-item-actions" role="group">
${actionButtons}
</div>
</div>
</div>
</div>`;
return li;
}

View File

@@ -161,21 +161,27 @@
<button type="submit" class="btn btn-outline-primary btn-sm">🧩 Zapisz jako szablon</button>
</form>
</div>
<div class="row g-2 mb-3">
<div class="col-12 col-md-3 col-lg-2">
<button class="btn btn-outline-light w-100" data-bs-toggle="modal" data-bs-target="#massAddModal">
Dodaj produkty masowo
</button>
</div>
<div class="col-12 col-md-9 col-lg-10">
<div class="input-group w-100 shopping-compact-input-group shopping-product-input-group">
<input type="text" id="newItem" name="name" class="form-control bg-dark text-white border-secondary shopping-product-name-input"
placeholder="Dodaj produkt" required>
<input type="number" id="newQuantity" name="quantity" class="form-control bg-dark text-white border-secondary shopping-qty-input"
placeholder="Ilość" min="1" value="1">
<button type="button" class="btn btn-outline-success shopping-compact-submit" onclick="addItem({{ list.id }})"> Dodaj</button>
</div>
</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"
class="form-control bg-dark text-white border-secondary shopping-product-name-input"
placeholder="Dodaj produkt" required>
<input type="number" id="newQuantity" name="quantity"
class="form-control bg-dark text-white border-secondary shopping-qty-input"
placeholder="Ilość" min="1" value="1">
<button type="button"
class="btn btn-outline-success share-submit-btn shopping-compact-submit"
onclick="addItem({{ list.id }})">
<span class="shopping-btn-icon" aria-hidden="true"></span>
<span class="shopping-btn-label">Dodaj</span>
</button>
</div>
{% endif %}
@@ -276,7 +282,7 @@
<div class="modal-footer justify-content-end">
<div class="btn-group" role="group">
<button type="button" class="btn btn-sm btn-outline-light" data-bs-dismiss="modal">❌ Anuluj</button>
<button type="submit" class="btn btn-sm btn-outline-light">💾 Zapisz</button>
<button type="submit" class="btn btn-sm btn-outline-light"><span class="shopping-btn-icon" aria-hidden="true">💾</span><span class="shopping-btn-label">Zapisz</span></button>
</div>
</div>
</form>
@@ -322,7 +328,7 @@
<div class="input-group input-group-sm">
<input type="text" class="access-input form-control form-control-sm bg-dark text-white border-secondary"
placeholder="Dodaj @użytkownika (wiele: przecinki/enter)" list="userHintsOwner" autocomplete="off" aria-label="Dodaj użytkowników">
<button type="button" class="access-add btn btn-sm btn-outline-light"> Dodaj</button>
<button type="button" class="access-add btn btn-sm btn-outline-light"><span class="shopping-btn-icon" aria-hidden="true"></span><span class="shopping-btn-label">Dodaj</span></button>
</div>
<div class="text-secondary small mt-1">Kliknij token, aby odebrać dostęp.</div>
</div>

View File

@@ -100,7 +100,7 @@
<input id="newQuantity" type="number" class="form-control bg-dark text-white border-secondary shopping-qty-input" placeholder="Ilość"
min="1" value="1" {% if not current_user.is_authenticated %}disabled{% endif %}>
<button onclick="addItem({{ list.id }})" class="btn btn-outline-success share-submit-btn shopping-compact-submit" {% if not
current_user.is_authenticated %}disabled{% endif %}> Dodaj</button>
current_user.is_authenticated %}disabled{% endif %}><span class="shopping-btn-icon" aria-hidden="true"></span><span class="shopping-btn-label">Dodaj</span></button>
</div>
{% endif %}
@@ -110,7 +110,7 @@
<div class="input-group mb-2 shopping-compact-input-group shopping-expense-input-group">
<input id="expenseAmount" type="number" step="0.01" min="0" class="form-control bg-dark text-white border-secondary shopping-expense-amount-input"
placeholder="Kwota (PLN)">
<button onclick="submitExpense({{ list.id }})" class="btn btn-outline-primary share-submit-btn shopping-compact-submit">💾 Zapisz</button>
<button onclick="submitExpense({{ list.id }})" class="btn btn-outline-primary share-submit-btn shopping-compact-submit"><span class="shopping-btn-icon" aria-hidden="true">💾</span><span class="shopping-btn-label">Zapisz</span></button>
</div>{% endif %}
<p id="total-expense2"><b>💸 Łącznie wydano:</b> {{ '%.2f'|format(total_expense) }} PLN</p>
@@ -216,7 +216,7 @@
<div class="modal-footer">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-light btn-sm" data-bs-dismiss="modal">❌ Anuluj</button>
<button type="submit" class="btn btn-outline-light btn-sm">💾 Zapisz</button>
<button type="submit" class="btn btn-outline-light btn-sm"><span class="shopping-btn-icon" aria-hidden="true">💾</span><span class="shopping-btn-label">Zapisz</span></button>
</div>
</div>