Extract colors
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m10s
All checks were successful
Build and Deploy / build-and-push (push) Successful in 1m10s
This commit is contained in:
137
index.html
137
index.html
@@ -31,7 +31,6 @@
|
|||||||
--text-primary-rgb: 28, 24, 21;
|
--text-primary-rgb: 28, 24, 21;
|
||||||
--text-secondary-rgb: 102, 92, 83;
|
--text-secondary-rgb: 102, 92, 83;
|
||||||
--text-tertiary-rgb: 156, 146, 137;
|
--text-tertiary-rgb: 156, 146, 137;
|
||||||
--accent-rgb: 111, 149, 255;
|
|
||||||
--warm-rgb: 183, 142, 88;
|
--warm-rgb: 183, 142, 88;
|
||||||
--success-rgb: 98, 171, 132;
|
--success-rgb: 98, 171, 132;
|
||||||
--danger-rgb: 210, 116, 116;
|
--danger-rgb: 210, 116, 116;
|
||||||
@@ -40,27 +39,66 @@
|
|||||||
--dock-shadow: 0 24px 56px rgba(24, 17, 11, 0.18);
|
--dock-shadow: 0 24px 56px rgba(24, 17, 11, 0.18);
|
||||||
--highlight-top: rgba(111, 149, 255, 0.14);
|
--highlight-top: rgba(111, 149, 255, 0.14);
|
||||||
--highlight-bottom: rgba(97, 184, 180, 0.12);
|
--highlight-bottom: rgba(97, 184, 180, 0.12);
|
||||||
|
|
||||||
|
/* Extended palette (placeholder light-mode values — light mode is WIP). */
|
||||||
|
--card-rgb: 255, 255, 255;
|
||||||
|
--card-soft-rgb: 250, 246, 240;
|
||||||
|
--card-strong-rgb: 235, 229, 221;
|
||||||
|
--card-raised-rgb: 252, 248, 242;
|
||||||
|
--sunken-rgb: 247, 242, 236;
|
||||||
|
--sunken-deep-rgb: 235, 229, 221;
|
||||||
|
--border-card-rgb: 220, 212, 200;
|
||||||
|
--border-input-rgb: 176, 164, 150;
|
||||||
|
--text-emphasis-rgb: 14, 12, 10;
|
||||||
|
--text-body-rgb: 48, 40, 33;
|
||||||
|
--text-body-soft-rgb: 72, 62, 52;
|
||||||
|
--text-muted-rgb: 112, 102, 91;
|
||||||
|
--text-dim-rgb: 140, 130, 118;
|
||||||
|
--text-faint-rgb: 156, 146, 137;
|
||||||
|
--text-subdued-rgb: 176, 166, 154;
|
||||||
|
--skeleton-rgb: 226, 220, 210;
|
||||||
|
--on-accent-rgb: 255, 255, 255;
|
||||||
|
--overlay-rgb: 24, 17, 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
color-scheme: dark;
|
color-scheme: dark;
|
||||||
--app-bg-rgb: 45, 46, 43;
|
--app-bg-rgb: 45, 46, 43; /* #2d2e2b */
|
||||||
--surface-rgb: 37, 35, 33;
|
--surface-rgb: 37, 35, 33; /* panel/input backgrounds (existing tokens) */
|
||||||
--surface-soft-rgb: 46, 43, 40;
|
--surface-soft-rgb: 46, 43, 40;
|
||||||
--surface-strong-rgb: 58, 55, 51;
|
--surface-strong-rgb: 58, 55, 51;
|
||||||
--line-rgb: 255, 249, 239;
|
--line-rgb: 255, 249, 239;
|
||||||
--text-primary-rgb: 246, 241, 232;
|
--text-primary-rgb: 246, 241, 232;
|
||||||
--text-secondary-rgb: 183, 173, 161;
|
--text-secondary-rgb: 183, 173, 161; /* #b7ada1 */
|
||||||
--text-tertiary-rgb: 129, 121, 112;
|
--text-tertiary-rgb: 129, 121, 112;
|
||||||
--accent-rgb: 134, 171, 255;
|
|
||||||
--warm-rgb: 198, 156, 101;
|
--warm-rgb: 198, 156, 101;
|
||||||
--success-rgb: 109, 194, 144;
|
--success-rgb: 110, 231, 183; /* #6ee7b7 — unified success green */
|
||||||
--danger-rgb: 220, 127, 127;
|
--danger-rgb: 220, 127, 127;
|
||||||
--panel-shadow: 0 22px 56px rgba(0, 0, 0, 0.24);
|
--panel-shadow: 0 22px 56px rgba(0, 0, 0, 0.24);
|
||||||
--panel-shadow-strong: 0 30px 82px rgba(0, 0, 0, 0.42);
|
--panel-shadow-strong: 0 30px 82px rgba(0, 0, 0, 0.42);
|
||||||
--dock-shadow: 0 30px 84px rgba(0, 0, 0, 0.42);
|
--dock-shadow: 0 30px 84px rgba(0, 0, 0, 0.42);
|
||||||
--highlight-top: transparent;
|
--highlight-top: transparent;
|
||||||
--highlight-bottom: transparent;
|
--highlight-bottom: transparent;
|
||||||
|
|
||||||
|
/* Extended dark palette — distinct shades used across cards, dock, pickers, inputs. */
|
||||||
|
--card-rgb: 57, 57, 55; /* #393937 — primary elevated card */
|
||||||
|
--card-soft-rgb: 47, 47, 45; /* #2f2f2d — medium card */
|
||||||
|
--card-strong-rgb: 68, 68, 66; /* #444442 — strong card / stroke */
|
||||||
|
--card-raised-rgb: 58, 58, 55; /* #3a3a37 — slight raise above card */
|
||||||
|
--sunken-rgb: 35, 34, 30; /* #23221e — deep inputs / search shell */
|
||||||
|
--sunken-deep-rgb: 22, 21, 19; /* #161513 — deepest well */
|
||||||
|
--border-card-rgb: 65, 66, 63; /* #41423f — dock/picker borders */
|
||||||
|
--border-input-rgb: 120, 120, 118; /* #787876 — input / active borders */
|
||||||
|
--text-emphasis-rgb: 242, 239, 232; /* #f2efe8 — brightest interactive text */
|
||||||
|
--text-body-rgb: 221, 214, 202; /* #ddd6ca — primary body text (most common) */
|
||||||
|
--text-body-soft-rgb: 215, 210, 200; /* #d7d2c8 — body soft */
|
||||||
|
--text-muted-rgb: 183, 173, 161; /* #b7ada1 — muted (matches --text-secondary) */
|
||||||
|
--text-dim-rgb: 155, 151, 143; /* #9b978f — dim / placeholder */
|
||||||
|
--text-faint-rgb: 143, 139, 132; /* #8f8b84 — faint icon color */
|
||||||
|
--text-subdued-rgb: 109, 108, 103; /* #6d6c67 — subdued */
|
||||||
|
--skeleton-rgb: 212, 212, 212; /* #d4d4d4 — image loading placeholder */
|
||||||
|
--on-accent-rgb: 26, 26, 26; /* #1a1a1a — text on bright accent backgrounds */
|
||||||
|
--overlay-rgb: 0, 0, 0; /* scrim / shadow base */
|
||||||
}
|
}
|
||||||
|
|
||||||
* { touch-action: manipulation; }
|
* { touch-action: manipulation; }
|
||||||
@@ -84,7 +122,7 @@
|
|||||||
height: 20px;
|
height: 20px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: rgb(var(--accent-rgb));
|
background: rgb(var(--text-body-rgb));
|
||||||
border: 2px solid rgba(var(--surface-rgb), 0.9);
|
border: 2px solid rgba(var(--surface-rgb), 0.9);
|
||||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22);
|
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.22);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -120,7 +158,7 @@
|
|||||||
background: linear-gradient(180deg, rgba(var(--surface-strong-rgb), 1) 0%, rgba(var(--surface-soft-rgb), 1) 100%) !important;
|
background: linear-gradient(180deg, rgba(var(--surface-strong-rgb), 1) 0%, rgba(var(--surface-soft-rgb), 1) 100%) !important;
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 12px 28px rgba(0, 0, 0, 0.18) !important;
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 12px 28px rgba(0, 0, 0, 0.18) !important;
|
||||||
}
|
}
|
||||||
.border-gray-900 { border-color: rgba(var(--accent-rgb), 0.42) !important; }
|
.border-gray-900 { border-color: rgba(var(--text-body-rgb), 0.42) !important; }
|
||||||
.bg-white\/90 { background-color: rgba(var(--surface-rgb), 0.9) !important; }
|
.bg-white\/90 { background-color: rgba(var(--surface-rgb), 0.9) !important; }
|
||||||
.bg-white\/80 { background-color: rgba(var(--surface-rgb), 0.78) !important; }
|
.bg-white\/80 { background-color: rgba(var(--surface-rgb), 0.78) !important; }
|
||||||
.bg-gray-50\/80 { background-color: rgba(var(--surface-soft-rgb), 0.72) !important; }
|
.bg-gray-50\/80 { background-color: rgba(var(--surface-soft-rgb), 0.72) !important; }
|
||||||
@@ -146,7 +184,7 @@
|
|||||||
.divide-red-50 > :not([hidden]) ~ :not([hidden]) { border-color: rgba(var(--danger-rgb), 0.1) !important; }
|
.divide-red-50 > :not([hidden]) ~ :not([hidden]) { border-color: rgba(var(--danger-rgb), 0.1) !important; }
|
||||||
|
|
||||||
.ring-gray-200 { --tw-ring-color: rgba(var(--line-rgb), 0.16) !important; }
|
.ring-gray-200 { --tw-ring-color: rgba(var(--line-rgb), 0.16) !important; }
|
||||||
.ring-gray-900 { --tw-ring-color: rgba(var(--accent-rgb), 0.52) !important; }
|
.ring-gray-900 { --tw-ring-color: rgba(var(--text-body-rgb), 0.52) !important; }
|
||||||
|
|
||||||
.hover\:bg-gray-50:hover { background-color: rgba(var(--surface-soft-rgb), 0.94) !important; }
|
.hover\:bg-gray-50:hover { background-color: rgba(var(--surface-soft-rgb), 0.94) !important; }
|
||||||
.hover\:bg-gray-100:hover { background-color: rgba(var(--surface-strong-rgb), 0.94) !important; }
|
.hover\:bg-gray-100:hover { background-color: rgba(var(--surface-strong-rgb), 0.94) !important; }
|
||||||
@@ -159,11 +197,11 @@
|
|||||||
.hover\:text-red-600:hover { color: rgba(var(--danger-rgb), 1) !important; }
|
.hover\:text-red-600:hover { color: rgba(var(--danger-rgb), 1) !important; }
|
||||||
.hover\:border-gray-300:hover { border-color: rgba(var(--line-rgb), 0.28) !important; }
|
.hover\:border-gray-300:hover { border-color: rgba(var(--line-rgb), 0.28) !important; }
|
||||||
.hover\:border-gray-400:hover { border-color: rgba(var(--line-rgb), 0.34) !important; }
|
.hover\:border-gray-400:hover { border-color: rgba(var(--line-rgb), 0.34) !important; }
|
||||||
.hover\:border-gray-900:hover { border-color: rgba(var(--accent-rgb), 0.54) !important; }
|
.hover\:border-gray-900:hover { border-color: rgba(var(--text-body-rgb), 0.54) !important; }
|
||||||
.hover\:border-red-200:hover { border-color: rgba(var(--danger-rgb), 0.34) !important; }
|
.hover\:border-red-200:hover { border-color: rgba(var(--danger-rgb), 0.34) !important; }
|
||||||
|
|
||||||
.focus\:border-gray-400:focus { border-color: rgba(var(--accent-rgb), 0.54) !important; }
|
.focus\:border-gray-400:focus { border-color: rgba(var(--text-body-rgb), 0.54) !important; }
|
||||||
.focus\:border-gray-300:focus { border-color: rgba(var(--accent-rgb), 0.44) !important; }
|
.focus\:border-gray-300:focus { border-color: rgba(var(--text-body-rgb), 0.44) !important; }
|
||||||
|
|
||||||
.shadow-lg { box-shadow: var(--panel-shadow-strong) !important; }
|
.shadow-lg { box-shadow: var(--panel-shadow-strong) !important; }
|
||||||
.shadow-sm { box-shadow: var(--panel-shadow) !important; }
|
.shadow-sm { box-shadow: var(--panel-shadow) !important; }
|
||||||
@@ -213,17 +251,26 @@
|
|||||||
.text-emerald-600 { color: rgba(var(--success-rgb), 0.94) !important; }
|
.text-emerald-600 { color: rgba(var(--success-rgb), 0.94) !important; }
|
||||||
.text-emerald-600\/80 { color: rgba(var(--success-rgb), 0.82) !important; }
|
.text-emerald-600\/80 { color: rgba(var(--success-rgb), 0.82) !important; }
|
||||||
.text-emerald-500 { color: rgba(var(--success-rgb), 0.9) !important; }
|
.text-emerald-500 { color: rgba(var(--success-rgb), 0.9) !important; }
|
||||||
|
.text-emerald-400 { color: rgb(var(--success-rgb)) !important; }
|
||||||
|
.text-emerald-300 { color: rgb(var(--success-rgb)) !important; }
|
||||||
|
.bg-emerald-400 { background-color: rgb(var(--success-rgb)) !important; }
|
||||||
|
.border-emerald-400\/40 { border-color: rgba(var(--success-rgb), 0.4) !important; }
|
||||||
|
|
||||||
.bg-red-50 { background-color: rgba(var(--danger-rgb), 0.12) !important; }
|
.bg-red-50 { background-color: rgba(var(--danger-rgb), 0.12) !important; }
|
||||||
.bg-red-100 { background-color: rgba(var(--danger-rgb), 0.2) !important; }
|
.bg-red-100 { background-color: rgba(var(--danger-rgb), 0.2) !important; }
|
||||||
.bg-red-500 { background-color: rgba(var(--danger-rgb), 0.94) !important; }
|
.bg-red-500 { background-color: rgba(var(--danger-rgb), 0.94) !important; }
|
||||||
|
.bg-red-400 { background-color: rgba(var(--danger-rgb), 0.82) !important; }
|
||||||
.border-red-200\/80 { border-color: rgba(var(--danger-rgb), 0.26) !important; }
|
.border-red-200\/80 { border-color: rgba(var(--danger-rgb), 0.26) !important; }
|
||||||
.border-red-100\/80 { border-color: rgba(var(--danger-rgb), 0.16) !important; }
|
.border-red-100\/80 { border-color: rgba(var(--danger-rgb), 0.16) !important; }
|
||||||
|
.border-red-300\/40 { border-color: rgba(var(--danger-rgb), 0.4) !important; }
|
||||||
|
.border-red-300\/30 { border-color: rgba(var(--danger-rgb), 0.3) !important; }
|
||||||
.text-red-800 { color: rgba(var(--danger-rgb), 1) !important; }
|
.text-red-800 { color: rgba(var(--danger-rgb), 1) !important; }
|
||||||
.text-red-600 { color: rgba(var(--danger-rgb), 0.96) !important; }
|
.text-red-600 { color: rgba(var(--danger-rgb), 0.96) !important; }
|
||||||
.text-red-600\/80 { color: rgba(var(--danger-rgb), 0.82) !important; }
|
.text-red-600\/80 { color: rgba(var(--danger-rgb), 0.82) !important; }
|
||||||
.text-red-500 { color: rgba(var(--danger-rgb), 0.9) !important; }
|
.text-red-500 { color: rgba(var(--danger-rgb), 0.9) !important; }
|
||||||
.text-red-400 { color: rgba(var(--danger-rgb), 0.78) !important; }
|
.text-red-400 { color: rgba(var(--danger-rgb), 0.78) !important; }
|
||||||
|
.text-red-300 { color: rgba(var(--danger-rgb), 0.66) !important; }
|
||||||
|
.hover\:text-red-500:hover { color: rgba(var(--danger-rgb), 0.9) !important; }
|
||||||
|
|
||||||
/* App shell */
|
/* App shell */
|
||||||
#main-view,
|
#main-view,
|
||||||
@@ -235,7 +282,7 @@
|
|||||||
#main-view > div:last-child,
|
#main-view > div:last-child,
|
||||||
#recipe-grid,
|
#recipe-grid,
|
||||||
#planner-picker-grid {
|
#planner-picker-grid {
|
||||||
background: #2d2e2b !important;
|
background: rgb(var(--app-bg-rgb)) !important;
|
||||||
}
|
}
|
||||||
#recipe-grid,
|
#recipe-grid,
|
||||||
#planner-picker-grid {
|
#planner-picker-grid {
|
||||||
@@ -250,7 +297,7 @@
|
|||||||
#calendar-week-wrap,
|
#calendar-week-wrap,
|
||||||
#calendar-month-wrap,
|
#calendar-month-wrap,
|
||||||
#planner-meal-slots {
|
#planner-meal-slots {
|
||||||
background: #2d2e2b !important;
|
background: rgb(var(--app-bg-rgb)) !important;
|
||||||
}
|
}
|
||||||
#main-view > div:first-child,
|
#main-view > div:first-child,
|
||||||
#planner-view > div:first-child,
|
#planner-view > div:first-child,
|
||||||
@@ -262,7 +309,7 @@
|
|||||||
/* Cards and sheets */
|
/* Cards and sheets */
|
||||||
#recipe-grid > *,
|
#recipe-grid > *,
|
||||||
#planner-picker-grid > * {
|
#planner-picker-grid > * {
|
||||||
background: #393937 !important;
|
background: rgb(var(--card-rgb)) !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
border-radius: 1.75rem !important;
|
border-radius: 1.75rem !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
@@ -354,8 +401,8 @@
|
|||||||
}
|
}
|
||||||
#recipe-topbar #recipe-search-shell,
|
#recipe-topbar #recipe-search-shell,
|
||||||
#recipe-topbar #recipe-search-shell:focus-within {
|
#recipe-topbar #recipe-search-shell:focus-within {
|
||||||
background: #23221e !important;
|
background: rgb(var(--sunken-rgb)) !important;
|
||||||
border: 1px solid #787876 !important;
|
border: 1px solid rgb(var(--border-input-rgb)) !important;
|
||||||
backdrop-filter: none;
|
backdrop-filter: none;
|
||||||
-webkit-backdrop-filter: none;
|
-webkit-backdrop-filter: none;
|
||||||
}
|
}
|
||||||
@@ -365,11 +412,11 @@
|
|||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
color: #ddd6ca !important;
|
color: rgb(var(--text-body-rgb)) !important;
|
||||||
caret-color: #ddd6ca;
|
caret-color: rgb(var(--text-body-rgb));
|
||||||
}
|
}
|
||||||
#recipe-topbar #recipe-search-input::placeholder {
|
#recipe-topbar #recipe-search-input::placeholder {
|
||||||
color: #9b978f !important;
|
color: rgb(var(--text-dim-rgb)) !important;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
#recipe-topbar #recipe-filter-btn {
|
#recipe-topbar #recipe-filter-btn {
|
||||||
@@ -383,8 +430,8 @@
|
|||||||
z-index: 0;
|
z-index: 0;
|
||||||
isolation: isolate;
|
isolation: isolate;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #393937 !important;
|
background: rgb(var(--card-rgb)) !important;
|
||||||
border: 1px solid #41423f !important;
|
border: 1px solid rgb(var(--border-card-rgb)) !important;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 5px 10px rgba(0, 0, 0, 0.16),
|
0 5px 10px rgba(0, 0, 0, 0.16),
|
||||||
0 14px 22px rgba(0, 0, 0, 0.24),
|
0 14px 22px rgba(0, 0, 0, 0.24),
|
||||||
@@ -410,8 +457,8 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
#planner-picker-search-shell:focus-within {
|
#planner-picker-search-shell:focus-within {
|
||||||
background: #393937 !important;
|
background: rgb(var(--card-rgb)) !important;
|
||||||
border: 1px solid #4a4b47 !important;
|
border: 1px solid rgba(var(--border-input-rgb), 0.62) !important;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 6px 12px rgba(0, 0, 0, 0.18),
|
0 6px 12px rgba(0, 0, 0, 0.18),
|
||||||
0 16px 24px rgba(0, 0, 0, 0.24),
|
0 16px 24px rgba(0, 0, 0, 0.24),
|
||||||
@@ -427,15 +474,15 @@
|
|||||||
border: none !important;
|
border: none !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
backdrop-filter: none !important;
|
backdrop-filter: none !important;
|
||||||
color: #dfd9cf !important;
|
color: rgb(var(--text-body-rgb)) !important;
|
||||||
caret-color: #dfd9cf;
|
caret-color: rgb(var(--text-body-rgb));
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: -0.02em;
|
||||||
}
|
}
|
||||||
#planner-picker-search::placeholder,
|
#planner-picker-search::placeholder,
|
||||||
#pantry-search::placeholder {
|
#pantry-search::placeholder {
|
||||||
color: #beb8ae !important;
|
color: rgba(var(--text-body-soft-rgb), 0.72) !important;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
#planner-picker-filter-btn {
|
#planner-picker-filter-btn {
|
||||||
@@ -470,7 +517,7 @@
|
|||||||
#planner-ing-backdrop,
|
#planner-ing-backdrop,
|
||||||
#pv2-edit-bg,
|
#pv2-edit-bg,
|
||||||
#mpe-overlay {
|
#mpe-overlay {
|
||||||
background: rgba(7, 6, 5, 0.42) !important;
|
background: rgba(var(--overlay-rgb), 0.42) !important;
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,8 +543,8 @@
|
|||||||
gap: 0.06rem;
|
gap: 0.06rem;
|
||||||
padding: 0.22rem;
|
padding: 0.22rem;
|
||||||
border-radius: 1.68rem;
|
border-radius: 1.68rem;
|
||||||
background: #393937;
|
background: rgb(var(--card-rgb));
|
||||||
border: 1px solid #41423f;
|
border: 1px solid rgb(var(--border-card-rgb));
|
||||||
box-shadow:
|
box-shadow:
|
||||||
inset 0 1px 8px rgba(0, 0, 0, 0.15),
|
inset 0 1px 8px rgba(0, 0, 0, 0.15),
|
||||||
0 5px 10px rgba(0, 0, 0, 0.16),
|
0 5px 10px rgba(0, 0, 0, 0.16),
|
||||||
@@ -528,7 +575,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
color: #ece8e0;
|
color: rgba(var(--text-primary-rgb), 0.94);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition:
|
transition:
|
||||||
transform 160ms ease,
|
transform 160ms ease,
|
||||||
@@ -544,14 +591,14 @@
|
|||||||
#app-bottom-nav .nav-tab:hover,
|
#app-bottom-nav .nav-tab:hover,
|
||||||
#app-bottom-nav .nav-action:hover {
|
#app-bottom-nav .nav-action:hover {
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
color: #ffffff;
|
color: rgb(var(--text-primary-rgb));
|
||||||
background: rgba(255, 255, 255, 0.04) !important;
|
background: rgba(255, 255, 255, 0.04) !important;
|
||||||
}
|
}
|
||||||
#app-bottom-nav .nav-tab.is-active {
|
#app-bottom-nav .nav-tab.is-active {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: #fff;
|
color: rgb(var(--text-primary-rgb));
|
||||||
background: #2d2e2b !important;
|
background: rgb(var(--app-bg-rgb)) !important;
|
||||||
border-radius: 1.46rem;
|
border-radius: 1.46rem;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
@@ -563,7 +610,7 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 0 3px rgba(255, 255, 255, 0.08),
|
0 0 0 3px rgba(255, 255, 255, 0.08),
|
||||||
0 0 0 6px rgba(var(--accent-rgb), 0.26) !important;
|
0 0 0 6px rgba(var(--text-body-rgb), 0.26) !important;
|
||||||
}
|
}
|
||||||
@media (max-width: 380px) {
|
@media (max-width: 380px) {
|
||||||
#app-bottom-nav {
|
#app-bottom-nav {
|
||||||
@@ -614,12 +661,16 @@
|
|||||||
const savedTheme = localStorage.getItem('theme');
|
const savedTheme = localStorage.getItem('theme');
|
||||||
const useDarkTheme = savedTheme ? savedTheme === 'dark' : true;
|
const useDarkTheme = savedTheme ? savedTheme === 'dark' : true;
|
||||||
if (useDarkTheme) document.documentElement.classList.add('dark');
|
if (useDarkTheme) document.documentElement.classList.add('dark');
|
||||||
document.querySelector('meta[name="theme-color"]')?.setAttribute('content', useDarkTheme ? '#2d2e2b' : '#f3efe9');
|
const themeMeta = document.querySelector('meta[name="theme-color"]');
|
||||||
|
if (themeMeta) {
|
||||||
|
const appBgRgb = getComputedStyle(document.documentElement).getPropertyValue('--app-bg-rgb').trim();
|
||||||
|
if (appBgRgb) themeMeta.setAttribute('content', `rgb(${appBgRgb})`);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="app-container" class="relative flex h-dvh min-h-0 w-full flex-col overflow-hidden bg-white">
|
<div id="app-container" class="relative flex h-dvh min-h-0 w-full flex-col overflow-hidden bg-white">
|
||||||
<div class="flex h-full items-center justify-center" style="background:#2d2e2b !important;">
|
<div class="flex h-full items-center justify-center" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div class="text-[13px] font-medium" style="color:#b7ada1 !important;">Ładowanie...</div>
|
<div class="text-[13px] font-medium" style="color:rgb(var(--text-muted-rgb)) !important;">Ładowanie...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -665,11 +716,11 @@
|
|||||||
const appContainer = document.getElementById('app-container');
|
const appContainer = document.getElementById('app-container');
|
||||||
if (!appContainer) return;
|
if (!appContainer) return;
|
||||||
appContainer.innerHTML = `
|
appContainer.innerHTML = `
|
||||||
<div class="flex h-full items-center justify-center px-6 text-center" style="background:#2d2e2b !important;">
|
<div class="flex h-full items-center justify-center px-6 text-center" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div class="max-w-[18rem] rounded-[1.5rem] border px-5 py-6" style="background:#2f2f2d !important; border-color:#444442 !important;">
|
<div class="max-w-[18rem] rounded-[1.5rem] border px-5 py-6" style="background:rgb(var(--card-soft-rgb)) !important; border-color:rgb(var(--card-strong-rgb)) !important;">
|
||||||
<p class="text-sm font-semibold" style="color:#f2efe8 !important;">Aplikacja nie wystartowała</p>
|
<p class="text-sm font-semibold" style="color:rgb(var(--text-emphasis-rgb)) !important;">Aplikacja nie wystartowała</p>
|
||||||
<p class="mt-2 text-xs leading-relaxed" style="color:#b7ada1 !important;">${message}</p>
|
<p class="mt-2 text-xs leading-relaxed" style="color:rgb(var(--text-muted-rgb)) !important;">${message}</p>
|
||||||
<button type="button" onclick="window.location.reload()" class="mt-4 h-10 px-4 rounded-full border text-[12px] font-semibold" style="background:#23221e !important; border-color:#787876 !important; color:#f2efe8 !important;">Odśwież</button>
|
<button type="button" onclick="window.location.reload()" class="mt-4 h-10 px-4 rounded-full border text-[12px] font-semibold" style="background:rgb(var(--sunken-rgb)) !important; border-color:rgb(var(--border-input-rgb)) !important; color:rgb(var(--text-emphasis-rgb)) !important;">Odśwież</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
10
js/app.js
10
js/app.js
@@ -65,11 +65,11 @@ function renderAppBootError(message) {
|
|||||||
if (!appContainer) return;
|
if (!appContainer) return;
|
||||||
|
|
||||||
appContainer.innerHTML = `
|
appContainer.innerHTML = `
|
||||||
<div class="flex h-full items-center justify-center px-6 text-center" style="background:#2d2e2b !important;">
|
<div class="flex h-full items-center justify-center px-6 text-center" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div class="max-w-[18rem] rounded-[1.5rem] border px-5 py-6" style="background:#2f2f2d !important; border-color:#444442 !important;">
|
<div class="max-w-[18rem] rounded-[1.5rem] border px-5 py-6" style="background:rgb(var(--card-soft-rgb)) !important; border-color:rgb(var(--card-strong-rgb)) !important;">
|
||||||
<p class="text-sm font-semibold" style="color:#f2efe8 !important;">Nie udało się uruchomić aplikacji</p>
|
<p class="text-sm font-semibold" style="color:rgb(var(--text-emphasis-rgb)) !important;">Nie udało się uruchomić aplikacji</p>
|
||||||
<p class="mt-2 text-xs leading-relaxed" style="color:#b7ada1 !important;">${message}</p>
|
<p class="mt-2 text-xs leading-relaxed" style="color:rgb(var(--text-muted-rgb)) !important;">${message}</p>
|
||||||
<button type="button" onclick="window.location.reload()" class="mt-4 h-10 px-4 rounded-full border text-[12px] font-semibold" style="background:#23221e !important; border-color:#787876 !important; color:#f2efe8 !important;">Odśwież aplikację</button>
|
<button type="button" onclick="window.location.reload()" class="mt-4 h-10 px-4 rounded-full border text-[12px] font-semibold" style="background:rgb(var(--sunken-rgb)) !important; border-color:rgb(var(--border-input-rgb)) !important; color:rgb(var(--text-emphasis-rgb)) !important;">Odśwież aplikację</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ function setupThemeToggle() {
|
|||||||
syncThemeToggleButton(btn, isDark);
|
syncThemeToggleButton(btn, isDark);
|
||||||
|
|
||||||
const meta = document.querySelector('meta[name="theme-color"]');
|
const meta = document.querySelector('meta[name="theme-color"]');
|
||||||
if (meta) meta.setAttribute('content', isDark ? '#161513' : '#f3efe9');
|
if (meta) {
|
||||||
|
const varName = isDark ? '--sunken-deep-rgb' : '--app-bg-rgb';
|
||||||
|
const rgb = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
|
||||||
|
if (rgb) meta.setAttribute('content', `rgb(${rgb})`);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,11 +79,11 @@ function mediaHtml(image, icon, sizeClass = 'w-9 h-9', radiusClass = 'rounded-lg
|
|||||||
const fit = image.endsWith('.svg') ? 'object-contain' : 'object-cover';
|
const fit = image.endsWith('.svg') ? 'object-contain' : 'object-cover';
|
||||||
return `<img src="${esc(image)}" alt="" class="${sizeClass} ${radiusClass} ${fit} shrink-0">`;
|
return `<img src="${esc(image)}" alt="" class="${sizeClass} ${radiusClass} ${fit} shrink-0">`;
|
||||||
}
|
}
|
||||||
return `<div class="${sizeClass} ${radiusClass} flex items-center justify-center shrink-0" style="background:#2f2f2d;"><i class="fas ${icon} text-sm" style="color:#8f8b84;"></i></div>`;
|
return `<div class="${sizeClass} ${radiusClass} flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb));"><i class="fas ${icon} text-sm" style="color:rgb(var(--text-faint-rgb));"></i></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compactMetaText(text, tone = 'default') {
|
function compactMetaText(text, tone = 'default') {
|
||||||
const color = tone === 'success' ? '#6ee7b7' : tone === 'muted' ? '#9b978f' : '#d7d2c8';
|
const color = tone === 'success' ? 'rgb(var(--success-rgb))' : tone === 'muted' ? 'rgb(var(--text-dim-rgb))' : 'rgb(var(--text-body-soft-rgb))';
|
||||||
return `<span class="text-[10px] font-medium" style="color:${color};">${esc(text)}</span>`;
|
return `<span class="text-[10px] font-medium" style="color:${color};">${esc(text)}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ export function getIngredientCardHTML({
|
|||||||
overlayClass = 'fixed inset-0 z-[70] hidden opacity-0 transition-opacity duration-200 flex items-center justify-center p-5',
|
overlayClass = 'fixed inset-0 z-[70] hidden opacity-0 transition-opacity duration-200 flex items-center justify-center p-5',
|
||||||
overlayStyle = 'pointer-events:none; background:rgba(0,0,0,0.5);',
|
overlayStyle = 'pointer-events:none; background:rgba(0,0,0,0.5);',
|
||||||
cardClass = 'relative w-full max-w-xs rounded-2xl shadow-2xl overflow-hidden',
|
cardClass = 'relative w-full max-w-xs rounded-2xl shadow-2xl overflow-hidden',
|
||||||
cardStyle = 'background:#2d2e2b; pointer-events:auto; max-height:85vh; overflow-y:auto; transform:translateY(0.75rem); opacity:0; transition:transform 220ms ease, opacity 220ms ease;',
|
cardStyle = 'background:rgb(var(--app-bg-rgb)); pointer-events:auto; max-height:85vh; overflow-y:auto; transform:translateY(0.75rem); opacity:0; transition:transform 220ms ease, opacity 220ms ease;',
|
||||||
} = {}) {
|
} = {}) {
|
||||||
if (!idBase) throw new Error('getIngredientCardHTML requires idBase');
|
if (!idBase) throw new Error('getIngredientCardHTML requires idBase');
|
||||||
return `
|
return `
|
||||||
@@ -162,24 +162,24 @@ export function getIngredientCardHTML({
|
|||||||
<div id="${idBase}" class="${cardClass}" style="${cardStyle}">
|
<div id="${idBase}" class="${cardClass}" style="${cardStyle}">
|
||||||
<div class="relative px-4 pt-4 pb-2">
|
<div class="relative px-4 pt-4 pb-2">
|
||||||
<div class="flex items-start gap-3 pr-10">
|
<div class="flex items-start gap-3 pr-10">
|
||||||
<div id="${idBase}-hero" class="relative w-20 h-20 rounded-2xl flex items-center justify-center shrink-0 overflow-hidden" style="background:#393937;">
|
<div id="${idBase}-hero" class="relative w-20 h-20 rounded-2xl flex items-center justify-center shrink-0 overflow-hidden" style="background:rgb(var(--card-rgb));">
|
||||||
<img id="${idBase}-img" class="w-full h-full hidden" alt="" />
|
<img id="${idBase}-img" class="w-full h-full hidden" alt="" />
|
||||||
<div id="${idBase}-fallback" class="absolute inset-0 flex items-center justify-center">
|
<div id="${idBase}-fallback" class="absolute inset-0 flex items-center justify-center">
|
||||||
<i id="${idBase}-fallback-icon" class="fas fa-box-open text-2xl" style="color:#6d6c67;"></i>
|
<i id="${idBase}-fallback-icon" class="fas fa-box-open text-2xl" style="color:rgb(var(--text-subdued-rgb));"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1 min-w-0 pt-0.5">
|
<div class="flex-1 min-w-0 pt-0.5">
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5">
|
||||||
<button type="button" id="${idBase}-back" class="hidden w-5 h-5 rounded-full items-center justify-center shrink-0" style="background:#393937; color:#ddd6ca;" aria-label="Wróć do składnika">
|
<button type="button" id="${idBase}-back" class="hidden w-5 h-5 rounded-full items-center justify-center shrink-0" style="background:rgb(var(--card-rgb)); color:rgb(var(--text-body-rgb));" aria-label="Wróć do składnika">
|
||||||
<i class="fas fa-chevron-left text-[9px]"></i>
|
<i class="fas fa-chevron-left text-[9px]"></i>
|
||||||
</button>
|
</button>
|
||||||
<p id="${idBase}-category" class="text-[10px] font-semibold uppercase tracking-wider truncate" style="color:#6ee7b7;"></p>
|
<p id="${idBase}-category" class="text-[10px] font-semibold uppercase tracking-wider truncate" style="color:rgb(var(--success-rgb));"></p>
|
||||||
</div>
|
</div>
|
||||||
<h3 id="${idBase}-name" class="text-[15px] font-bold leading-snug mt-0.5" style="color:#ddd6ca;"></h3>
|
<h3 id="${idBase}-name" class="text-[15px] font-bold leading-snug mt-0.5" style="color:rgb(var(--text-body-rgb));"></h3>
|
||||||
<p id="${idBase}-subtitle" class="text-[11px] mt-0.5 hidden" style="color:#9b978f;"></p>
|
<p id="${idBase}-subtitle" class="text-[11px] mt-0.5 hidden" style="color:rgb(var(--text-dim-rgb));"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" id="${idBase}-close" class="absolute top-3 right-3 w-8 h-8 rounded-full flex items-center justify-center" style="background:#393937; color:#ddd6ca;" aria-label="Zamknij">
|
<button type="button" id="${idBase}-close" class="absolute top-3 right-3 w-8 h-8 rounded-full flex items-center justify-center" style="background:rgb(var(--card-rgb)); color:rgb(var(--text-body-rgb));" aria-label="Zamknij">
|
||||||
<i class="fas fa-times text-sm"></i>
|
<i class="fas fa-times text-sm"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -319,24 +319,24 @@ export function createIngredientCardController({ idBase, defaultSourceNote = 'Ze
|
|||||||
const nutritionMeta = hint ? `${unitScope} • ${hint}` : unitScope;
|
const nutritionMeta = hint ? `${unitScope} • ${hint}` : unitScope;
|
||||||
|
|
||||||
wrap.innerHTML = `
|
wrap.innerHTML = `
|
||||||
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:#9b978f;">Wartości odżywcze</p>
|
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:rgb(var(--text-dim-rgb));">Wartości odżywcze</p>
|
||||||
<p class="text-[10px] mb-1.5" style="color:#9b978f;">${esc(nutritionMeta)}</p>
|
<p class="text-[10px] mb-1.5" style="color:rgb(var(--text-dim-rgb));">${esc(nutritionMeta)}</p>
|
||||||
<div class="grid grid-cols-4 gap-1.5">
|
<div class="grid grid-cols-4 gap-1.5">
|
||||||
<div class="rounded-xl px-2 py-1.5 text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-1.5 text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold tabular-nums leading-tight" style="color:#ddd6ca;">${nutrition.kcal}</p>
|
<p class="text-[15px] font-bold tabular-nums leading-tight" style="color:rgb(var(--text-body-rgb));">${nutrition.kcal}</p>
|
||||||
<p class="text-[9px] font-medium" style="color:#9b978f;">kcal</p>
|
<p class="text-[9px] font-medium" style="color:rgb(var(--text-dim-rgb));">kcal</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-1.5 text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-1.5 text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">${formatQty(nutrition.protein)}g</p>
|
<p class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">${formatQty(nutrition.protein)}g</p>
|
||||||
<p class="text-[9px] font-medium" style="color:#9b978f;">białko</p>
|
<p class="text-[9px] font-medium" style="color:rgb(var(--text-dim-rgb));">białko</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-1.5 text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-1.5 text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">${formatQty(nutrition.fat)}g</p>
|
<p class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">${formatQty(nutrition.fat)}g</p>
|
||||||
<p class="text-[9px] font-medium" style="color:#9b978f;">tłuszcz</p>
|
<p class="text-[9px] font-medium" style="color:rgb(var(--text-dim-rgb));">tłuszcz</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-1.5 text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-1.5 text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">${formatQty(nutrition.carbs)}g</p>
|
<p class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">${formatQty(nutrition.carbs)}g</p>
|
||||||
<p class="text-[9px] font-medium" style="color:#9b978f;">węgl.</p>
|
<p class="text-[9px] font-medium" style="color:rgb(var(--text-dim-rgb));">węgl.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
@@ -364,35 +364,35 @@ export function createIngredientCardController({ idBase, defaultSourceNote = 'Ze
|
|||||||
const actionLabel = state.stockEditorOpen ? 'Anuluj' : 'Zmień';
|
const actionLabel = state.stockEditorOpen ? 'Anuluj' : 'Zmień';
|
||||||
|
|
||||||
wrap.innerHTML = `
|
wrap.innerHTML = `
|
||||||
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:#9b978f;">Zapas</p>
|
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:rgb(var(--text-dim-rgb));">Zapas</p>
|
||||||
<div class="rounded-2xl border px-3 py-3" style="background:#393937; border-color:#444442;">
|
<div class="rounded-2xl border px-3 py-3" style="background:rgb(var(--card-rgb)); border-color:rgb(var(--card-strong-rgb));">
|
||||||
<div class="flex items-start justify-between gap-3">
|
<div class="flex items-start justify-between gap-3">
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="text-[16px] font-bold tabular-nums" style="color:#6ee7b7;">${esc(stockValueLabel)}</p>
|
<p class="text-[16px] font-bold tabular-nums" style="color:rgb(var(--success-rgb));">${esc(stockValueLabel)}</p>
|
||||||
${stockSubLabel ? `<p class="text-[11px] mt-1" style="color:#9b978f;">${esc(stockSubLabel)}</p>` : ''}
|
${stockSubLabel ? `<p class="text-[11px] mt-1" style="color:rgb(var(--text-dim-rgb));">${esc(stockSubLabel)}</p>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="ingredient-card-stock-toggle inline-flex items-center rounded-full px-2.5 py-1 text-[10px] font-semibold shrink-0" style="background:${state.stockEditorOpen ? '#23221e' : '#2f2f2d'}; color:${state.stockEditorOpen ? '#f2efe8' : '#d7d2c8'};">
|
<button type="button" class="ingredient-card-stock-toggle inline-flex items-center rounded-full px-2.5 py-1 text-[10px] font-semibold shrink-0" style="background:${state.stockEditorOpen ? 'rgb(var(--sunken-rgb))' : 'rgb(var(--card-soft-rgb))'}; color:${state.stockEditorOpen ? 'rgb(var(--text-emphasis-rgb))' : 'rgb(var(--text-body-soft-rgb))'};">
|
||||||
${esc(actionLabel)}
|
${esc(actionLabel)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
${state.stockEditorOpen ? `
|
${state.stockEditorOpen ? `
|
||||||
<div class="mt-3 pt-3 border-t" style="border-color:#444442;">
|
<div class="mt-3 pt-3 border-t" style="border-color:rgb(var(--card-strong-rgb));">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button type="button" class="ingredient-card-stock-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:#2f2f2d; color:#d7d2c8;" data-dir="-1" aria-label="Zmniejsz szkic zapasu">
|
<button type="button" class="ingredient-card-stock-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb)); color:rgb(var(--text-body-soft-rgb));" data-dir="-1" aria-label="Zmniejsz szkic zapasu">
|
||||||
<i class="fas fa-minus text-xs"></i>
|
<i class="fas fa-minus text-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
<label class="flex-1 rounded-xl px-3 py-2 flex items-center justify-center gap-2" style="background:#2f2f2d;">
|
<label class="flex-1 rounded-xl px-3 py-2 flex items-center justify-center gap-2" style="background:rgb(var(--card-soft-rgb));">
|
||||||
<input type="number" min="0" step="${usesPackStep ? '1' : step}" value="${draftInputValue}" class="ingredient-card-stock-input w-20 bg-transparent text-center text-[14px] font-semibold tabular-nums outline-none appearance-none" style="color:#ddd6ca; background:transparent !important; border:none !important; box-shadow:none !important; -webkit-appearance:none; -moz-appearance:textfield;">
|
<input type="number" min="0" step="${usesPackStep ? '1' : step}" value="${draftInputValue}" class="ingredient-card-stock-input w-20 bg-transparent text-center text-[14px] font-semibold tabular-nums outline-none appearance-none" style="color:rgb(var(--text-body-rgb)); background:transparent !important; border:none !important; box-shadow:none !important; -webkit-appearance:none; -moz-appearance:textfield;">
|
||||||
<span class="text-[12px] font-medium shrink-0" style="color:#9b978f;">${esc(draftInputUnit)}</span>
|
<span class="text-[12px] font-medium shrink-0" style="color:rgb(var(--text-dim-rgb));">${esc(draftInputUnit)}</span>
|
||||||
</label>
|
</label>
|
||||||
<button type="button" class="ingredient-card-stock-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:#2f2f2d; color:#d7d2c8;" data-dir="1" aria-label="Zwiększ szkic zapasu">
|
<button type="button" class="ingredient-card-stock-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb)); color:rgb(var(--text-body-soft-rgb));" data-dir="1" aria-label="Zwiększ szkic zapasu">
|
||||||
<i class="fas fa-plus text-xs"></i>
|
<i class="fas fa-plus text-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
${usesPackStep ? `<p class="text-[10px] mt-2 text-right" style="color:#9b978f;">${esc(formatQtyWithUnit(draftQty, def.pantryUnit))}</p>` : ''}
|
${usesPackStep ? `<p class="text-[10px] mt-2 text-right" style="color:rgb(var(--text-dim-rgb));">${esc(formatQtyWithUnit(draftQty, def.pantryUnit))}</p>` : ''}
|
||||||
<div class="flex items-center justify-between gap-3 mt-3">
|
<div class="flex items-center justify-between gap-3 mt-3">
|
||||||
<button type="button" class="ingredient-card-stock-clear text-[11px] font-semibold" style="color:#9b978f;">Wyzeruj</button>
|
<button type="button" class="ingredient-card-stock-clear text-[11px] font-semibold" style="color:rgb(var(--text-dim-rgb));">Wyzeruj</button>
|
||||||
<button type="button" class="ingredient-card-stock-save inline-flex items-center rounded-full px-3 py-1.5 text-[11px] font-semibold" style="background:#ddd6ca; color:#2d2e2b;">Zapisz</button>
|
<button type="button" class="ingredient-card-stock-save inline-flex items-center rounded-full px-3 py-1.5 text-[11px] font-semibold" style="background:rgb(var(--text-body-rgb)); color:rgb(var(--app-bg-rgb));">Zapisz</button>
|
||||||
</div>
|
</div>
|
||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -473,37 +473,37 @@ export function createIngredientCardController({ idBase, defaultSourceNote = 'Ze
|
|||||||
const actionLabel = state.shopEditorOpen ? 'Anuluj' : (hasShoppingItem ? 'Zmień' : 'Dodaj');
|
const actionLabel = state.shopEditorOpen ? 'Anuluj' : (hasShoppingItem ? 'Zmień' : 'Dodaj');
|
||||||
|
|
||||||
wrap.innerHTML = `
|
wrap.innerHTML = `
|
||||||
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:#9b978f;">Lista zakupów</p>
|
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:rgb(var(--text-dim-rgb));">Lista zakupów</p>
|
||||||
<div class="rounded-2xl border px-3 py-3" style="background:#393937; border-color:#444442;">
|
<div class="rounded-2xl border px-3 py-3" style="background:rgb(var(--card-rgb)); border-color:rgb(var(--card-strong-rgb));">
|
||||||
<div class="flex items-start justify-between gap-3">
|
<div class="flex items-start justify-between gap-3">
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="text-[16px] font-bold tabular-nums" style="color:${hasShoppingItem ? '#ddd6ca' : '#9b978f'};">${esc(shopValueLabel)}</p>
|
<p class="text-[16px] font-bold tabular-nums" style="color:${hasShoppingItem ? 'rgb(var(--text-body-rgb))' : 'rgb(var(--text-dim-rgb))'};">${esc(shopValueLabel)}</p>
|
||||||
${shopSubLabel ? `<p class="text-[11px] mt-1" style="color:#9b978f;">${esc(shopSubLabel)}</p>` : ''}
|
${shopSubLabel ? `<p class="text-[11px] mt-1" style="color:rgb(var(--text-dim-rgb));">${esc(shopSubLabel)}</p>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="ingredient-card-shop-toggle inline-flex items-center rounded-full px-2.5 py-1 text-[10px] font-semibold shrink-0" style="background:${state.shopEditorOpen ? '#23221e' : '#2f2f2d'}; color:${state.shopEditorOpen ? '#f2efe8' : '#d7d2c8'};">
|
<button type="button" class="ingredient-card-shop-toggle inline-flex items-center rounded-full px-2.5 py-1 text-[10px] font-semibold shrink-0" style="background:${state.shopEditorOpen ? 'rgb(var(--sunken-rgb))' : 'rgb(var(--card-soft-rgb))'}; color:${state.shopEditorOpen ? 'rgb(var(--text-emphasis-rgb))' : 'rgb(var(--text-body-soft-rgb))'};">
|
||||||
${esc(actionLabel)}
|
${esc(actionLabel)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
${state.shopEditorOpen ? `
|
${state.shopEditorOpen ? `
|
||||||
<div class="mt-3 pt-3 border-t" style="border-color:#444442;">
|
<div class="mt-3 pt-3 border-t" style="border-color:rgb(var(--card-strong-rgb));">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button type="button" class="ingredient-card-shop-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:#2f2f2d; color:#d7d2c8;" data-dir="-1" aria-label="Zmniejsz ilość na liście">
|
<button type="button" class="ingredient-card-shop-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb)); color:rgb(var(--text-body-soft-rgb));" data-dir="-1" aria-label="Zmniejsz ilość na liście">
|
||||||
<i class="fas fa-minus text-xs"></i>
|
<i class="fas fa-minus text-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
<label class="flex-1 rounded-xl px-3 py-2 flex items-center justify-center gap-2" style="background:#2f2f2d;">
|
<label class="flex-1 rounded-xl px-3 py-2 flex items-center justify-center gap-2" style="background:rgb(var(--card-soft-rgb));">
|
||||||
<input type="number" min="0" step="${usesPackStep ? '1' : defaultAmount}" value="${shopInputValue}" class="ingredient-card-shop-input w-20 bg-transparent text-center text-[14px] font-semibold tabular-nums outline-none appearance-none" style="color:#ddd6ca; background:transparent !important; border:none !important; box-shadow:none !important; -webkit-appearance:none; -moz-appearance:textfield;">
|
<input type="number" min="0" step="${usesPackStep ? '1' : defaultAmount}" value="${shopInputValue}" class="ingredient-card-shop-input w-20 bg-transparent text-center text-[14px] font-semibold tabular-nums outline-none appearance-none" style="color:rgb(var(--text-body-rgb)); background:transparent !important; border:none !important; box-shadow:none !important; -webkit-appearance:none; -moz-appearance:textfield;">
|
||||||
<span class="text-[12px] font-medium shrink-0" style="color:#9b978f;">${esc(shopInputUnit)}</span>
|
<span class="text-[12px] font-medium shrink-0" style="color:rgb(var(--text-dim-rgb));">${esc(shopInputUnit)}</span>
|
||||||
</label>
|
</label>
|
||||||
<button type="button" class="ingredient-card-shop-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:#2f2f2d; color:#d7d2c8;" data-dir="1" aria-label="Zwiększ ilość na liście">
|
<button type="button" class="ingredient-card-shop-step w-9 h-9 rounded-xl flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb)); color:rgb(var(--text-body-soft-rgb));" data-dir="1" aria-label="Zwiększ ilość na liście">
|
||||||
<i class="fas fa-plus text-xs"></i>
|
<i class="fas fa-plus text-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
${usesPackStep ? `<p class="text-[10px] mt-2 text-right" style="color:#9b978f;">${esc(formatQtyWithUnit(draftQty, def.pantryUnit))}</p>` : ''}
|
${usesPackStep ? `<p class="text-[10px] mt-2 text-right" style="color:rgb(var(--text-dim-rgb));">${esc(formatQtyWithUnit(draftQty, def.pantryUnit))}</p>` : ''}
|
||||||
<div class="flex items-center justify-between gap-3 mt-3">
|
<div class="flex items-center justify-between gap-3 mt-3">
|
||||||
${hasShoppingItem
|
${hasShoppingItem
|
||||||
? '<button type="button" class="ingredient-card-shop-remove text-[11px] font-semibold" style="color:#9b978f;">Usuń z listy</button>'
|
? '<button type="button" class="ingredient-card-shop-remove text-[11px] font-semibold" style="color:rgb(var(--text-dim-rgb));">Usuń z listy</button>'
|
||||||
: '<span></span>'}
|
: '<span></span>'}
|
||||||
<button type="button" class="ingredient-card-shop-save inline-flex items-center rounded-full px-3 py-1.5 text-[11px] font-semibold" style="background:#ddd6ca; color:#2d2e2b;">Zapisz</button>
|
<button type="button" class="ingredient-card-shop-save inline-flex items-center rounded-full px-3 py-1.5 text-[11px] font-semibold" style="background:rgb(var(--text-body-rgb)); color:rgb(var(--app-bg-rgb));">Zapisz</button>
|
||||||
</div>
|
</div>
|
||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -611,24 +611,24 @@ export function createIngredientCardController({ idBase, defaultSourceNote = 'Ze
|
|||||||
const shoppingAmount = shoppingItem?.amount || 0;
|
const shoppingAmount = shoppingItem?.amount || 0;
|
||||||
|
|
||||||
const pantryLabel = pantryQty > 0 ? `${formatQty(pantryQty)} ${unit}` : '—';
|
const pantryLabel = pantryQty > 0 ? `${formatQty(pantryQty)} ${unit}` : '—';
|
||||||
const pantryColor = pantryQty > 0 ? '#ddd6ca' : '#6d6c67';
|
const pantryColor = pantryQty > 0 ? 'rgb(var(--text-body-rgb))' : 'rgb(var(--text-subdued-rgb))';
|
||||||
const shoppingLabel = shoppingAmount > 0 ? `${formatQty(shoppingAmount)} ${unit}` : '';
|
const shoppingLabel = shoppingAmount > 0 ? `${formatQty(shoppingAmount)} ${unit}` : '';
|
||||||
|
|
||||||
return `<button type="button" class="ingredient-card-product-row w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-left transition-colors active:scale-[0.99]" style="background:#393937; border:1px solid transparent;" data-product-id="${esc(productId)}">
|
return `<button type="button" class="ingredient-card-product-row w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-left transition-colors active:scale-[0.99]" style="background:rgb(var(--card-rgb)); border:1px solid transparent;" data-product-id="${esc(productId)}">
|
||||||
${mediaHtml(product.image || def.image, icon)}
|
${mediaHtml(product.image || def.image, icon)}
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<span class="text-[13px] font-semibold truncate block" style="color:#ddd6ca;">${esc(product.name)}</span>
|
<span class="text-[13px] font-semibold truncate block" style="color:rgb(var(--text-body-rgb));">${esc(product.name)}</span>
|
||||||
${product.packLabel ? `<span class="text-[10px] block mt-0.5" style="color:#9b978f;">${esc(product.packLabel)}</span>` : ''}
|
${product.packLabel ? `<span class="text-[10px] block mt-0.5" style="color:rgb(var(--text-dim-rgb));">${esc(product.packLabel)}</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col items-end gap-0.5 shrink-0 tabular-nums">
|
<div class="flex flex-col items-end gap-0.5 shrink-0 tabular-nums">
|
||||||
<span class="text-[11px] font-semibold inline-flex items-center gap-1" style="color:${pantryColor};">
|
<span class="text-[11px] font-semibold inline-flex items-center gap-1" style="color:${pantryColor};">
|
||||||
<i class="fas fa-box text-[9px]" style="color:#8f8b84;"></i>${esc(pantryLabel)}
|
<i class="fas fa-box text-[9px]" style="color:rgb(var(--text-faint-rgb));"></i>${esc(pantryLabel)}
|
||||||
</span>
|
</span>
|
||||||
${shoppingLabel ? `<span class="text-[11px] font-semibold inline-flex items-center gap-1" style="color:#ddd6ca;">
|
${shoppingLabel ? `<span class="text-[11px] font-semibold inline-flex items-center gap-1" style="color:rgb(var(--text-body-rgb));">
|
||||||
<i class="fas fa-cart-shopping text-[9px]" style="color:#8f8b84;"></i>${esc(shoppingLabel)}
|
<i class="fas fa-cart-shopping text-[9px]" style="color:rgb(var(--text-faint-rgb));"></i>${esc(shoppingLabel)}
|
||||||
</span>` : ''}
|
</span>` : ''}
|
||||||
</div>
|
</div>
|
||||||
<i class="fas fa-chevron-right text-[10px] shrink-0" style="color:#8f8b84;"></i>
|
<i class="fas fa-chevron-right text-[10px] shrink-0" style="color:rgb(var(--text-faint-rgb));"></i>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,7 +649,7 @@ export function createIngredientCardController({ idBase, defaultSourceNote = 'Ze
|
|||||||
const kitchenItems = (kitchen && kitchen.type === 'kitchen') ? kitchen.items : [];
|
const kitchenItems = (kitchen && kitchen.type === 'kitchen') ? kitchen.items : [];
|
||||||
|
|
||||||
wrap.innerHTML = `
|
wrap.innerHTML = `
|
||||||
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:#9b978f;">Produkty</p>
|
<p class="text-[9px] font-semibold uppercase tracking-wide mb-1.5" style="color:rgb(var(--text-dim-rgb));">Produkty</p>
|
||||||
<div class="space-y-1.5">
|
<div class="space-y-1.5">
|
||||||
${products.map((product) => productRowHtml(state.ingredientId, product.id, pantry, kitchenItems)).join('')}
|
${products.map((product) => productRowHtml(state.ingredientId, product.id, pantry, kitchenItems)).join('')}
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const CALENDAR_MONTHS_SHORT = [
|
|||||||
|
|
||||||
export const CALENDAR_WEEKDAYS_SHORT = ['pn', 'wt', 'śr', 'cz', 'pt', 'so', 'nd'];
|
export const CALENDAR_WEEKDAYS_SHORT = ['pn', 'wt', 'śr', 'cz', 'pt', 'so', 'nd'];
|
||||||
export const CALENDAR_DAY_ATTR = 'data-calendar-day';
|
export const CALENDAR_DAY_ATTR = 'data-calendar-day';
|
||||||
export const CALENDAR_HANDLE_CLASS = 'block h-1 w-10 rounded-full bg-[#6d6c67]/75';
|
export const CALENDAR_HANDLE_CLASS = 'block h-1 w-10 rounded-full bg-[rgb(var(--text-subdued-rgb))]/75';
|
||||||
|
|
||||||
function getCalendarDayHTML(day, meta, dayState, dayAttr, theme = {}) {
|
function getCalendarDayHTML(day, meta, dayState, dayAttr, theme = {}) {
|
||||||
const { mode, selectedDate } = meta;
|
const { mode, selectedDate } = meta;
|
||||||
@@ -27,9 +27,9 @@ function getCalendarDayHTML(day, meta, dayState, dayAttr, theme = {}) {
|
|||||||
const showIndicator = !!dayState.showIndicator;
|
const showIndicator = !!dayState.showIndicator;
|
||||||
const isDisabled = !!dayState.disabled;
|
const isDisabled = !!dayState.disabled;
|
||||||
const isDimmed = !!dayState.dimmed && !isSelected;
|
const isDimmed = !!dayState.dimmed && !isSelected;
|
||||||
const defaultBg = '#2f2f2d';
|
const defaultBg = 'rgb(var(--card-soft-rgb))';
|
||||||
const defaultBorder = '#444442';
|
const defaultBorder = 'rgb(var(--card-strong-rgb))';
|
||||||
const defaultText = '#d7d2c8';
|
const defaultText = 'rgb(var(--text-body-soft-rgb))';
|
||||||
|
|
||||||
let bg;
|
let bg;
|
||||||
let borderColor;
|
let borderColor;
|
||||||
@@ -37,12 +37,12 @@ function getCalendarDayHTML(day, meta, dayState, dayAttr, theme = {}) {
|
|||||||
let borderClass = 'border';
|
let borderClass = 'border';
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
bg = theme.selectedBg || '#23221e';
|
bg = theme.selectedBg || 'rgb(var(--sunken-rgb))';
|
||||||
borderColor = theme.selectedBorder || '#787876';
|
borderColor = theme.selectedBorder || 'rgb(var(--border-input-rgb))';
|
||||||
text = theme.selectedText || '#f2efe8';
|
text = theme.selectedText || 'rgb(var(--text-emphasis-rgb))';
|
||||||
} else if (isDimmed) {
|
} else if (isDimmed) {
|
||||||
bg = theme.dimmedBg ?? theme.bg ?? defaultBg;
|
bg = theme.dimmedBg ?? theme.bg ?? defaultBg;
|
||||||
text = theme.dimText || '#7d7a74';
|
text = theme.dimText || 'rgb(var(--text-faint-rgb))';
|
||||||
borderClass = 'border-0';
|
borderClass = 'border-0';
|
||||||
} else {
|
} else {
|
||||||
bg = theme.bg || defaultBg;
|
bg = theme.bg || defaultBg;
|
||||||
@@ -50,7 +50,7 @@ function getCalendarDayHTML(day, meta, dayState, dayAttr, theme = {}) {
|
|||||||
text = theme.text || defaultText;
|
text = theme.text || defaultText;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dot = isSelected ? (theme.selectedDot || '#f2efe8') : (theme.dot || '#a59f92');
|
const dot = isSelected ? (theme.selectedDot || 'rgb(var(--text-emphasis-rgb))') : (theme.dot || 'rgb(var(--text-faint-rgb))');
|
||||||
const opacity = isDimmed ? String(theme.dimOpacity ?? 0.72) : '1';
|
const opacity = isDimmed ? String(theme.dimOpacity ?? 0.72) : '1';
|
||||||
const borderStyle = isDimmed ? 'border:none;' : `border-color:${borderColor};`;
|
const borderStyle = isDimmed ? 'border:none;' : `border-color:${borderColor};`;
|
||||||
const outerClass = `${mode === 'month' ? 'mx-auto ' : ''}flex h-[2.05rem] w-full min-w-0 max-w-full items-center justify-center rounded-full ${borderClass} text-xs font-medium transition-colors leading-tight overflow-hidden`;
|
const outerClass = `${mode === 'month' ? 'mx-auto ' : ''}flex h-[2.05rem] w-full min-w-0 max-w-full items-center justify-center rounded-full ${borderClass} text-xs font-medium transition-colors leading-tight overflow-hidden`;
|
||||||
@@ -118,10 +118,10 @@ export function createCalendarTopbarHTML({
|
|||||||
todayId,
|
todayId,
|
||||||
nextId,
|
nextId,
|
||||||
wrapperClass = 'px-4 pt-4 pb-3 flex items-center justify-end',
|
wrapperClass = 'px-4 pt-4 pb-3 flex items-center justify-end',
|
||||||
controlsStyle = 'background:#2f2f2d;border-color:#444442;',
|
controlsStyle = 'background:rgb(var(--card-soft-rgb));border-color:rgb(var(--card-strong-rgb));',
|
||||||
navButtonClass = 'shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[#d7d2c8] transition-colors',
|
navButtonClass = 'shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[rgb(var(--text-body-soft-rgb))] transition-colors',
|
||||||
todayButtonActiveClass = 'h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center rounded-full bg-transparent px-1.5 text-[10px] font-semibold leading-none tabular-nums text-[#d7d2c8] active:bg-transparent whitespace-nowrap',
|
todayButtonActiveClass = 'h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center rounded-full bg-transparent px-1.5 text-[10px] font-semibold leading-none tabular-nums text-[rgb(var(--text-body-soft-rgb))] active:bg-transparent whitespace-nowrap',
|
||||||
todayButtonDimClass = 'h-full shrink-0 inline-flex items-center justify-center rounded-full px-2 text-[10px] font-semibold leading-none text-[#7d7a74] cursor-default',
|
todayButtonDimClass = 'h-full shrink-0 inline-flex items-center justify-center rounded-full px-2 text-[10px] font-semibold leading-none text-[rgb(var(--text-faint-rgb))] cursor-default',
|
||||||
}) {
|
}) {
|
||||||
return `
|
return `
|
||||||
<div class="${wrapperClass}">
|
<div class="${wrapperClass}">
|
||||||
@@ -168,7 +168,7 @@ export function syncCalendarTodayButton(buttonEl, isOnToday, selectedDate, optio
|
|||||||
ariaLabelCurrent = 'Widok jest ustawiony na bieżący okres',
|
ariaLabelCurrent = 'Widok jest ustawiony na bieżący okres',
|
||||||
} = options;
|
} = options;
|
||||||
const active = buttonEl.dataset.calActiveClass
|
const active = buttonEl.dataset.calActiveClass
|
||||||
|| 'h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center rounded-full bg-transparent px-1.5 text-[10px] font-semibold leading-none tabular-nums text-[#d7d2c8] active:bg-transparent whitespace-nowrap';
|
|| 'h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center rounded-full bg-transparent px-1.5 text-[10px] font-semibold leading-none tabular-nums text-[rgb(var(--text-body-soft-rgb))] active:bg-transparent whitespace-nowrap';
|
||||||
if (selectedDate != null) {
|
if (selectedDate != null) {
|
||||||
buttonEl.textContent = formatCalendarSelectedDate(selectedDate);
|
buttonEl.textContent = formatCalendarSelectedDate(selectedDate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,21 +37,21 @@ const slotLabel = Object.fromEntries(MEAL_SLOTS.map((s) => [s.id, s.label]));
|
|||||||
export function getMealPlanEditorHTML() {
|
export function getMealPlanEditorHTML() {
|
||||||
return `
|
return `
|
||||||
<div id="mpe-overlay" class="absolute inset-0 z-[55] bg-black/45 hidden flex items-end" style="pointer-events:none">
|
<div id="mpe-overlay" class="absolute inset-0 z-[55] bg-black/45 hidden flex items-end" style="pointer-events:none">
|
||||||
<div id="mpe-sheet" class="w-full bg-[#2d2e2b] rounded-t-3xl shadow-lg flex flex-col overflow-hidden" style="pointer-events:auto; background:#2d2e2b !important; background-image:none !important; backdrop-filter:none !important; height:100dvh; max-height:100dvh; transform:translateY(100%); transition:transform 300ms cubic-bezier(0.32,0.72,0,1)">
|
<div id="mpe-sheet" class="w-full bg-[rgb(var(--app-bg-rgb))] rounded-t-3xl shadow-lg flex flex-col overflow-hidden" style="pointer-events:auto; background:rgb(var(--app-bg-rgb)) !important; background-image:none !important; backdrop-filter:none !important; height:100dvh; max-height:100dvh; transform:translateY(100%); transition:transform 300ms cubic-bezier(0.32,0.72,0,1)">
|
||||||
<div class="shrink-0 px-5 pt-3 pb-2.5 border-b border-gray-100 bg-[#2d2e2b]" style="background:#2d2e2b !important; background-image:none !important;">
|
<div class="shrink-0 px-5 pt-3 pb-2.5 border-b border-gray-100 bg-[rgb(var(--app-bg-rgb))]" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important;">
|
||||||
<div class="w-10 h-1 bg-gray-200 rounded-full mx-auto mb-3"></div>
|
<div class="w-10 h-1 bg-gray-200 rounded-full mx-auto mb-3"></div>
|
||||||
<div class="flex items-start justify-between gap-3">
|
<div class="flex items-start justify-between gap-3">
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<h2 id="mpe-title" class="text-[15px] font-bold text-gray-900 leading-tight"></h2>
|
<h2 id="mpe-title" class="text-[15px] font-bold text-gray-900 leading-tight"></h2>
|
||||||
<p id="mpe-subtitle" class="text-[11px] text-gray-500 mt-0.5 truncate"></p>
|
<p id="mpe-subtitle" class="text-[11px] text-gray-500 mt-0.5 truncate"></p>
|
||||||
</div>
|
</div>
|
||||||
<button id="mpe-confirm-btn" type="button" aria-label="Dodaj do planu" class="shrink-0 mt-0.5 border h-8 px-3 rounded-full font-semibold text-[12px] transition-colors inline-flex items-center justify-center gap-1.5" style="background:#dcd6cb !important; color:#2d2e2b !important; background-image:none !important; border-color:#dcd6cb !important; box-shadow:0 2px 10px rgba(0,0,0,0.18);">
|
<button id="mpe-confirm-btn" type="button" aria-label="Dodaj do planu" class="shrink-0 mt-0.5 border h-8 px-3 rounded-full font-semibold text-[12px] transition-colors inline-flex items-center justify-center gap-1.5" style="background:rgb(var(--text-body-rgb)) !important; color:rgb(var(--app-bg-rgb)) !important; background-image:none !important; border-color:rgb(var(--text-body-rgb)) !important; box-shadow:0 2px 10px rgba(0,0,0,0.18);">
|
||||||
<i id="mpe-confirm-icon" class="fas fa-plus text-[10px]" aria-hidden="true"></i>
|
<i id="mpe-confirm-icon" class="fas fa-plus text-[10px]" aria-hidden="true"></i>
|
||||||
<span id="mpe-confirm-label">Dodaj</span>
|
<span id="mpe-confirm-label">Dodaj</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="mpe-cal-wrap" class="hidden relative z-[1] shrink-0 px-5 pt-3 pb-3 bg-[#2d2e2b]" style="background:#2d2e2b !important; background-image:none !important;">
|
<div id="mpe-cal-wrap" class="hidden relative z-[1] shrink-0 px-5 pt-3 pb-3 bg-[rgb(var(--app-bg-rgb))]" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important;">
|
||||||
<div id="mpe-cal-section" class="hidden">
|
<div id="mpe-cal-section" class="hidden">
|
||||||
${createCalendarTopbarHTML({
|
${createCalendarTopbarHTML({
|
||||||
prevId: 'mpe-cal-prev',
|
prevId: 'mpe-cal-prev',
|
||||||
@@ -66,12 +66,12 @@ export function getMealPlanEditorHTML() {
|
|||||||
<div id="mpe-slot-chips" class="flex flex-wrap gap-1.5"></div>
|
<div id="mpe-slot-chips" class="flex flex-wrap gap-1.5"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="mpe-summary-wrap" class="relative z-[1] shrink-0 px-5 pb-3 bg-[#2d2e2b]" style="background:#2d2e2b !important; background-image:none !important;">
|
<div id="mpe-summary-wrap" class="relative z-[1] shrink-0 px-5 pb-3 bg-[rgb(var(--app-bg-rgb))]" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important;">
|
||||||
<div id="mpe-nutrition-section"></div>
|
<div id="mpe-nutrition-section"></div>
|
||||||
<div id="mpe-servings-row" class="mt-3"></div>
|
<div id="mpe-servings-row" class="mt-3"></div>
|
||||||
<div id="mpe-top-shadow" class="pointer-events-none absolute inset-x-0 -bottom-3 h-3 opacity-0 transition-opacity duration-200" style="background:linear-gradient(to bottom, rgba(0,0,0,0.12), rgba(0,0,0,0.03), rgba(0,0,0,0));"></div>
|
<div id="mpe-top-shadow" class="pointer-events-none absolute inset-x-0 -bottom-3 h-3 opacity-0 transition-opacity duration-200" style="background:linear-gradient(to bottom, rgba(0,0,0,0.12), rgba(0,0,0,0.03), rgba(0,0,0,0));"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="mpe-ing-scroll" class="flex-1 min-h-0 overflow-y-auto no-scrollbar px-5 bg-[#2d2e2b]" style="background:#2d2e2b !important; background-image:none !important; padding-bottom:calc(1.5rem + env(safe-area-inset-bottom));">
|
<div id="mpe-ing-scroll" class="flex-1 min-h-0 overflow-y-auto no-scrollbar px-5 bg-[rgb(var(--app-bg-rgb))]" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important; padding-bottom:calc(1.5rem + env(safe-area-inset-bottom));">
|
||||||
<div id="mpe-ing-section" class="mb-4">
|
<div id="mpe-ing-section" class="mb-4">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Składniki</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Składniki</p>
|
||||||
<div id="mpe-ing-list" class="space-y-1.5"></div>
|
<div id="mpe-ing-list" class="space-y-1.5"></div>
|
||||||
@@ -214,9 +214,9 @@ export function setupMealPlanEditor() {
|
|||||||
if (!r) return;
|
if (!r) return;
|
||||||
el.innerHTML = MEAL_SLOTS.filter((s) => r.allowedSlots.includes(s.id)).map((s) => {
|
el.innerHTML = MEAL_SLOTS.filter((s) => r.allowedSlots.includes(s.id)).map((s) => {
|
||||||
const sel = s.id === S.slotId;
|
const sel = s.id === S.slotId;
|
||||||
const bg = sel ? '#23221e' : '#2f2f2d';
|
const bg = sel ? 'rgb(var(--sunken-rgb))' : 'rgb(var(--card-soft-rgb))';
|
||||||
const border = sel ? '#787876' : '#444442';
|
const border = sel ? 'rgb(var(--border-input-rgb))' : 'rgb(var(--card-strong-rgb))';
|
||||||
const text = sel ? '#f2efe8' : '#d7d2c8';
|
const text = sel ? 'rgb(var(--text-emphasis-rgb))' : 'rgb(var(--text-body-soft-rgb))';
|
||||||
return `<button type="button" class="mpe-slot-btn px-3 py-1.5 rounded-full border text-[12px] font-semibold transition-colors" data-slot-id="${s.id}" style="background:${bg} !important; background-image:none !important; box-shadow:none !important; border-color:${border} !important; color:${text} !important;">${esc(s.label)}</button>`;
|
return `<button type="button" class="mpe-slot-btn px-3 py-1.5 rounded-full border text-[12px] font-semibold transition-colors" data-slot-id="${s.id}" style="background:${bg} !important; background-image:none !important; box-shadow:none !important; border-color:${border} !important; color:${text} !important;">${esc(s.label)}</button>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
}
|
}
|
||||||
@@ -245,12 +245,12 @@ export function setupMealPlanEditor() {
|
|||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="flex items-center justify-between gap-3">
|
<div class="flex items-center justify-between gap-3">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Porcje</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Porcje</p>
|
||||||
<div class="flex h-[2rem] w-[5.25rem] shrink-0 items-center gap-0.5 rounded-full border px-0.5" style="background:#2f2f2d;border-color:#444442;box-shadow:0 2px 8px rgba(0,0,0,0.25);">
|
<div class="flex h-[2rem] w-[5.25rem] shrink-0 items-center gap-0.5 rounded-full border px-0.5" style="background:rgb(var(--card-soft-rgb));border-color:rgb(var(--card-strong-rgb));box-shadow:0 2px 8px rgba(0,0,0,0.25);">
|
||||||
<button type="button" id="mpe-serv-minus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[#d7d2c8] transition-colors" aria-label="Zmniejsz liczbę porcji">
|
<button type="button" id="mpe-serv-minus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[rgb(var(--text-body-soft-rgb))] transition-colors" aria-label="Zmniejsz liczbę porcji">
|
||||||
<i class="fas fa-minus text-[10px]"></i>
|
<i class="fas fa-minus text-[10px]"></i>
|
||||||
</button>
|
</button>
|
||||||
<span id="mpe-serv-count" class="flex-1 h-full inline-flex items-center justify-center px-0.5 text-[12px] font-semibold leading-none text-[#d7d2c8] tabular-nums">${S.servings}</span>
|
<span id="mpe-serv-count" class="flex-1 h-full inline-flex items-center justify-center px-0.5 text-[12px] font-semibold leading-none text-[rgb(var(--text-body-soft-rgb))] tabular-nums">${S.servings}</span>
|
||||||
<button type="button" id="mpe-serv-plus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[#d7d2c8] transition-colors" aria-label="Zwiększ liczbę porcji">
|
<button type="button" id="mpe-serv-plus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[rgb(var(--text-body-soft-rgb))] transition-colors" aria-label="Zwiększ liczbę porcji">
|
||||||
<i class="fas fa-plus text-[10px]"></i>
|
<i class="fas fa-plus text-[10px]"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -269,7 +269,7 @@ export function setupMealPlanEditor() {
|
|||||||
const removeBtn = (cls, attrs) =>
|
const removeBtn = (cls, attrs) =>
|
||||||
`<button type="button" class="${cls} shrink-0 w-6 h-6 rounded-full border border-gray-200 text-gray-300 hover:text-red-500 hover:border-red-200 hover:bg-red-50 flex items-center justify-center transition-colors" ${attrs}><i class="fas fa-minus text-[8px]"></i></button>`;
|
`<button type="button" class="${cls} shrink-0 w-6 h-6 rounded-full border border-gray-200 text-gray-300 hover:text-red-500 hover:border-red-200 hover:bg-red-50 flex items-center justify-center transition-colors" ${attrs}><i class="fas fa-minus text-[8px]"></i></button>`;
|
||||||
const ingredientRowClass = 'mpe-ing-row rounded-xl px-3 py-3';
|
const ingredientRowClass = 'mpe-ing-row rounded-xl px-3 py-3';
|
||||||
const ingredientRowStyle = 'background:#393937 !important; background-image:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.25) !important; border:none !important;';
|
const ingredientRowStyle = 'background:rgb(var(--card-rgb)) !important; background-image:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.25) !important; border:none !important;';
|
||||||
|
|
||||||
for (const ing of r.ingredients) {
|
for (const ing of r.ingredients) {
|
||||||
const id = ing.ingredientId;
|
const id = ing.ingredientId;
|
||||||
@@ -317,12 +317,12 @@ export function setupMealPlanEditor() {
|
|||||||
const isSel = eid === altId;
|
const isSel = eid === altId;
|
||||||
const checkbox = `
|
const checkbox = `
|
||||||
<span class="ml-auto self-center w-[18px] h-[18px] rounded-full shrink-0 flex items-center justify-center"
|
<span class="ml-auto self-center w-[18px] h-[18px] rounded-full shrink-0 flex items-center justify-center"
|
||||||
style="border:1.5px solid #56534f; background:transparent;">
|
style="border:1.5px solid rgba(var(--border-input-rgb), 0.58); background:transparent;">
|
||||||
${isSel ? '<i class="fas fa-check" style="color:#9b978f; font-size:8px; line-height:1; display:block; transform:translateY(0.5px);"></i>' : ''}
|
${isSel ? '<i class="fas fa-check" style="color:rgb(var(--text-dim-rgb)); font-size:8px; line-height:1; display:block; transform:translateY(0.5px);"></i>' : ''}
|
||||||
</span>`;
|
</span>`;
|
||||||
const n = nutFor(altId, disp, ing.unit);
|
const n = nutFor(altId, disp, ing.unit);
|
||||||
const nLine = n ? `<div class="text-[10px] text-gray-400 mt-0.5 tabular-nums">${n.kcal} kcal · ${n.protein}g B · ${n.fat}g T · ${n.carbs}g W</div>` : '';
|
const nLine = n ? `<div class="text-[10px] text-gray-400 mt-0.5 tabular-nums">${n.kcal} kcal · ${n.protein}g B · ${n.fat}g T · ${n.carbs}g W</div>` : '';
|
||||||
html += `<button type="button" class="mpe-alt-pick w-full text-left p-2.5 rounded-lg transition-all" style="background:#2f2f2d !important; background-image:none !important; border:none !important; box-shadow:none !important;" data-orig-id="${esc(id)}" data-alt-id="${esc(altId)}"><div class="flex items-center gap-3"><div class="min-w-0 flex-1"><div class="text-[11px] font-semibold text-gray-900">${esc(name)}</div>${nLine}</div>${checkbox}</div></button>`;
|
html += `<button type="button" class="mpe-alt-pick w-full text-left p-2.5 rounded-lg transition-all" style="background:rgb(var(--card-soft-rgb)) !important; background-image:none !important; border:none !important; box-shadow:none !important;" data-orig-id="${esc(id)}" data-alt-id="${esc(altId)}"><div class="flex items-center gap-3"><div class="min-w-0 flex-1"><div class="text-[11px] font-semibold text-gray-900">${esc(name)}</div>${nLine}</div>${checkbox}</div></button>`;
|
||||||
}
|
}
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
}
|
}
|
||||||
@@ -341,7 +341,7 @@ export function setupMealPlanEditor() {
|
|||||||
const addedBadge = addedProduct
|
const addedBadge = addedProduct
|
||||||
? `<div class="flex items-center gap-1 mt-0.5"><span class="text-[10px] text-emerald-400 truncate">${esc(addedProduct.name)}</span></div>`
|
? `<div class="flex items-center gap-1 mt-0.5"><span class="text-[10px] text-emerald-400 truncate">${esc(addedProduct.name)}</span></div>`
|
||||||
: '';
|
: '';
|
||||||
html += `<div class="flex-1 min-w-0 mpe-open-product-card cursor-pointer" data-eid="${esc(a.ingredientId)}" data-pid="${esc(addedPid)}"><div class="flex items-center gap-1.5"><span class="text-[12px] font-semibold text-gray-900 truncate">${esc(name)}</span><span class="shrink-0 inline-flex items-center justify-center text-[#8f8b84]" title="Dodany składnik" aria-label="Dodany składnik"><i class="fas fa-plus text-[8px]"></i></span></div>${addedBadge}</div>`;
|
html += `<div class="flex-1 min-w-0 mpe-open-product-card cursor-pointer" data-eid="${esc(a.ingredientId)}" data-pid="${esc(addedPid)}"><div class="flex items-center gap-1.5"><span class="text-[12px] font-semibold text-gray-900 truncate">${esc(name)}</span><span class="shrink-0 inline-flex items-center justify-center text-[rgb(var(--text-faint-rgb))]" title="Dodany składnik" aria-label="Dodany składnik"><i class="fas fa-plus text-[8px]"></i></span></div>${addedBadge}</div>`;
|
||||||
html += `<button type="button" class="mpe-edit-amt shrink-0 flex items-center gap-1 px-2 py-1 rounded-lg hover:bg-gray-100 transition-colors" data-ing-id="${esc(a.ingredientId)}" data-type="added">`;
|
html += `<button type="button" class="mpe-edit-amt shrink-0 flex items-center gap-1 px-2 py-1 rounded-lg hover:bg-gray-100 transition-colors" data-ing-id="${esc(a.ingredientId)}" data-type="added">`;
|
||||||
html += `<span class="text-[12px] font-semibold text-gray-900 tabular-nums">${fmtAmt(disp)}</span>`;
|
html += `<span class="text-[12px] font-semibold text-gray-900 tabular-nums">${fmtAmt(disp)}</span>`;
|
||||||
html += `<span class="text-[11px] text-gray-500">${esc(a.unit)}</span></button>`;
|
html += `<span class="text-[11px] text-gray-500">${esc(a.unit)}</span></button>`;
|
||||||
@@ -365,7 +365,7 @@ export function setupMealPlanEditor() {
|
|||||||
const el = document.getElementById('mpe-add-area');
|
const el = document.getElementById('mpe-add-area');
|
||||||
if (!el) return;
|
if (!el) return;
|
||||||
if (!S.addOpen) {
|
if (!S.addOpen) {
|
||||||
el.innerHTML = `<button type="button" id="mpe-add-btn" class="w-full py-2 rounded-xl border border-dashed text-[12px] font-semibold transition-colors" style="border-color:#444442; color:#9b978f; background:transparent !important; box-shadow:none !important; -webkit-tap-highlight-color:transparent;"><i class="fas fa-plus text-[10px] mr-1.5 opacity-70"></i>Dodaj składnik</button>`;
|
el.innerHTML = `<button type="button" id="mpe-add-btn" class="w-full py-2 rounded-xl border border-dashed text-[12px] font-semibold transition-colors" style="border-color:rgb(var(--card-strong-rgb)); color:rgb(var(--text-dim-rgb)); background:transparent !important; box-shadow:none !important; -webkit-tap-highlight-color:transparent;"><i class="fas fa-plus text-[10px] mr-1.5 opacity-70"></i>Dodaj składnik</button>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const recipe = RECIPES[S.recipeId];
|
const recipe = RECIPES[S.recipeId];
|
||||||
@@ -376,15 +376,15 @@ export function setupMealPlanEditor() {
|
|||||||
const q = S.addQuery.toLowerCase().trim();
|
const q = S.addQuery.toLowerCase().trim();
|
||||||
const avail = Object.values(INGREDIENTS).filter((i) => !usedIds.has(i.id) && (!q || i.name.toLowerCase().includes(q)));
|
const avail = Object.values(INGREDIENTS).filter((i) => !usedIds.has(i.id) && (!q || i.name.toLowerCase().includes(q)));
|
||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="rounded-xl p-3" style="background:#393937 !important; border:1px solid #444442;">
|
<div class="rounded-xl p-3" style="background:rgb(var(--card-rgb)) !important; border:1px solid rgb(var(--card-strong-rgb));">
|
||||||
<div class="flex items-center gap-2 mb-2">
|
<div class="flex items-center gap-2 mb-2">
|
||||||
<input type="text" id="mpe-add-search" class="flex-1 rounded-lg px-3 py-1.5 text-[12px] outline-none placeholder:text-[#8f8b84]" style="background:#2f2f2d !important; border:1px solid #444442; color:#ddd6ca;" placeholder="Szukaj składnika…" value="${esc(S.addQuery)}">
|
<input type="text" id="mpe-add-search" class="flex-1 rounded-lg px-3 py-1.5 text-[12px] outline-none placeholder:text-[rgb(var(--text-faint-rgb))]" style="background:rgb(var(--card-soft-rgb)) !important; border:1px solid rgb(var(--card-strong-rgb)); color:rgb(var(--text-body-rgb));" placeholder="Szukaj składnika…" value="${esc(S.addQuery)}">
|
||||||
<button type="button" id="mpe-add-cancel" class="text-[11px] font-semibold px-2 py-1 transition-colors" style="color:#9b978f;">Anuluj</button>
|
<button type="button" id="mpe-add-cancel" class="text-[11px] font-semibold px-2 py-1 transition-colors" style="color:rgb(var(--text-dim-rgb));">Anuluj</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="max-h-40 overflow-y-auto space-y-1 no-scrollbar" id="mpe-add-results">
|
<div class="max-h-40 overflow-y-auto space-y-1 no-scrollbar" id="mpe-add-results">
|
||||||
${avail.length === 0
|
${avail.length === 0
|
||||||
? '<p class="rounded-lg px-2.5 py-3 text-[11px] text-center" style="background:#2f2f2d !important; color:#9b978f;">Brak wyników</p>'
|
? '<p class="rounded-lg px-2.5 py-3 text-[11px] text-center" style="background:rgb(var(--card-soft-rgb)) !important; color:rgb(var(--text-dim-rgb));">Brak wyników</p>'
|
||||||
: avail.slice(0, 20).map((i) => `<button type="button" class="mpe-add-pick w-full text-left px-3 py-3 rounded-lg transition-colors text-[12px] font-medium" style="background:#2f2f2d !important; color:#ddd6ca;" data-ing-id="${esc(i.id)}">${esc(i.name)}</button>`).join('')}
|
: avail.slice(0, 20).map((i) => `<button type="button" class="mpe-add-pick w-full text-left px-3 py-3 rounded-lg transition-colors text-[12px] font-medium" style="background:rgb(var(--card-soft-rgb)) !important; color:rgb(var(--text-body-rgb));" data-ing-id="${esc(i.id)}">${esc(i.name)}</button>`).join('')}
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
@@ -400,8 +400,8 @@ export function setupMealPlanEditor() {
|
|||||||
const q = S.addQuery.toLowerCase().trim();
|
const q = S.addQuery.toLowerCase().trim();
|
||||||
const avail = Object.values(INGREDIENTS).filter((i) => !usedIds.has(i.id) && (!q || i.name.toLowerCase().includes(q)));
|
const avail = Object.values(INGREDIENTS).filter((i) => !usedIds.has(i.id) && (!q || i.name.toLowerCase().includes(q)));
|
||||||
results.innerHTML = avail.length === 0
|
results.innerHTML = avail.length === 0
|
||||||
? '<p class="rounded-lg px-2.5 py-3 text-[11px] text-center" style="background:#2f2f2d !important; color:#9b978f;">Brak wyników</p>'
|
? '<p class="rounded-lg px-2.5 py-3 text-[11px] text-center" style="background:rgb(var(--card-soft-rgb)) !important; color:rgb(var(--text-dim-rgb));">Brak wyników</p>'
|
||||||
: avail.slice(0, 20).map((i) => `<button type="button" class="mpe-add-pick w-full text-left px-3 py-3 rounded-lg transition-colors text-[12px] font-medium" style="background:#2f2f2d !important; color:#ddd6ca;" data-ing-id="${esc(i.id)}">${esc(i.name)}</button>`).join('');
|
: avail.slice(0, 20).map((i) => `<button type="button" class="mpe-add-pick w-full text-left px-3 py-3 rounded-lg transition-colors text-[12px] font-medium" style="background:rgb(var(--card-soft-rgb)) !important; color:rgb(var(--text-body-rgb));" data-ing-id="${esc(i.id)}">${esc(i.name)}</button>`).join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderIngredients() {
|
function renderIngredients() {
|
||||||
@@ -417,23 +417,23 @@ export function setupMealPlanEditor() {
|
|||||||
if (!el) return;
|
if (!el) return;
|
||||||
const n = totalNutrition();
|
const n = totalNutrition();
|
||||||
el.innerHTML = `
|
el.innerHTML = `
|
||||||
<div class="h-full pb-2 flex flex-col" style="background:#2d2e2b !important; background-image:none !important; box-shadow:none !important;">
|
<div class="h-full pb-2 flex flex-col" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important; box-shadow:none !important;">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Wartości odżywcze</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Wartości odżywcze</p>
|
||||||
<div class="flex-1 flex items-center">
|
<div class="flex-1 flex items-center">
|
||||||
<div class="grid grid-cols-4 gap-1.5 w-full">
|
<div class="grid grid-cols-4 gap-1.5 w-full">
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-gray-100 tabular-nums leading-tight">${n.kcal}</p>
|
<p class="text-[15px] font-bold text-gray-100 tabular-nums leading-tight">${n.kcal}</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">kcal</p>
|
<p class="text-[9px] text-gray-500 font-medium">kcal</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">${n.protein}g</p>
|
<p class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">${n.protein}g</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">białko</p>
|
<p class="text-[9px] text-gray-500 font-medium">białko</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">${n.fat}g</p>
|
<p class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">${n.fat}g</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">tłuszcz</p>
|
<p class="text-[9px] text-gray-500 font-medium">tłuszcz</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">${n.carbs}g</p>
|
<p class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">${n.carbs}g</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">węglowodany</p>
|
<p class="text-[9px] text-gray-500 font-medium">węglowodany</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -753,7 +753,7 @@ export function setupMealPlanEditor() {
|
|||||||
const ingBase = S.overrides[origId] ?? recipeIng?.amount ?? 0;
|
const ingBase = S.overrides[origId] ?? recipeIng?.amount ?? 0;
|
||||||
const ingDisp = ingBase * S.servings;
|
const ingDisp = ingBase * S.servings;
|
||||||
|
|
||||||
const checkmark = (sel) => `<span class="ml-auto self-center w-[18px] h-[18px] rounded-full shrink-0 flex items-center justify-center" style="border:1.5px solid #56534f; background:transparent;">${sel ? '<i class="fas fa-check" style="color:#9b978f; font-size:8px; line-height:1; display:block; transform:translateY(0.5px);"></i>' : ''}</span>`;
|
const checkmark = (sel) => `<span class="ml-auto self-center w-[18px] h-[18px] rounded-full shrink-0 flex items-center justify-center" style="border:1.5px solid rgba(var(--border-input-rgb), 0.58); background:transparent;">${sel ? '<i class="fas fa-check" style="color:rgb(var(--text-dim-rgb)); font-size:8px; line-height:1; display:block; transform:translateY(0.5px);"></i>' : ''}</span>`;
|
||||||
|
|
||||||
let pickerHtml = '<div class="mpe-product-picker mt-2 ml-1 space-y-1">';
|
let pickerHtml = '<div class="mpe-product-picker mt-2 ml-1 space-y-1">';
|
||||||
for (const p of products) {
|
for (const p of products) {
|
||||||
@@ -766,7 +766,7 @@ export function setupMealPlanEditor() {
|
|||||||
const f = g / 100;
|
const f = g / 100;
|
||||||
const n = pNut ? { kcal: Math.round(pNut.kcal * f), protein: Math.round(pNut.protein * f * 10) / 10, fat: Math.round(pNut.fat * f * 10) / 10, carbs: Math.round(pNut.carbs * f * 10) / 10 } : null;
|
const n = pNut ? { kcal: Math.round(pNut.kcal * f), protein: Math.round(pNut.protein * f * 10) / 10, fat: Math.round(pNut.fat * f * 10) / 10, carbs: Math.round(pNut.carbs * f * 10) / 10 } : null;
|
||||||
const nLine = n ? `<div class="text-[10px] text-gray-400 mt-0.5 tabular-nums">${n.kcal} kcal · ${n.protein}g B · ${n.fat}g T · ${n.carbs}g W</div>` : '';
|
const nLine = n ? `<div class="text-[10px] text-gray-400 mt-0.5 tabular-nums">${n.kcal} kcal · ${n.protein}g B · ${n.fat}g T · ${n.carbs}g W</div>` : '';
|
||||||
pickerHtml += `<button type="button" class="mpe-prod-pick w-full text-left p-2.5 rounded-lg transition-all" style="background:#2f2f2d !important; background-image:none !important; border:none !important; box-shadow:none !important;" data-eid="${esc(eid)}" data-prod-id="${esc(p.id)}">
|
pickerHtml += `<button type="button" class="mpe-prod-pick w-full text-left p-2.5 rounded-lg transition-all" style="background:rgb(var(--card-soft-rgb)) !important; background-image:none !important; border:none !important; box-shadow:none !important;" data-eid="${esc(eid)}" data-prod-id="${esc(p.id)}">
|
||||||
<div class="flex items-center gap-3"><div class="min-w-0 flex-1"><div class="text-[11px] font-semibold text-gray-900">${esc(p.name)}</div>${nLine}</div>${checkmark(isSel)}</div>
|
<div class="flex items-center gap-3"><div class="min-w-0 flex-1"><div class="text-[11px] font-semibold text-gray-900">${esc(p.name)}</div>${nLine}</div>${checkmark(isSel)}</div>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,22 +33,22 @@ function renderRecipeCard(recipe, { showSlotLabels = true, cardClassName = '' }
|
|||||||
const className = ['recipe-browser-card', cardClassName].filter(Boolean).join(' ');
|
const className = ['recipe-browser-card', cardClassName].filter(Boolean).join(' ');
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<button type="button" data-recipe-id="${escapeHtml(recipe.id)}" class="${className} rounded-xl overflow-hidden flex flex-col bg-[#393937] cursor-pointer text-left transition-shadow" style="background:#393937 !important; border:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.28) !important;">
|
<button type="button" data-recipe-id="${escapeHtml(recipe.id)}" class="${className} rounded-xl overflow-hidden flex flex-col bg-[rgb(var(--card-rgb))] cursor-pointer text-left transition-shadow" style="background:rgb(var(--card-rgb)) !important; border:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.28) !important;">
|
||||||
<div class="recipe-browser-card-media h-32 bg-[#d4d4d4] relative overflow-hidden">
|
<div class="recipe-browser-card-media h-32 bg-[rgb(var(--skeleton-rgb))] relative overflow-hidden">
|
||||||
${recipe.image
|
${recipe.image
|
||||||
? `<img src="${escapeHtml(recipe.image)}" alt="${escapeHtml(recipe.title)}" class="w-full h-full object-cover">`
|
? `<img src="${escapeHtml(recipe.image)}" alt="${escapeHtml(recipe.title)}" class="w-full h-full object-cover">`
|
||||||
: `<span class="absolute inset-0 flex items-center justify-center text-white font-medium text-xs">${escapeHtml(recipe.thumbLabel)}</span>`}
|
: `<span class="absolute inset-0 flex items-center justify-center text-white font-medium text-xs">${escapeHtml(recipe.thumbLabel)}</span>`}
|
||||||
</div>
|
</div>
|
||||||
<div class="recipe-browser-card-body p-3 flex flex-col flex-1">
|
<div class="recipe-browser-card-body p-3 flex flex-col flex-1">
|
||||||
<h3 class="recipe-browser-card-title text-sm font-medium underline decoration-1 underline-offset-2 text-[#f1ede4] mb-3 line-clamp-2">${escapeHtml(recipe.title)}</h3>
|
<h3 class="recipe-browser-card-title text-sm font-medium underline decoration-1 underline-offset-2 text-[rgb(var(--text-primary-rgb))] mb-3 line-clamp-2">${escapeHtml(recipe.title)}</h3>
|
||||||
<div class="recipe-browser-card-footer mt-auto">
|
<div class="recipe-browser-card-footer mt-auto">
|
||||||
<div class="recipe-browser-card-meta flex items-center justify-between text-[11px] text-[#c2bcb2] font-medium mb-2">
|
<div class="recipe-browser-card-meta flex items-center justify-between text-[11px] text-[rgb(var(--text-muted-rgb))] font-medium mb-2">
|
||||||
<div class="flex items-center gap-1"><i class="fas fa-clock text-[#8f8b84]" aria-hidden="true"></i><span>${recipe.minutes} min</span></div>
|
<div class="flex items-center gap-1"><i class="fas fa-clock text-[rgb(var(--text-faint-rgb))]" aria-hidden="true"></i><span>${recipe.minutes} min</span></div>
|
||||||
<div class="flex items-center gap-1"><i class="fas fa-fire text-[#8f8b84]" aria-hidden="true"></i><span>${recipe.nutritionPerServing.kcal} kcal</span></div>
|
<div class="flex items-center gap-1"><i class="fas fa-fire text-[rgb(var(--text-faint-rgb))]" aria-hidden="true"></i><span>${recipe.nutritionPerServing.kcal} kcal</span></div>
|
||||||
</div>
|
</div>
|
||||||
${labels.length > 0
|
${labels.length > 0
|
||||||
? `<div class="recipe-browser-card-labels flex flex-wrap gap-1">
|
? `<div class="recipe-browser-card-labels flex flex-wrap gap-1">
|
||||||
${labels.map((label) => `<span class="recipe-browser-card-label px-2 py-0.5 bg-[#2f2f2d] text-[#d7d2c8] text-[10px] rounded-md font-medium">${escapeHtml(label)}</span>`).join('')}
|
${labels.map((label) => `<span class="recipe-browser-card-label px-2 py-0.5 bg-[rgb(var(--card-soft-rgb))] text-[rgb(var(--text-body-soft-rgb))] text-[10px] rounded-md font-medium">${escapeHtml(label)}</span>`).join('')}
|
||||||
</div>`
|
</div>`
|
||||||
: ''}
|
: ''}
|
||||||
</div>
|
</div>
|
||||||
@@ -71,14 +71,14 @@ export function getRecipeGridSectionHTML({
|
|||||||
scrollId,
|
scrollId,
|
||||||
gridId,
|
gridId,
|
||||||
emptyStateId,
|
emptyStateId,
|
||||||
scrollClassName = 'relative flex-1 overflow-y-auto px-4 pt-20 pb-24 bg-[#2d2e2b]',
|
scrollClassName = 'relative flex-1 overflow-y-auto px-4 pt-20 pb-24 bg-[rgb(var(--app-bg-rgb))]',
|
||||||
gridClassName = 'grid grid-cols-2 gap-3 bg-[#2d2e2b]',
|
gridClassName = 'grid grid-cols-2 gap-3 bg-[rgb(var(--app-bg-rgb))]',
|
||||||
emptyTitle = 'Brak wyników',
|
emptyTitle = 'Brak wyników',
|
||||||
emptyMessage = 'Zmień kryteria wyszukiwania lub filtry',
|
emptyMessage = 'Zmień kryteria wyszukiwania lub filtry',
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return `
|
return `
|
||||||
<div id="${escapeHtml(scrollId)}" class="${scrollClassName}" style="background:#2d2e2b !important;">
|
<div id="${escapeHtml(scrollId)}" class="${scrollClassName}" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div id="${escapeHtml(gridId)}" class="${gridClassName}" style="background:#2d2e2b !important;"></div>
|
<div id="${escapeHtml(gridId)}" class="${gridClassName}" style="background:rgb(var(--app-bg-rgb)) !important;"></div>
|
||||||
${getEmptyStateHTML({
|
${getEmptyStateHTML({
|
||||||
emptyStateId,
|
emptyStateId,
|
||||||
title: emptyTitle,
|
title: emptyTitle,
|
||||||
|
|||||||
@@ -27,11 +27,11 @@ export function getRecipeSearchFieldHTML({
|
|||||||
const ariaLabel = inputAriaLabel || placeholder;
|
const ariaLabel = inputAriaLabel || placeholder;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div id="${escapeHtml(shellId)}" class="relative z-[1] mx-auto flex items-center w-full overflow-hidden" style="width:min(calc(100% - 0.5rem), 22.4rem); background:#393937 !important; border:1px solid #41423f !important; border-radius:999px !important; box-shadow:${RECIPE_SEARCH_SHELL_BASE_SHADOW} !important; transition:box-shadow 180ms ease;">
|
<div id="${escapeHtml(shellId)}" class="relative z-[1] mx-auto flex items-center w-full overflow-hidden" style="width:min(calc(100% - 0.5rem), 22.4rem); background:rgb(var(--card-rgb)) !important; border:1px solid rgb(var(--border-card-rgb)) !important; border-radius:999px !important; box-shadow:${RECIPE_SEARCH_SHELL_BASE_SHADOW} !important; transition:box-shadow 180ms ease;">
|
||||||
<input type="text" id="${escapeHtml(inputId)}" value="${escapeHtml(inputValue)}" placeholder="${escapeHtml(placeholder)}" aria-label="${escapeHtml(ariaLabel)}" class="w-full bg-transparent outline-none text-[15px] text-center py-[12px] ${inputPadding}" style="background:transparent !important; border:none !important; box-shadow:none !important; backdrop-filter:none !important;">
|
<input type="text" id="${escapeHtml(inputId)}" value="${escapeHtml(inputValue)}" placeholder="${escapeHtml(placeholder)}" aria-label="${escapeHtml(ariaLabel)}" class="w-full bg-transparent outline-none text-[15px] text-center py-[12px] ${inputPadding}" style="background:transparent !important; border:none !important; box-shadow:none !important; backdrop-filter:none !important;">
|
||||||
${hasFilterButton
|
${hasFilterButton
|
||||||
? `
|
? `
|
||||||
<button id="${escapeHtml(filterButtonId)}"${actionAttr} class="absolute right-2 top-1/2 -translate-y-1/2 w-9 h-9 text-[#c9c3b8] hover:text-[#f0e8dc] flex items-center justify-center transition-colors" style="background:transparent !important; border:none !important; box-shadow:none !important;" aria-label="${escapeHtml(filterButtonLabel)}">
|
<button id="${escapeHtml(filterButtonId)}"${actionAttr} class="absolute right-2 top-1/2 -translate-y-1/2 w-9 h-9 text-[rgb(var(--text-body-soft-rgb))] hover:text-[rgb(var(--text-emphasis-rgb))] flex items-center justify-center transition-colors" style="background:transparent !important; border:none !important; box-shadow:none !important;" aria-label="${escapeHtml(filterButtonLabel)}">
|
||||||
<i class="fas fa-sliders-h" aria-hidden="true"></i>
|
<i class="fas fa-sliders-h" aria-hidden="true"></i>
|
||||||
</button>`
|
</button>`
|
||||||
: ''}
|
: ''}
|
||||||
|
|||||||
@@ -3,15 +3,15 @@ import { MEAL_SLOTS } from '../planner/mealSlots.js';
|
|||||||
import { applyFilters, getFilterState } from './RecipeList.js';
|
import { applyFilters, getFilterState } from './RecipeList.js';
|
||||||
|
|
||||||
const FILTER_PANEL_TRANSITION = 'opacity 180ms ease, transform 180ms ease';
|
const FILTER_PANEL_TRANSITION = 'opacity 180ms ease, transform 180ms ease';
|
||||||
const FILTER_SURFACE = '#23221e';
|
const FILTER_SURFACE = 'rgb(var(--sunken-rgb))';
|
||||||
const FILTER_SURFACE_SOFT = '#2d2e2b';
|
const FILTER_SURFACE_SOFT = 'rgb(var(--app-bg-rgb))';
|
||||||
const FILTER_BORDER = '#787876';
|
const FILTER_BORDER = 'rgb(var(--border-input-rgb))';
|
||||||
const FILTER_CHIP_ACTIVE_BG = '#393937';
|
const FILTER_CHIP_ACTIVE_BG = 'rgb(var(--card-rgb))';
|
||||||
const FILTER_TEXT_SECONDARY = '#d7d2c8';
|
const FILTER_TEXT_SECONDARY = 'rgb(var(--text-body-soft-rgb))';
|
||||||
const FILTER_TEXT_MUTED = '#b5afa5';
|
const FILTER_TEXT_MUTED = 'rgb(var(--text-muted-rgb))';
|
||||||
const FILTER_TEXT_ACTIVE = '#f2efe8';
|
const FILTER_TEXT_ACTIVE = 'rgb(var(--text-emphasis-rgb))';
|
||||||
const FILTER_TRACK = '#393937';
|
const FILTER_TRACK = 'rgb(var(--card-rgb))';
|
||||||
const FILTER_TRACK_FILL = '#56534f';
|
const FILTER_TRACK_FILL = 'rgba(var(--border-input-rgb), 0.58)';
|
||||||
const FILTER_SHADOW = '0 5px 10px rgba(0,0,0,0.16), 0 14px 22px rgba(0,0,0,0.24), 0 22px 34px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.04)';
|
const FILTER_SHADOW = '0 5px 10px rgba(0,0,0,0.16), 0 14px 22px rgba(0,0,0,0.24), 0 22px 34px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.04)';
|
||||||
const PREP_TIME_MIN = 5;
|
const PREP_TIME_MIN = 5;
|
||||||
const PREP_TIME_MAX = 120;
|
const PREP_TIME_MAX = 120;
|
||||||
@@ -72,7 +72,7 @@ export function getFilterHTML() {
|
|||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
border-radius: 9999px;
|
border-radius: 9999px;
|
||||||
border: 1px solid rgba(242,239,232,0.16);
|
border: 1px solid rgba(var(--text-emphasis-rgb),0.16);
|
||||||
background: ${FILTER_TRACK_FILL};
|
background: ${FILTER_TRACK_FILL};
|
||||||
box-shadow: 0 0 0 1px rgba(0,0,0,0.12);
|
box-shadow: 0 0 0 1px rgba(0,0,0,0.12);
|
||||||
touch-action: none;
|
touch-action: none;
|
||||||
@@ -374,9 +374,9 @@ function syncPanelCount() {
|
|||||||
|
|
||||||
if (button) {
|
if (button) {
|
||||||
const highlight = isFilterPanelOpen() || count > 0;
|
const highlight = isFilterPanelOpen() || count > 0;
|
||||||
button.style.setProperty('background', highlight ? '#23221e' : '#393937', 'important');
|
button.style.setProperty('background', highlight ? 'rgb(var(--sunken-rgb))' : 'rgb(var(--card-rgb))', 'important');
|
||||||
button.style.setProperty('border-color', highlight ? '#787876' : '#41423f', 'important');
|
button.style.setProperty('border-color', highlight ? 'rgb(var(--border-input-rgb))' : 'rgb(var(--border-card-rgb))', 'important');
|
||||||
button.style.setProperty('color', highlight ? '#f2efe8' : '#ddd6ca', 'important');
|
button.style.setProperty('color', highlight ? 'rgb(var(--text-emphasis-rgb))' : 'rgb(var(--text-body-rgb))', 'important');
|
||||||
}
|
}
|
||||||
|
|
||||||
const badge = button?.querySelector('[id$="-filter-count"]');
|
const badge = button?.querySelector('[id$="-filter-count"]');
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ function syncTodayButton(mode, weekStart, monthAnchor, selected) {
|
|||||||
|
|
||||||
export function getMealPlannerHTML() {
|
export function getMealPlannerHTML() {
|
||||||
return `
|
return `
|
||||||
<div id="planner-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden bg-[#2d2e2b] z-10">
|
<div id="planner-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden bg-[rgb(var(--app-bg-rgb))] z-10">
|
||||||
<div id="planner-cal-bar" class="shrink-0 bg-[#2d2e2b] border-b border-[#444442] mt-3 relative z-10">
|
<div id="planner-cal-bar" class="shrink-0 bg-[rgb(var(--app-bg-rgb))] border-b border-[rgb(var(--card-strong-rgb))] mt-3 relative z-10">
|
||||||
<div class="min-h-12 px-4 pt-4 pb-3 flex items-center justify-between gap-3 min-w-0">
|
<div class="min-h-12 px-4 pt-4 pb-3 flex items-center justify-between gap-3 min-w-0">
|
||||||
<h1 class="min-w-0 flex-1 truncate" style="margin:0;padding:0;color:#f2efe8;font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Plan posiłków</h1>
|
<h1 class="min-w-0 flex-1 truncate" style="margin:0;padding:0;color:rgb(var(--text-emphasis-rgb));font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Plan posiłków</h1>
|
||||||
${createCalendarTopbarHTML({
|
${createCalendarTopbarHTML({
|
||||||
prevId: 'cal-prev',
|
prevId: 'cal-prev',
|
||||||
todayId: 'cal-go-today',
|
todayId: 'cal-go-today',
|
||||||
@@ -81,12 +81,12 @@ export function getMealPlannerHTML() {
|
|||||||
wrapperClass: 'flex shrink-0 items-center justify-end',
|
wrapperClass: 'flex shrink-0 items-center justify-end',
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div id="calendar-swipe-zone" class="overflow-x-hidden bg-[#2d2e2b]" style="touch-action: none">
|
<div id="calendar-swipe-zone" class="overflow-x-hidden bg-[rgb(var(--app-bg-rgb))]" style="touch-action: none">
|
||||||
<div id="calendar-week-wrap" class="px-3 overflow-x-hidden bg-[#2d2e2b]" style="overflow: hidden; max-height: 10rem; opacity: 1; padding-bottom: 0.75rem">
|
<div id="calendar-week-wrap" class="px-3 overflow-x-hidden bg-[rgb(var(--app-bg-rgb))]" style="overflow: hidden; max-height: 10rem; opacity: 1; padding-bottom: 0.75rem">
|
||||||
${createCalendarWeekdayHeaderHTML()}
|
${createCalendarWeekdayHeaderHTML()}
|
||||||
<div id="calendar-week-grid" class="grid grid-cols-7 gap-1.5 max-w-full overflow-x-hidden"></div>
|
<div id="calendar-week-grid" class="grid grid-cols-7 gap-1.5 max-w-full overflow-x-hidden"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="calendar-month-wrap" class="px-3 bg-[#2d2e2b]" style="overflow: hidden; max-height: 0; opacity: 0; padding-bottom: 0">
|
<div id="calendar-month-wrap" class="px-3 bg-[rgb(var(--app-bg-rgb))]" style="overflow: hidden; max-height: 0; opacity: 0; padding-bottom: 0">
|
||||||
${createCalendarWeekdayHeaderHTML()}
|
${createCalendarWeekdayHeaderHTML()}
|
||||||
<div id="calendar-month-grid" class="grid grid-cols-7 gap-1.5"></div>
|
<div id="calendar-month-grid" class="grid grid-cols-7 gap-1.5"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,25 +96,25 @@ export function getMealPlannerHTML() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="planner-scroll" class="flex-1 overflow-y-auto px-4 pt-3 pb-24 bg-[#2d2e2b]">
|
<div id="planner-scroll" class="flex-1 overflow-y-auto px-4 pt-3 pb-24 bg-[rgb(var(--app-bg-rgb))]">
|
||||||
<div id="planner-summary-card" class="mb-3">
|
<div id="planner-summary-card" class="mb-3">
|
||||||
<div class="h-full flex flex-col" style="background:#2d2e2b !important; background-image:none !important; box-shadow:none !important;">
|
<div class="h-full flex flex-col" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important; box-shadow:none !important;">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Wartości odżywcze</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Wartości odżywcze</p>
|
||||||
<div class="flex-1 flex items-center">
|
<div class="flex-1 flex items-center">
|
||||||
<div class="grid grid-cols-4 gap-1.5 w-full">
|
<div class="grid grid-cols-4 gap-1.5 w-full">
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p id="planner-nutrition-kcal" class="text-[15px] font-bold text-gray-100 tabular-nums leading-tight">—</p>
|
<p id="planner-nutrition-kcal" class="text-[15px] font-bold text-gray-100 tabular-nums leading-tight">—</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">kcal</p>
|
<p class="text-[9px] text-gray-500 font-medium">kcal</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p id="planner-nutrition-p" class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">—</p>
|
<p id="planner-nutrition-p" class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">—</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">białko</p>
|
<p class="text-[9px] text-gray-500 font-medium">białko</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p id="planner-nutrition-f" class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">—</p>
|
<p id="planner-nutrition-f" class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">—</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">tłuszcz</p>
|
<p class="text-[9px] text-gray-500 font-medium">tłuszcz</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p id="planner-nutrition-c" class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">—</p>
|
<p id="planner-nutrition-c" class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">—</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">węglowodany</p>
|
<p class="text-[9px] text-gray-500 font-medium">węglowodany</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -122,19 +122,19 @@ export function getMealPlannerHTML() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" id="planner-open-ingredients" class="hidden w-full mb-3 flex items-center justify-center gap-2 py-2.5 rounded-xl border border-dashed border-[#444442] bg-[#2d2e2b] text-[13px] font-semibold text-[#d7d2c8] hover:border-[#6d6c67] hover:bg-[#3a3a37] transition-colors">
|
<button type="button" id="planner-open-ingredients" class="hidden w-full mb-3 flex items-center justify-center gap-2 py-2.5 rounded-xl border border-dashed border-[rgb(var(--card-strong-rgb))] bg-[rgb(var(--app-bg-rgb))] text-[13px] font-semibold text-[rgb(var(--text-body-soft-rgb))] hover:border-[rgb(var(--text-subdued-rgb))] hover:bg-[rgb(var(--card-raised-rgb))] transition-colors">
|
||||||
<i class="fas fa-shopping-basket text-[#9b978f] text-xs" aria-hidden="true"></i>
|
<i class="fas fa-shopping-basket text-[rgb(var(--text-dim-rgb))] text-xs" aria-hidden="true"></i>
|
||||||
Składniki na ten dzień
|
Składniki na ten dzień
|
||||||
</button>
|
</button>
|
||||||
<div id="planner-meal-slots" class="space-y-3 pb-2 bg-[#2d2e2b]"></div>
|
<div id="planner-meal-slots" class="space-y-3 pb-2 bg-[rgb(var(--app-bg-rgb))]"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="planner-picker-backdrop" class="absolute inset-0 z-[55] bg-black/45 hidden opacity-0 transition-opacity duration-200" aria-hidden="true"></div>
|
<div id="planner-picker-backdrop" class="absolute inset-0 z-[55] bg-black/45 hidden opacity-0 transition-opacity duration-200" aria-hidden="true"></div>
|
||||||
<div id="planner-picker-sheet" data-off-transform="${PLANNER_PICKER_OFF_TRANSFORM}" class="absolute inset-x-0 bottom-0 z-[60] flex flex-col will-change-transform rounded-t-[1.85rem] overflow-hidden" style="top:calc(env(safe-area-inset-top) + 0.35rem); visibility: hidden; transform: ${PLANNER_PICKER_OFF_TRANSFORM}; transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1); background:#2d2e2b !important; background-image:none !important;" role="dialog" aria-label="Wybierz przepis" aria-modal="true">
|
<div id="planner-picker-sheet" data-off-transform="${PLANNER_PICKER_OFF_TRANSFORM}" class="absolute inset-x-0 bottom-0 z-[60] flex flex-col will-change-transform rounded-t-[1.85rem] overflow-hidden" style="top:calc(env(safe-area-inset-top) + 0.35rem); visibility: hidden; transform: ${PLANNER_PICKER_OFF_TRANSFORM}; transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1); background:rgb(var(--app-bg-rgb)) !important; background-image:none !important;" role="dialog" aria-label="Wybierz przepis" aria-modal="true">
|
||||||
<div class="pointer-events-none absolute inset-x-0 top-0 z-[2] px-4 pt-3">
|
<div class="pointer-events-none absolute inset-x-0 top-0 z-[2] px-4 pt-3">
|
||||||
<div class="pointer-events-auto pb-4 touch-none cursor-grab active:cursor-grabbing select-none" data-planner-sheet-drag-zone aria-label="Przeciągnij w dół, by zamknąć">
|
<div class="pointer-events-auto pb-4 touch-none cursor-grab active:cursor-grabbing select-none" data-planner-sheet-drag-zone aria-label="Przeciągnij w dół, by zamknąć">
|
||||||
<div class="w-10 h-1 bg-[#6d6c67]/75 rounded-full mx-auto" aria-hidden="true"></div>
|
<div class="w-10 h-1 bg-[rgb(var(--text-subdued-rgb))]/75 rounded-full mx-auto" aria-hidden="true"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="pointer-events-auto">
|
<div class="pointer-events-auto">
|
||||||
${getRecipeSearchFieldHTML({
|
${getRecipeSearchFieldHTML({
|
||||||
@@ -148,8 +148,8 @@ export function getMealPlannerHTML() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="planner-picker-scroll" class="relative min-h-0 flex-1 overflow-y-auto px-4 pt-28 pb-8 bg-[#2d2e2b]" style="background:#2d2e2b !important;">
|
<div id="planner-picker-scroll" class="relative min-h-0 flex-1 overflow-y-auto px-4 pt-28 pb-8 bg-[rgb(var(--app-bg-rgb))]" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div id="planner-picker-grid" class="grid grid-cols-3 gap-2 bg-[#2d2e2b]" style="background:#2d2e2b !important;"></div>
|
<div id="planner-picker-grid" class="grid grid-cols-3 gap-2 bg-[rgb(var(--app-bg-rgb))]" style="background:rgb(var(--app-bg-rgb)) !important;"></div>
|
||||||
<div id="planner-picker-empty-state" class="hidden flex flex-col items-center justify-center py-16 text-center">
|
<div id="planner-picker-empty-state" class="hidden flex flex-col items-center justify-center py-16 text-center">
|
||||||
<div class="w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center mb-4">
|
<div class="w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center mb-4">
|
||||||
<i class="fas fa-search text-2xl text-gray-300" aria-hidden="true"></i>
|
<i class="fas fa-search text-2xl text-gray-300" aria-hidden="true"></i>
|
||||||
@@ -161,20 +161,20 @@ export function getMealPlannerHTML() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="planner-ing-backdrop" class="absolute inset-0 z-[55] bg-black/45 hidden opacity-0 transition-opacity duration-200" aria-hidden="true"></div>
|
<div id="planner-ing-backdrop" class="absolute inset-0 z-[55] bg-black/45 hidden opacity-0 transition-opacity duration-200" aria-hidden="true"></div>
|
||||||
<div id="planner-ing-sheet" class="absolute left-0 right-0 bottom-0 z-[60] rounded-t-3xl shadow-[0_-10px_40px_rgba(0,0,0,0.12)] flex flex-col will-change-transform" style="visibility: hidden; height: auto; max-height: calc(100vh - env(safe-area-inset-top) - 1rem); transform: ${PLANNER_SHEET_OFF_TRANSFORM}; transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1); background:#2d2e2b !important; background-image:none !important;" role="dialog" aria-labelledby="planner-ing-title" aria-modal="true">
|
<div id="planner-ing-sheet" class="absolute left-0 right-0 bottom-0 z-[60] rounded-t-3xl shadow-[0_-10px_40px_rgba(0,0,0,0.12)] flex flex-col will-change-transform" style="visibility: hidden; height: auto; max-height: calc(100vh - env(safe-area-inset-top) - 1rem); transform: ${PLANNER_SHEET_OFF_TRANSFORM}; transition: transform 300ms cubic-bezier(0.32, 0.72, 0, 1); background:rgb(var(--app-bg-rgb)) !important; background-image:none !important;" role="dialog" aria-labelledby="planner-ing-title" aria-modal="true">
|
||||||
<div class="shrink-0 px-4 pt-3 pb-2 border-b border-[#444442] touch-none cursor-grab active:cursor-grabbing select-none" data-planner-sheet-drag-zone aria-label="Przeciągnij w dół, by zamknąć">
|
<div class="shrink-0 px-4 pt-3 pb-2 border-b border-[rgb(var(--card-strong-rgb))] touch-none cursor-grab active:cursor-grabbing select-none" data-planner-sheet-drag-zone aria-label="Przeciągnij w dół, by zamknąć">
|
||||||
<div class="w-10 h-1 bg-[#6d6c67]/75 rounded-full mx-auto mb-2.5" aria-hidden="true"></div>
|
<div class="w-10 h-1 bg-[rgb(var(--text-subdued-rgb))]/75 rounded-full mx-auto mb-2.5" aria-hidden="true"></div>
|
||||||
<h2 id="planner-ing-title" class="text-[15px] font-bold text-[#ddd6ca] leading-tight pr-2">Składniki i spiżarnia</h2>
|
<h2 id="planner-ing-title" class="text-[15px] font-bold text-[rgb(var(--text-body-rgb))] leading-tight pr-2">Składniki i spiżarnia</h2>
|
||||||
<p id="planner-ing-sub" class="text-[11px] text-[#9b978f] mt-1">Porównanie potrzeb z zapasami.</p>
|
<p id="planner-ing-sub" class="text-[11px] text-[rgb(var(--text-dim-rgb))] mt-1">Porównanie potrzeb z zapasami.</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="planner-ing-body" class="min-h-0 flex-1 overflow-y-auto no-scrollbar px-4 py-2 pb-2"></div>
|
<div id="planner-ing-body" class="min-h-0 flex-1 overflow-y-auto no-scrollbar px-4 py-2 pb-2"></div>
|
||||||
<div id="planner-ing-footer" class="shrink-0 p-4 pt-2 pb-5 border-t border-[#444442] bg-[#2d2e2b] space-y-2">
|
<div id="planner-ing-footer" class="shrink-0 p-4 pt-2 pb-5 border-t border-[rgb(var(--card-strong-rgb))] bg-[rgb(var(--app-bg-rgb))] space-y-2">
|
||||||
<button type="button" id="planner-ing-add-all" class="w-full bg-gray-900 hover:bg-black text-white py-3 rounded-xl font-semibold shadow-sm transition-colors text-[13px] flex items-center justify-center gap-2">
|
<button type="button" id="planner-ing-add-all" class="w-full bg-gray-900 hover:bg-black text-white py-3 rounded-xl font-semibold shadow-sm transition-colors text-[13px] flex items-center justify-center gap-2">
|
||||||
<i class="fas fa-cart-plus text-xs" aria-hidden="true"></i>
|
<i class="fas fa-cart-plus text-xs" aria-hidden="true"></i>
|
||||||
Dodaj braki na dziś do listy
|
Dodaj braki na dziś do listy
|
||||||
</button>
|
</button>
|
||||||
<button type="button" id="planner-ing-add-btn" class="hidden w-full border border-[#444442] bg-[#2d2e2b] text-[#d7d2c8] hover:bg-[#3a3a37] py-2.5 rounded-xl font-semibold text-[13px] flex items-center justify-center gap-2 transition-colors">
|
<button type="button" id="planner-ing-add-btn" class="hidden w-full border border-[rgb(var(--card-strong-rgb))] bg-[rgb(var(--app-bg-rgb))] text-[rgb(var(--text-body-soft-rgb))] hover:bg-[rgb(var(--card-raised-rgb))] py-2.5 rounded-xl font-semibold text-[13px] flex items-center justify-center gap-2 transition-colors">
|
||||||
<i class="fas fa-calendar-week text-[#9b978f] text-[11px]" aria-hidden="true"></i>
|
<i class="fas fa-calendar-week text-[rgb(var(--text-dim-rgb))] text-[11px]" aria-hidden="true"></i>
|
||||||
Dodaj braki na cały tydzień
|
Dodaj braki na cały tydzień
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -469,27 +469,27 @@ function renderDayContent(state, onMealRemoved = null) {
|
|||||||
(entry.addedIngredients?.length > 0) ||
|
(entry.addedIngredients?.length > 0) ||
|
||||||
(entry.substitutions && Object.keys(entry.substitutions).length > 0);
|
(entry.substitutions && Object.keys(entry.substitutions).length > 0);
|
||||||
const customDot = hasCustom ? '<span class="w-1.5 h-1.5 rounded-full bg-amber-400 inline-block shrink-0 ml-1"></span>' : '';
|
const customDot = hasCustom ? '<span class="w-1.5 h-1.5 rounded-full bg-amber-400 inline-block shrink-0 ml-1"></span>' : '';
|
||||||
const servLabel = servings > 1 ? `<span class="mx-1.5 text-[#6d6c67]">·</span>×${servings}` : '';
|
const servLabel = servings > 1 ? `<span class="mx-1.5 text-[rgb(var(--text-subdued-rgb))]">·</span>×${servings}` : '';
|
||||||
const rowStyle = `--planner-swipe-progress:${isPendingDelete ? '1' : '0'};`;
|
const rowStyle = `--planner-swipe-progress:${isPendingDelete ? '1' : '0'};`;
|
||||||
const rowAttrs = isPendingDelete ? 'data-pending-delete="true"' : '';
|
const rowAttrs = isPendingDelete ? 'data-pending-delete="true"' : '';
|
||||||
const backgroundStyle = isPendingDelete
|
const backgroundStyle = isPendingDelete
|
||||||
? 'background:linear-gradient(90deg, rgba(65,64,60,0.08), rgba(65,64,60,0.2));'
|
? 'background:linear-gradient(90deg, rgba(var(--border-card-rgb),0.08), rgba(var(--border-card-rgb),0.2));'
|
||||||
: 'background:rgba(203,74,72, calc(0.18 + var(--planner-swipe-progress) * 0.5));';
|
: 'background:rgba(var(--danger-rgb), calc(0.18 + var(--planner-swipe-progress) * 0.5));';
|
||||||
const backgroundLabel = isPendingDelete
|
const backgroundLabel = isPendingDelete
|
||||||
? `<span class="inline-flex items-center gap-1.5 text-[11px] font-semibold tracking-wide uppercase" style="color:rgba(210,204,194,0.42);">
|
? `<span class="inline-flex items-center gap-1.5 text-[11px] font-semibold tracking-wide uppercase" style="color:rgba(var(--text-body-soft-rgb),0.42);">
|
||||||
<i class="fas fa-hourglass-half text-[10px]" aria-hidden="true"></i>
|
<i class="fas fa-hourglass-half text-[10px]" aria-hidden="true"></i>
|
||||||
Usuwanie
|
Usuwanie
|
||||||
</span>`
|
</span>`
|
||||||
: `<span class="inline-flex items-center gap-1.5 text-[11px] font-semibold tracking-wide uppercase" style="color:rgba(250,234,234, calc(0.55 + var(--planner-swipe-progress) * 0.45));">
|
: `<span class="inline-flex items-center gap-1.5 text-[11px] font-semibold tracking-wide uppercase" style="color:rgba(var(--text-emphasis-rgb), calc(0.55 + var(--planner-swipe-progress) * 0.45));">
|
||||||
<i class="fas fa-trash text-[10px]" aria-hidden="true"></i>
|
<i class="fas fa-trash text-[10px]" aria-hidden="true"></i>
|
||||||
Usuń
|
Usuń
|
||||||
</span>`;
|
</span>`;
|
||||||
const titleClass = isPendingDelete
|
const titleClass = isPendingDelete
|
||||||
? 'text-[13px] font-normal text-[#bcb5ab] truncate'
|
? 'text-[13px] font-normal text-[rgb(var(--text-muted-rgb))] truncate'
|
||||||
: 'text-[13px] font-normal text-[#ddd6ca] truncate';
|
: 'text-[13px] font-normal text-[rgb(var(--text-body-rgb))] truncate';
|
||||||
const metaClass = isPendingDelete
|
const metaClass = isPendingDelete
|
||||||
? 'text-[11px] text-[#878079] mt-0.5 tabular-nums'
|
? 'text-[11px] text-[rgb(var(--text-faint-rgb))] mt-0.5 tabular-nums'
|
||||||
: 'text-[11px] text-[#9b978f] mt-0.5 tabular-nums';
|
: 'text-[11px] text-[rgb(var(--text-dim-rgb))] mt-0.5 tabular-nums';
|
||||||
const actionWrapClass = isPendingDelete
|
const actionWrapClass = isPendingDelete
|
||||||
? 'relative z-[2] flex items-center shrink-0 self-center'
|
? 'relative z-[2] flex items-center shrink-0 self-center'
|
||||||
: 'flex items-center gap-1 shrink-0 self-center';
|
: 'flex items-center gap-1 shrink-0 self-center';
|
||||||
@@ -501,11 +501,11 @@ function renderDayContent(state, onMealRemoved = null) {
|
|||||||
: 0;
|
: 0;
|
||||||
const entryAction = isPendingDelete
|
const entryAction = isPendingDelete
|
||||||
? `<button type="button" class="planner-cancel-pending-remove rounded-full p-[1.5px] transition-transform hover:scale-[1.02] active:scale-[0.98]" style="background:${getPendingMealRemovalButtonStyle(remainingProgress)};" data-pending-delete-progress data-day-key="${selectedDayKey}" data-slot-id="${slot.id}" data-entry-id="${eid}" aria-label="Anuluj usunięcie posiłku">
|
? `<button type="button" class="planner-cancel-pending-remove rounded-full p-[1.5px] transition-transform hover:scale-[1.02] active:scale-[0.98]" style="background:${getPendingMealRemovalButtonStyle(remainingProgress)};" data-pending-delete-progress data-day-key="${selectedDayKey}" data-slot-id="${slot.id}" data-entry-id="${eid}" aria-label="Anuluj usunięcie posiłku">
|
||||||
<span class="flex h-7 w-7 items-center justify-center rounded-full bg-[#343530] text-[#e2ddd4] shadow-[0_1px_2px_rgba(0,0,0,0.28)]">
|
<span class="flex h-7 w-7 items-center justify-center rounded-full bg-[rgb(var(--card-raised-rgb))] text-[rgb(var(--text-body-rgb))] shadow-[0_1px_2px_rgba(0,0,0,0.28)]">
|
||||||
<i class="fas fa-rotate-left text-[10px]" aria-hidden="true"></i>
|
<i class="fas fa-rotate-left text-[10px]" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
</button>`
|
</button>`
|
||||||
: `<button type="button" class="planner-edit-meal w-6 h-6 rounded-full border border-[#444442] text-[#9b978f] hover:text-[#ddd6ca] hover:border-[#6d6c67] hover:bg-[#3a3a37] flex items-center justify-center transition-colors" data-slot-id="${slot.id}" data-entry-id="${eid}" aria-label="Edytuj ten przepis">
|
: `<button type="button" class="planner-edit-meal w-6 h-6 rounded-full border border-[rgb(var(--card-strong-rgb))] text-[rgb(var(--text-dim-rgb))] hover:text-[rgb(var(--text-body-rgb))] hover:border-[rgb(var(--text-subdued-rgb))] hover:bg-[rgb(var(--card-raised-rgb))] flex items-center justify-center transition-colors" data-slot-id="${slot.id}" data-entry-id="${eid}" aria-label="Edytuj ten przepis">
|
||||||
<i class="fas fa-pencil text-[9px]" aria-hidden="true"></i>
|
<i class="fas fa-pencil text-[9px]" aria-hidden="true"></i>
|
||||||
</button>`;
|
</button>`;
|
||||||
return `
|
return `
|
||||||
@@ -513,10 +513,10 @@ function renderDayContent(state, onMealRemoved = null) {
|
|||||||
<div class="pointer-events-none absolute inset-0 flex items-center justify-end px-4" style="${backgroundStyle}">
|
<div class="pointer-events-none absolute inset-0 flex items-center justify-end px-4" style="${backgroundStyle}">
|
||||||
${backgroundLabel}
|
${backgroundLabel}
|
||||||
</div>
|
</div>
|
||||||
<div class="relative z-[1] rounded-lg p-2 planner-open-recipe cursor-pointer" style="background:${isPendingDelete ? 'rgba(45,45,43,0.76)' : '#2d2e2b'}; box-shadow:inset 0 1px 3px rgba(0,0,0,0.3); transform:${isPendingDelete ? 'translateX(0) scale(0.988)' : 'translateX(0)'}; transition:transform 180ms cubic-bezier(0.22, 1, 0.36, 1), opacity 180ms ease, background-color 180ms ease; touch-action:pan-y; opacity:1;" data-planner-swipe-card data-slot-id="${slot.id}" data-entry-id="${eid}" data-recipe-id="${escapeHtml(recipe.id)}">
|
<div class="relative z-[1] rounded-lg p-2 planner-open-recipe cursor-pointer" style="background:${isPendingDelete ? 'rgba(var(--app-bg-rgb),0.76)' : 'rgb(var(--app-bg-rgb))'}; box-shadow:inset 0 1px 3px rgba(0,0,0,0.3); transform:${isPendingDelete ? 'translateX(0) scale(0.988)' : 'translateX(0)'}; transition:transform 180ms cubic-bezier(0.22, 1, 0.36, 1), opacity 180ms ease, background-color 180ms ease; touch-action:pan-y; opacity:1;" data-planner-swipe-card data-slot-id="${slot.id}" data-entry-id="${eid}" data-recipe-id="${escapeHtml(recipe.id)}">
|
||||||
<div class="relative flex items-start justify-between gap-2">
|
<div class="relative flex items-start justify-between gap-2">
|
||||||
<div class="flex items-center gap-2 min-w-0" style="${contentToneStyle}">
|
<div class="flex items-center gap-2 min-w-0" style="${contentToneStyle}">
|
||||||
<div class="w-8 h-8 rounded-lg bg-[#3a3a37] overflow-hidden shrink-0">
|
<div class="w-8 h-8 rounded-lg bg-[rgb(var(--card-raised-rgb))] overflow-hidden shrink-0">
|
||||||
${recipe.image
|
${recipe.image
|
||||||
? `<img src="${escapeHtml(recipe.image)}" alt="" class="w-full h-full object-cover">`
|
? `<img src="${escapeHtml(recipe.image)}" alt="" class="w-full h-full object-cover">`
|
||||||
: `<span class="w-full h-full flex items-center justify-center text-white text-[8px] font-medium">${escapeHtml(recipe.thumbLabel)}</span>`}
|
: `<span class="w-full h-full flex items-center justify-center text-white text-[8px] font-medium">${escapeHtml(recipe.thumbLabel)}</span>`}
|
||||||
@@ -524,9 +524,9 @@ function renderDayContent(state, onMealRemoved = null) {
|
|||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<div class="flex items-center"><p class="${titleClass}">${escapeHtml(recipe.title)}</p>${customDot}</div>
|
<div class="flex items-center"><p class="${titleClass}">${escapeHtml(recipe.title)}</p>${customDot}</div>
|
||||||
<p class="${metaClass}">
|
<p class="${metaClass}">
|
||||||
<i class="fas fa-clock text-[#7d7a74] mr-0.5" aria-hidden="true"></i>${recipe.minutes} min
|
<i class="fas fa-clock text-[rgb(var(--text-faint-rgb))] mr-0.5" aria-hidden="true"></i>${recipe.minutes} min
|
||||||
<span class="mx-1.5 text-[#6d6c67]">·</span>
|
<span class="mx-1.5 text-[rgb(var(--text-subdued-rgb))]">·</span>
|
||||||
<i class="fas fa-fire text-[#7d7a74] mr-0.5" aria-hidden="true"></i>${entryN.kcal} kcal${servLabel}
|
<i class="fas fa-fire text-[rgb(var(--text-faint-rgb))] mr-0.5" aria-hidden="true"></i>${entryN.kcal} kcal${servLabel}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -538,36 +538,36 @@ function renderDayContent(state, onMealRemoved = null) {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
const addBtn = `<button type="button" class="planner-add-meal w-7 h-7 rounded-full border border-[#444442] text-[#9b978f] flex items-center justify-center shrink-0" data-slot-id="${slot.id}" aria-label="Dodaj przepis"><i class="fas fa-plus text-[10px]"></i></button>`;
|
const addBtn = `<button type="button" class="planner-add-meal w-7 h-7 rounded-full border border-[rgb(var(--card-strong-rgb))] text-[rgb(var(--text-dim-rgb))] flex items-center justify-center shrink-0" data-slot-id="${slot.id}" aria-label="Dodaj przepis"><i class="fas fa-plus text-[10px]"></i></button>`;
|
||||||
|
|
||||||
const kcalPill = slotKcal > 0
|
const kcalPill = slotKcal > 0
|
||||||
? `<span class="text-[10px] font-semibold tabular-nums shrink-0 px-2 py-0.5 rounded-full" style="background:#2d2e2b; color:#d7d2c8;">${slotKcal} kcal</span>`
|
? `<span class="text-[10px] font-semibold tabular-nums shrink-0 px-2 py-0.5 rounded-full" style="background:rgb(var(--app-bg-rgb)); color:rgb(var(--text-body-soft-rgb));">${slotKcal} kcal</span>`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
const filledCard = `
|
const filledCard = `
|
||||||
<div class="rounded-xl bg-[#393937] overflow-hidden" style="background:#393937 !important; box-shadow:0 2px 8px rgba(0,0,0,0.25);" data-slot-id="${slot.id}">
|
<div class="rounded-xl bg-[rgb(var(--card-rgb))] overflow-hidden" style="background:rgb(var(--card-rgb)) !important; box-shadow:0 2px 8px rgba(0,0,0,0.25);" data-slot-id="${slot.id}">
|
||||||
<div class="flex items-center gap-2 px-3 py-2.5 bg-[#393937]" style="background:#393937 !important;">
|
<div class="flex items-center gap-2 px-3 py-2.5 bg-[rgb(var(--card-rgb))]" style="background:rgb(var(--card-rgb)) !important;">
|
||||||
<i class="fas ${slot.icon} w-7 text-center text-[13px] text-[#9b978f] shrink-0" aria-hidden="true"></i>
|
<i class="fas ${slot.icon} w-7 text-center text-[13px] text-[rgb(var(--text-dim-rgb))] shrink-0" aria-hidden="true"></i>
|
||||||
<span class="text-[13px] font-semibold text-[#ddd6ca] truncate min-w-0">${slot.label}</span>
|
<span class="text-[13px] font-semibold text-[rgb(var(--text-body-rgb))] truncate min-w-0">${slot.label}</span>
|
||||||
<span class="ml-auto"></span>
|
<span class="ml-auto"></span>
|
||||||
${kcalPill}
|
${kcalPill}
|
||||||
${addBtn}
|
${addBtn}
|
||||||
</div>
|
</div>
|
||||||
${entries.length > 0 ? `<div class="px-2.5 pb-2.5 space-y-2 border-t border-[#444442]" style="padding-top:0.625rem;">${entryCards}</div>` : ''}
|
${entries.length > 0 ? `<div class="px-2.5 pb-2.5 space-y-2 border-t border-[rgb(var(--card-strong-rgb))]" style="padding-top:0.625rem;">${entryCards}</div>` : ''}
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
if (entries.length > 0) return filledCard;
|
if (entries.length > 0) return filledCard;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="rounded-xl bg-[#393937] overflow-hidden" style="background:#393937 !important; box-shadow:0 2px 8px rgba(0,0,0,0.25);" data-slot-id="${slot.id}">
|
<div class="rounded-xl bg-[rgb(var(--card-rgb))] overflow-hidden" style="background:rgb(var(--card-rgb)) !important; box-shadow:0 2px 8px rgba(0,0,0,0.25);" data-slot-id="${slot.id}">
|
||||||
<div class="flex items-center gap-2 px-3 py-2.5">
|
<div class="flex items-center gap-2 px-3 py-2.5">
|
||||||
<i class="fas ${slot.icon} w-7 text-center text-[13px] text-[#9b978f] shrink-0" aria-hidden="true"></i>
|
<i class="fas ${slot.icon} w-7 text-center text-[13px] text-[rgb(var(--text-dim-rgb))] shrink-0" aria-hidden="true"></i>
|
||||||
<span class="text-[13px] font-semibold text-[#ddd6ca] truncate min-w-0">${slot.label}</span>
|
<span class="text-[13px] font-semibold text-[rgb(var(--text-body-rgb))] truncate min-w-0">${slot.label}</span>
|
||||||
<span class="ml-auto"></span>
|
<span class="ml-auto"></span>
|
||||||
${addBtn}
|
${addBtn}
|
||||||
</div>
|
</div>
|
||||||
<div class="px-3 pb-2.5 -mt-0.5">
|
<div class="px-3 pb-2.5 -mt-0.5">
|
||||||
<p class="text-[11px] text-[#7d7a74] italic pl-9">Zaplanuj posiłek</p>
|
<p class="text-[11px] text-[rgb(var(--text-faint-rgb))] italic pl-9">Zaplanuj posiłek</p>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
@@ -594,7 +594,7 @@ function getPendingMealRemovalProgress(state, dayKey, slotId, entryId) {
|
|||||||
function getPendingMealRemovalButtonStyle(progress) {
|
function getPendingMealRemovalButtonStyle(progress) {
|
||||||
const clamped = Math.max(0, Math.min(1, progress));
|
const clamped = Math.max(0, Math.min(1, progress));
|
||||||
const angle = Math.round(clamped * 360);
|
const angle = Math.round(clamped * 360);
|
||||||
return `conic-gradient(from -90deg, rgba(229,223,214,0.96) 0deg, rgba(229,223,214,0.96) ${angle}deg, rgba(109,108,103,0.24) ${angle}deg, rgba(109,108,103,0.24) 360deg)`;
|
return `conic-gradient(from -90deg, rgba(var(--text-body-rgb),0.96) 0deg, rgba(var(--text-body-rgb),0.96) ${angle}deg, rgba(var(--text-subdued-rgb),0.24) ${angle}deg, rgba(var(--text-subdued-rgb),0.24) 360deg)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopPendingMealRemovalTicker(state) {
|
function stopPendingMealRemovalTicker(state) {
|
||||||
@@ -970,7 +970,7 @@ function renderIngredientsSheet(state) {
|
|||||||
if (subEl) subEl.textContent = 'Porównanie potrzeb z zapasami w spiżarni.';
|
if (subEl) subEl.textContent = 'Porównanie potrzeb z zapasami w spiżarni.';
|
||||||
|
|
||||||
if (!today || today.items.length === 0) {
|
if (!today || today.items.length === 0) {
|
||||||
body.innerHTML = '<p class="text-sm text-[#9b978f] text-center py-8">Najpierw zaplanuj posiłki.</p>';
|
body.innerHTML = '<p class="text-sm text-[rgb(var(--text-dim-rgb))] text-center py-8">Najpierw zaplanuj posiłki.</p>';
|
||||||
updateIngButtons(state);
|
updateIngButtons(state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -980,8 +980,8 @@ function renderIngredientsSheet(state) {
|
|||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
if (shortItems.length === 0) {
|
if (shortItems.length === 0) {
|
||||||
html += `<div class="rounded-xl bg-[#2d2e2b] border border-emerald-400/40 p-3 mb-4 flex items-center gap-2.5">
|
html += `<div class="rounded-xl bg-[rgb(var(--app-bg-rgb))] border border-emerald-400/40 p-3 mb-4 flex items-center gap-2.5">
|
||||||
<div class="w-8 h-8 rounded-full bg-[#24352a] flex items-center justify-center shrink-0">
|
<div class="w-8 h-8 rounded-full bg-[rgba(var(--success-rgb), 0.14)] flex items-center justify-center shrink-0">
|
||||||
<i class="fas fa-check text-emerald-600 text-sm"></i>
|
<i class="fas fa-check text-emerald-600 text-sm"></i>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -990,8 +990,8 @@ function renderIngredientsSheet(state) {
|
|||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
} else {
|
} else {
|
||||||
html += `<div class="rounded-xl bg-[#2d2e2b] border border-red-300/40 p-3 mb-4 flex items-center gap-2.5">
|
html += `<div class="rounded-xl bg-[rgb(var(--app-bg-rgb))] border border-red-300/40 p-3 mb-4 flex items-center gap-2.5">
|
||||||
<div class="w-8 h-8 rounded-full bg-[#3a2326] flex items-center justify-center shrink-0">
|
<div class="w-8 h-8 rounded-full bg-[rgba(var(--danger-rgb), 0.14)] flex items-center justify-center shrink-0">
|
||||||
<i class="fas fa-exclamation text-red-500 text-sm"></i>
|
<i class="fas fa-exclamation text-red-500 text-sm"></i>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -1006,15 +1006,15 @@ function renderIngredientsSheet(state) {
|
|||||||
<p class="text-[10px] font-bold text-red-400 uppercase tracking-wider mb-2 px-0.5">
|
<p class="text-[10px] font-bold text-red-400 uppercase tracking-wider mb-2 px-0.5">
|
||||||
<i class="fas fa-cart-shopping text-[9px] mr-1"></i>Do kupienia
|
<i class="fas fa-cart-shopping text-[9px] mr-1"></i>Do kupienia
|
||||||
</p>
|
</p>
|
||||||
<ul class="border border-red-300/30 rounded-xl overflow-hidden bg-[#2d2e2b] divide-y divide-[#3a2326]">
|
<ul class="border border-red-300/30 rounded-xl overflow-hidden bg-[rgb(var(--app-bg-rgb))] divide-y divide-[rgba(var(--danger-rgb), 0.14)]">
|
||||||
${shortItems.map((ing) => `
|
${shortItems.map((ing) => `
|
||||||
<li class="flex items-start gap-3 py-3 px-3">
|
<li class="flex items-start gap-3 py-3 px-3">
|
||||||
<div class="w-2 h-2 rounded-full bg-red-400 mt-1.5 shrink-0"></div>
|
<div class="w-2 h-2 rounded-full bg-red-400 mt-1.5 shrink-0"></div>
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<p class="text-[13px] font-semibold text-[#ddd6ca]">${escapeHtml(ing.name)}</p>
|
<p class="text-[13px] font-semibold text-[rgb(var(--text-body-rgb))]">${escapeHtml(ing.name)}</p>
|
||||||
<p class="text-[11px] text-[#9b978f] mt-0.5">
|
<p class="text-[11px] text-[rgb(var(--text-dim-rgb))] mt-0.5">
|
||||||
potrzeba <span class="font-medium text-[#d7d2c8]">${formatAmount(ing.amount)} ${escapeHtml(ing.pantryUnit)}</span>
|
potrzeba <span class="font-medium text-[rgb(var(--text-body-soft-rgb))]">${formatAmount(ing.amount)} ${escapeHtml(ing.pantryUnit)}</span>
|
||||||
<span class="mx-1 text-[#6d6c67]">·</span>
|
<span class="mx-1 text-[rgb(var(--text-subdued-rgb))]">·</span>
|
||||||
w spiżarni <span class="font-medium ${ing.pantryQty > 0 ? 'text-amber-600' : 'text-gray-400'}">${ing.pantryQty > 0 ? formatAmount(ing.pantryQty) + ' ' + escapeHtml(ing.pantryUnit) : 'brak'}</span>
|
w spiżarni <span class="font-medium ${ing.pantryQty > 0 ? 'text-amber-600' : 'text-gray-400'}">${ing.pantryQty > 0 ? formatAmount(ing.pantryQty) + ' ' + escapeHtml(ing.pantryUnit) : 'brak'}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -1032,15 +1032,15 @@ function renderIngredientsSheet(state) {
|
|||||||
<p class="text-[10px] font-bold text-emerald-500 uppercase tracking-wider mb-2 px-0.5">
|
<p class="text-[10px] font-bold text-emerald-500 uppercase tracking-wider mb-2 px-0.5">
|
||||||
<i class="fas fa-check text-[9px] mr-1"></i>W spiżarni
|
<i class="fas fa-check text-[9px] mr-1"></i>W spiżarni
|
||||||
</p>
|
</p>
|
||||||
<ul class="border border-[#444442] rounded-xl overflow-hidden bg-[#2d2e2b] divide-y divide-[#353632]">
|
<ul class="border border-[rgb(var(--card-strong-rgb))] rounded-xl overflow-hidden bg-[rgb(var(--app-bg-rgb))] divide-y divide-[rgb(var(--card-raised-rgb))]">
|
||||||
${okItems.map((ing) => `
|
${okItems.map((ing) => `
|
||||||
<li class="flex items-start gap-3 py-2.5 px-3">
|
<li class="flex items-start gap-3 py-2.5 px-3">
|
||||||
<div class="w-2 h-2 rounded-full bg-emerald-400 mt-1.5 shrink-0"></div>
|
<div class="w-2 h-2 rounded-full bg-emerald-400 mt-1.5 shrink-0"></div>
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<p class="text-[13px] font-medium text-[#d7d2c8]">${escapeHtml(ing.name)}</p>
|
<p class="text-[13px] font-medium text-[rgb(var(--text-body-soft-rgb))]">${escapeHtml(ing.name)}</p>
|
||||||
<p class="text-[11px] text-[#9b978f] mt-0.5">
|
<p class="text-[11px] text-[rgb(var(--text-dim-rgb))] mt-0.5">
|
||||||
potrzeba <span class="font-medium text-[#d7d2c8]">${formatAmount(ing.amount)} ${escapeHtml(ing.pantryUnit)}</span>
|
potrzeba <span class="font-medium text-[rgb(var(--text-body-soft-rgb))]">${formatAmount(ing.amount)} ${escapeHtml(ing.pantryUnit)}</span>
|
||||||
<span class="mx-1 text-[#6d6c67]">·</span>
|
<span class="mx-1 text-[rgb(var(--text-subdued-rgb))]">·</span>
|
||||||
masz <span class="font-medium text-emerald-600">${formatAmount(ing.pantryQty)} ${escapeHtml(ing.pantryUnit)}</span>
|
masz <span class="font-medium text-emerald-600">${formatAmount(ing.pantryQty)} ${escapeHtml(ing.pantryUnit)}</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -1059,7 +1059,7 @@ function renderIngredientsSheet(state) {
|
|||||||
const wd = WEEKDAYS_LONG[day.date.getDay()];
|
const wd = WEEKDAYS_LONG[day.date.getDay()];
|
||||||
const label = `${wd}, ${day.date.getDate()} ${CALENDAR_MONTHS_SHORT[day.date.getMonth()]}`;
|
const label = `${wd}, ${day.date.getDate()} ${CALENDAR_MONTHS_SHORT[day.date.getMonth()]}`;
|
||||||
const shorts = day.items.filter((it) => !it.enough);
|
const shorts = day.items.filter((it) => !it.enough);
|
||||||
return `<div class="rounded-xl border border-amber-200/80 bg-[#2d2e2b] p-3">
|
return `<div class="rounded-xl border border-amber-200/80 bg-[rgb(var(--app-bg-rgb))] p-3">
|
||||||
<p class="text-[12px] font-semibold text-amber-900">
|
<p class="text-[12px] font-semibold text-amber-900">
|
||||||
<i class="fas fa-calendar-day text-[10px] mr-1.5 text-amber-500"></i>${escapeHtml(label)}
|
<i class="fas fa-calendar-day text-[10px] mr-1.5 text-amber-500"></i>${escapeHtml(label)}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ function getActivePantryFilterCount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function filterChipStyle(active) {
|
function filterChipStyle(active) {
|
||||||
const background = active ? '#393937' : '#2d2e2b';
|
const background = active ? 'rgb(var(--card-rgb))' : 'rgb(var(--app-bg-rgb))';
|
||||||
const color = active ? '#f2efe8' : '#d7d2c8';
|
const color = active ? 'rgb(var(--text-emphasis-rgb))' : 'rgb(var(--text-body-soft-rgb))';
|
||||||
const borderRule = active ? 'border:1px solid #787876;' : 'border:none;';
|
const borderRule = active ? 'border:1px solid rgb(var(--border-input-rgb));' : 'border:none;';
|
||||||
const shadow = active
|
const shadow = active
|
||||||
? 'box-shadow:inset 0 1px 0 rgba(255,255,255,0.04), 0 0 0 1px rgba(0,0,0,0.08);'
|
? 'box-shadow:inset 0 1px 0 rgba(255,255,255,0.04), 0 0 0 1px rgba(0,0,0,0.08);'
|
||||||
: '';
|
: '';
|
||||||
@@ -81,20 +81,20 @@ const MONTHS_SHORT = ['sty', 'lut', 'mar', 'kwi', 'maj', 'cze', 'lip', 'sie', 'w
|
|||||||
const SEARCH_SHELL_SHADOW = '0 5px 10px rgba(0,0,0,0.16), 0 14px 22px rgba(0,0,0,0.24), 0 22px 34px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.04)';
|
const SEARCH_SHELL_SHADOW = '0 5px 10px rgba(0,0,0,0.16), 0 14px 22px rgba(0,0,0,0.24), 0 22px 34px rgba(0,0,0,0.18), inset 0 1px 0 rgba(255,255,255,0.04)';
|
||||||
const DEFAULT_HORIZON_DAYS = 7;
|
const DEFAULT_HORIZON_DAYS = 7;
|
||||||
const PANTRY_CALENDAR_DAY_ATTR = 'data-pantry-calendar-day';
|
const PANTRY_CALENDAR_DAY_ATTR = 'data-pantry-calendar-day';
|
||||||
const SHORTFALL_ACCENT = '#CB4A48';
|
const SHORTFALL_ACCENT = 'rgb(var(--danger-rgb))';
|
||||||
const PANTRY_CALENDAR_THEME = {
|
const PANTRY_CALENDAR_THEME = {
|
||||||
bg: '#272622',
|
bg: 'rgb(var(--app-bg-rgb))',
|
||||||
border: '#34312c',
|
border: 'rgb(var(--card-raised-rgb))',
|
||||||
text: '#d7d2c8',
|
text: 'rgb(var(--text-body-soft-rgb))',
|
||||||
dimText: '#888278',
|
dimText: 'rgb(var(--text-faint-rgb))',
|
||||||
dimOpacity: 0.58,
|
dimOpacity: 0.58,
|
||||||
dimmedBg: 'transparent',
|
dimmedBg: 'transparent',
|
||||||
dimmedBorder: 'transparent',
|
dimmedBorder: 'transparent',
|
||||||
dot: '#7d7a74',
|
dot: 'rgb(var(--text-faint-rgb))',
|
||||||
selectedBg: '#393937',
|
selectedBg: 'rgb(var(--card-rgb))',
|
||||||
selectedBorder: '#787876',
|
selectedBorder: 'rgb(var(--border-input-rgb))',
|
||||||
selectedText: '#f2efe8',
|
selectedText: 'rgb(var(--text-emphasis-rgb))',
|
||||||
selectedDot: '#f2efe8',
|
selectedDot: 'rgb(var(--text-emphasis-rgb))',
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ── state ── */
|
/* ── state ── */
|
||||||
@@ -162,7 +162,7 @@ function photoStripMedia(image, icon, accentBg) {
|
|||||||
<img src="${esc(image)}" alt="" class="absolute inset-0 w-full h-full object-cover">
|
<img src="${esc(image)}" alt="" class="absolute inset-0 w-full h-full object-cover">
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
return `<div class="w-[4.5rem] shrink-0 flex items-center justify-center self-stretch" style="background:#333331;">
|
return `<div class="w-[4.5rem] shrink-0 flex items-center justify-center self-stretch" style="background:rgb(var(--card-raised-rgb));">
|
||||||
<i class="fas ${icon} text-[22px]" style="color:rgba(255,255,255,0.10);"></i>
|
<i class="fas ${icon} text-[22px]" style="color:rgba(255,255,255,0.10);"></i>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
@@ -171,32 +171,32 @@ function photoStripMedia(image, icon, accentBg) {
|
|||||||
|
|
||||||
export function getPantryHTML() {
|
export function getPantryHTML() {
|
||||||
return `
|
return `
|
||||||
<div id="pantry-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden z-10" style="background:#2d2e2b !important;">
|
<div id="pantry-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden z-10" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
|
|
||||||
<!-- ── floating top bar ── -->
|
<!-- ── floating top bar ── -->
|
||||||
<div id="pantry-topbar-outer" class="pointer-events-none absolute inset-x-0 top-0 z-[12] px-4 pt-4 pb-4" style="background:#2d2e2b !important; border:none !important;">
|
<div id="pantry-topbar-outer" class="pointer-events-none absolute inset-x-0 top-0 z-[12] px-4 pt-4 pb-4" style="background:rgb(var(--app-bg-rgb)) !important; border:none !important;">
|
||||||
<div class="pointer-events-auto relative z-[1] w-full">
|
<div class="pointer-events-auto relative z-[1] w-full">
|
||||||
<div id="pantry-topbar" class="relative min-h-12">
|
<div id="pantry-topbar" class="relative min-h-12">
|
||||||
<div id="pantry-default-row" class="flex min-h-12 items-center gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
|
<div id="pantry-default-row" class="flex min-h-12 items-center gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
|
||||||
<h1 class="flex-1 min-w-0 truncate" style="margin:0;padding:0;color:#f2efe8;font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Zapasy</h1>
|
<h1 class="flex-1 min-w-0 truncate" style="margin:0;padding:0;color:rgb(var(--text-emphasis-rgb));font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Zapasy</h1>
|
||||||
|
|
||||||
<div id="pantry-horizon-wrap" class="relative shrink">
|
<div id="pantry-horizon-wrap" class="relative shrink">
|
||||||
<button type="button" id="pantry-horizon-compact" class="min-w-0 max-w-[12rem] h-10 rounded-full flex items-center gap-1.5 px-2.5 transition-all" style="background:#393937 !important; border:1px solid #41423f !important; box-shadow:${SEARCH_SHELL_SHADOW} !important;">
|
<button type="button" id="pantry-horizon-compact" class="min-w-0 max-w-[12rem] h-10 rounded-full flex items-center gap-1.5 px-2.5 transition-all" style="background:rgb(var(--card-rgb)) !important; border:1px solid rgb(var(--border-card-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important;">
|
||||||
<span id="pantry-horizon-compact-label" class="min-w-0 flex-1 text-left text-[13px] font-normal truncate" style="color:#ddd6ca;"></span>
|
<span id="pantry-horizon-compact-label" class="min-w-0 flex-1 text-left text-[13px] font-normal truncate" style="color:rgb(var(--text-body-rgb));"></span>
|
||||||
<i id="pantry-horizon-chevron" class="fas fa-chevron-down text-[10px] shrink-0 transition-transform duration-200" style="color:#9b978f;"></i>
|
<i id="pantry-horizon-chevron" class="fas fa-chevron-down text-[10px] shrink-0 transition-transform duration-200" style="color:rgb(var(--text-dim-rgb));"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pantry-filter-wrap" class="relative shrink-0">
|
<div id="pantry-filter-wrap" class="relative shrink-0">
|
||||||
<button type="button" id="pantry-filter-toggle" class="relative w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:#393937; border:1px solid #41423f; box-shadow:${SEARCH_SHELL_SHADOW}; color:#ddd6ca;">
|
<button type="button" id="pantry-filter-toggle" class="relative w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:rgb(var(--card-rgb)); border:1px solid rgb(var(--border-card-rgb)); box-shadow:${SEARCH_SHELL_SHADOW}; color:rgb(var(--text-body-rgb));">
|
||||||
<i class="fas fa-sliders-h text-[12px]"></i>
|
<i class="fas fa-sliders-h text-[12px]"></i>
|
||||||
<span id="pantry-filter-count" class="hidden absolute -top-1 -right-1 min-w-[1.1rem] h-[1.1rem] px-1 rounded-full text-[9px] font-bold leading-none items-center justify-center" style="background:#23221e; border:1px solid #787876; color:#f2efe8;"></span>
|
<span id="pantry-filter-count" class="hidden absolute -top-1 -right-1 min-w-[1.1rem] h-[1.1rem] px-1 rounded-full text-[9px] font-bold leading-none items-center justify-center" style="background:rgb(var(--sunken-rgb)); border:1px solid rgb(var(--border-input-rgb)); color:rgb(var(--text-emphasis-rgb));"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div id="pantry-filter-popover" class="absolute right-0 top-full mt-2 w-[19rem] max-w-[calc(100vw-2rem)] rounded-[1.35rem] px-3 py-3 transition-all duration-200 pointer-events-none" style="background:#23221e !important; border:1px solid #787876 !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-6px) scale(0.98);">
|
<div id="pantry-filter-popover" class="absolute right-0 top-full mt-2 w-[19rem] max-w-[calc(100vw-2rem)] rounded-[1.35rem] px-3 py-3 transition-all duration-200 pointer-events-none" style="background:rgb(var(--sunken-rgb)) !important; border:1px solid rgb(var(--border-input-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-6px) scale(0.98);">
|
||||||
<div class="flex items-center justify-between gap-3 px-0.5 pb-3">
|
<div class="flex items-center justify-between gap-3 px-0.5 pb-3">
|
||||||
<p class="text-[11px] font-semibold leading-none" style="color:#f2efe8;">Filtry</p>
|
<p class="text-[11px] font-semibold leading-none" style="color:rgb(var(--text-emphasis-rgb));">Filtry</p>
|
||||||
<button type="button" id="pantry-filter-clear" class="h-8 px-2 rounded-full text-[11px] font-semibold transition-colors" style="background:transparent; border:none; color:#b5afa5;">
|
<button type="button" id="pantry-filter-clear" class="h-8 px-2 rounded-full text-[11px] font-semibold transition-colors" style="background:transparent; border:none; color:rgb(var(--text-muted-rgb));">
|
||||||
Wyczyść
|
Wyczyść
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -204,38 +204,38 @@ export function getPantryHTML() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" id="pantry-search-toggle" class="w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:#393937 !important; border:1px solid #41423f !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; color:#ddd6ca;">
|
<button type="button" id="pantry-search-toggle" class="w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:rgb(var(--card-rgb)) !important; border:1px solid rgb(var(--border-card-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; color:rgb(var(--text-body-rgb));">
|
||||||
<i class="fas fa-search text-[13px]"></i>
|
<i class="fas fa-search text-[13px]"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="pantry-calendar-popover" class="absolute left-0 right-0 top-full mt-2 rounded-[1.35rem] px-3 py-3 transition-all duration-200 pointer-events-none" style="background:#23221e !important; border:1px solid #787876 !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-6px) scale(0.98);">
|
<div id="pantry-calendar-popover" class="absolute left-0 right-0 top-full mt-2 rounded-[1.35rem] px-3 py-3 transition-all duration-200 pointer-events-none" style="background:rgb(var(--sunken-rgb)) !important; border:1px solid rgb(var(--border-input-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-6px) scale(0.98);">
|
||||||
${createCalendarTopbarHTML({
|
${createCalendarTopbarHTML({
|
||||||
prevId: 'pantry-cal-prev',
|
prevId: 'pantry-cal-prev',
|
||||||
todayId: 'pantry-cal-today',
|
todayId: 'pantry-cal-today',
|
||||||
nextId: 'pantry-cal-next',
|
nextId: 'pantry-cal-next',
|
||||||
wrapperClass: 'pb-3 flex items-center justify-end gap-3',
|
wrapperClass: 'pb-3 flex items-center justify-end gap-3',
|
||||||
controlsStyle: `background:${PANTRY_CALENDAR_THEME.bg};border-color:${PANTRY_CALENDAR_THEME.border};`,
|
controlsStyle: `background:${PANTRY_CALENDAR_THEME.bg};border-color:${PANTRY_CALENDAR_THEME.border};`,
|
||||||
navButtonClass: 'shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[#d7d2c8] transition-colors',
|
navButtonClass: 'shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[rgb(var(--text-body-soft-rgb))] transition-colors',
|
||||||
todayButtonActiveClass: 'h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center rounded-full bg-transparent px-1.5 text-[10px] font-semibold leading-none tabular-nums text-[#d7d2c8] active:bg-transparent whitespace-nowrap',
|
todayButtonActiveClass: 'h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center rounded-full bg-transparent px-1.5 text-[10px] font-semibold leading-none tabular-nums text-[rgb(var(--text-body-soft-rgb))] active:bg-transparent whitespace-nowrap',
|
||||||
todayButtonDimClass: 'h-full shrink-0 inline-flex items-center justify-center rounded-full px-2 text-[10px] font-semibold leading-none text-[#7d7a74] cursor-default',
|
todayButtonDimClass: 'h-full shrink-0 inline-flex items-center justify-center rounded-full px-2 text-[10px] font-semibold leading-none text-[rgb(var(--text-faint-rgb))] cursor-default',
|
||||||
})}
|
})}
|
||||||
${createCalendarWeekdayHeaderHTML(undefined, {
|
${createCalendarWeekdayHeaderHTML(undefined, {
|
||||||
wrapperClass: 'grid grid-cols-7 gap-1.5 text-center text-[8px] font-medium text-[#9b978f] uppercase tracking-wide mb-1 leading-none',
|
wrapperClass: 'grid grid-cols-7 gap-1.5 text-center text-[8px] font-medium text-[rgb(var(--text-dim-rgb))] uppercase tracking-wide mb-1 leading-none',
|
||||||
})}
|
})}
|
||||||
<div id="pantry-calendar-grid" class="grid grid-cols-7 gap-1.5"></div>
|
<div id="pantry-calendar-grid" class="grid grid-cols-7 gap-1.5"></div>
|
||||||
|
|
||||||
<div class="mt-3 pt-3 border-t" style="border-color:#444442;">
|
<div class="mt-3 pt-3 border-t" style="border-color:rgb(var(--card-strong-rgb));">
|
||||||
<p id="pantry-cal-selection" class="min-w-0 text-[11px] leading-snug" style="color:#9b978f;"></p>
|
<p id="pantry-cal-selection" class="min-w-0 text-[11px] leading-snug" style="color:rgb(var(--text-dim-rgb));"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pantry-search-shell" class="absolute inset-0 flex items-center gap-2 rounded-full px-3 transition-all duration-200 pointer-events-none" style="background:#23221e !important; border:1px solid #787876 !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-2px) scale(0.98);">
|
<div id="pantry-search-shell" class="absolute inset-0 flex items-center gap-2 rounded-full px-3 transition-all duration-200 pointer-events-none" style="background:rgb(var(--sunken-rgb)) !important; border:1px solid rgb(var(--border-input-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-2px) scale(0.98);">
|
||||||
<i class="fas fa-search text-[13px] shrink-0" style="color:#9b978f;"></i>
|
<i class="fas fa-search text-[13px] shrink-0" style="color:rgb(var(--text-dim-rgb));"></i>
|
||||||
<input type="search" id="pantry-search" autocomplete="off" placeholder="Szukaj w spiżarni…"
|
<input type="search" id="pantry-search" autocomplete="off" placeholder="Szukaj w spiżarni…"
|
||||||
class="flex-1 min-w-0 h-full bg-transparent outline-none text-[15px] leading-none py-0" style="background:transparent !important; border:none !important; box-shadow:none !important; color:#ddd6ca; margin:0;">
|
class="flex-1 min-w-0 h-full bg-transparent outline-none text-[15px] leading-none py-0" style="background:transparent !important; border:none !important; box-shadow:none !important; color:rgb(var(--text-body-rgb)); margin:0;">
|
||||||
<button type="button" id="pantry-search-close" class="w-8 h-8 rounded-full shrink-0 flex items-center justify-center transition-colors" style="background:#2f2f2d; border:none; color:#9b978f;">
|
<button type="button" id="pantry-search-close" class="w-8 h-8 rounded-full shrink-0 flex items-center justify-center transition-colors" style="background:rgb(var(--card-soft-rgb)); border:none; color:rgb(var(--text-dim-rgb));">
|
||||||
<i class="fas fa-xmark text-[13px]"></i>
|
<i class="fas fa-xmark text-[13px]"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -244,7 +244,7 @@ export function getPantryHTML() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── scrollable content ── -->
|
<!-- ── scrollable content ── -->
|
||||||
<div id="pantry-scroll" class="flex-1 overflow-y-auto no-scrollbar px-4 pt-[5.35rem] pb-24" style="background:#2d2e2b !important;">
|
<div id="pantry-scroll" class="flex-1 overflow-y-auto no-scrollbar px-4 pt-[5.35rem] pb-24" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div id="pantry-board"></div>
|
<div id="pantry-board"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -284,8 +284,8 @@ function syncHorizonUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compactPill) {
|
if (compactPill) {
|
||||||
compactPill.style.setProperty('background', showCalendar ? '#23221e' : '#393937', 'important');
|
compactPill.style.setProperty('background', showCalendar ? 'rgb(var(--sunken-rgb))' : 'rgb(var(--card-rgb))', 'important');
|
||||||
compactPill.style.setProperty('border-color', showCalendar ? '#787876' : '#41423f', 'important');
|
compactPill.style.setProperty('border-color', showCalendar ? 'rgb(var(--border-input-rgb))' : 'rgb(var(--border-card-rgb))', 'important');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popover) {
|
if (popover) {
|
||||||
@@ -304,9 +304,9 @@ function syncHorizonUI() {
|
|||||||
}
|
}
|
||||||
if (filterToggle) {
|
if (filterToggle) {
|
||||||
const isActive = showFilter || hasActivePantryFilters();
|
const isActive = showFilter || hasActivePantryFilters();
|
||||||
filterToggle.style.setProperty('background', isActive ? '#23221e' : '#393937', 'important');
|
filterToggle.style.setProperty('background', isActive ? 'rgb(var(--sunken-rgb))' : 'rgb(var(--card-rgb))', 'important');
|
||||||
filterToggle.style.setProperty('border-color', isActive ? '#787876' : '#41423f', 'important');
|
filterToggle.style.setProperty('border-color', isActive ? 'rgb(var(--border-input-rgb))' : 'rgb(var(--border-card-rgb))', 'important');
|
||||||
filterToggle.style.setProperty('color', isActive ? '#f2efe8' : '#ddd6ca', 'important');
|
filterToggle.style.setProperty('color', isActive ? 'rgb(var(--text-emphasis-rgb))' : 'rgb(var(--text-body-rgb))', 'important');
|
||||||
}
|
}
|
||||||
if (filterCount) {
|
if (filterCount) {
|
||||||
filterCount.textContent = String(activeFilterCount);
|
filterCount.textContent = String(activeFilterCount);
|
||||||
@@ -400,11 +400,11 @@ function renderFilterPopover() {
|
|||||||
|
|
||||||
body.innerHTML = `
|
body.innerHTML = `
|
||||||
<section>
|
<section>
|
||||||
<p class="text-[10px] font-bold uppercase tracking-wider mb-3 px-0.5" style="color:#b5afa5;">Kategorie</p>
|
<p class="text-[10px] font-bold uppercase tracking-wider mb-3 px-0.5" style="color:rgb(var(--text-muted-rgb));">Kategorie</p>
|
||||||
<div class="flex flex-wrap gap-2">${categoryChips}</div>
|
<div class="flex flex-wrap gap-2">${categoryChips}</div>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<p class="text-[10px] font-bold uppercase tracking-wider mb-3 px-0.5" style="color:#b5afa5;">Sekcje</p>
|
<p class="text-[10px] font-bold uppercase tracking-wider mb-3 px-0.5" style="color:rgb(var(--text-muted-rgb));">Sekcje</p>
|
||||||
<div class="flex flex-wrap gap-2">${sectionChips}</div>
|
<div class="flex flex-wrap gap-2">${sectionChips}</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
@@ -554,24 +554,24 @@ function classifyIngredients(searchQuery) {
|
|||||||
|
|
||||||
function tileIconHtml(item) {
|
function tileIconHtml(item) {
|
||||||
if (item.image) {
|
if (item.image) {
|
||||||
return `<div class="w-6 h-6 rounded-md shrink-0 overflow-hidden" style="background:#2f2f2d;"><img src="${esc(item.image)}" alt="" class="w-full h-full object-contain" style="padding:1px;"></div>`;
|
return `<div class="w-6 h-6 rounded-md shrink-0 overflow-hidden" style="background:rgb(var(--card-soft-rgb));"><img src="${esc(item.image)}" alt="" class="w-full h-full object-contain" style="padding:1px;"></div>`;
|
||||||
}
|
}
|
||||||
return `<div class="w-6 h-6 rounded-md flex items-center justify-center shrink-0" style="background:#2f2f2d;"><i class="fas ${item.icon} text-[11px]" style="color:#7d7a74;"></i></div>`;
|
return `<div class="w-6 h-6 rounded-md flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb));"><i class="fas ${item.icon} text-[11px]" style="color:rgb(var(--text-faint-rgb));"></i></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shortfallTileHtml(item) {
|
function shortfallTileHtml(item) {
|
||||||
const clamp = item.name.length > 25 ? ' min-w-0' : '';
|
const clamp = item.name.length > 25 ? ' min-w-0' : '';
|
||||||
return `
|
return `
|
||||||
<button type="button" class="pv2-tile text-left rounded-2xl flex flex-col gap-2 px-2.5 py-2${clamp} transition-all active:scale-[0.98]" style="flex:1 0 auto; min-width:6rem; max-width:100%; background:#393937; border:none; box-shadow:0 2px 8px rgba(0,0,0,0.28);" data-id="${esc(item.ingredientId)}">
|
<button type="button" class="pv2-tile text-left rounded-2xl flex flex-col gap-2 px-2.5 py-2${clamp} transition-all active:scale-[0.98]" style="flex:1 0 auto; min-width:6rem; max-width:100%; background:rgb(var(--card-rgb)); border:none; box-shadow:0 2px 8px rgba(0,0,0,0.28);" data-id="${esc(item.ingredientId)}">
|
||||||
<div class="flex items-center gap-1.5 min-w-0">
|
<div class="flex items-center gap-1.5 min-w-0">
|
||||||
${tileIconHtml(item)}
|
${tileIconHtml(item)}
|
||||||
<p class="text-[11px] font-normal leading-tight truncate min-w-0" style="color:#ddd6ca;">${esc(item.name)}</p>
|
<p class="text-[11px] font-normal leading-tight truncate min-w-0" style="color:rgb(var(--text-body-rgb));">${esc(item.name)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2">
|
<div class="w-full flex items-center gap-2">
|
||||||
<div class="flex-1 h-1 rounded-full overflow-hidden" style="background:#2a2a28;">
|
<div class="flex-1 h-1 rounded-full overflow-hidden" style="background:rgb(var(--app-bg-rgb));">
|
||||||
<div class="h-full rounded-full" style="width:${item.fillPct}%; background:${SHORTFALL_ACCENT};"></div>
|
<div class="h-full rounded-full" style="width:${item.fillPct}%; background:${SHORTFALL_ACCENT};"></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="shrink-0 text-[10px] font-semibold tabular-nums" style="color:#ddd6ca;">${esc(formatQty(item.pantryQty))}<span class="font-medium" style="color:#9b978f;">/${esc(formatQty(item.needed))} ${esc(unitLabel(item.unit))}</span></span>
|
<span class="shrink-0 text-[10px] font-semibold tabular-nums" style="color:rgb(var(--text-body-rgb));">${esc(formatQty(item.pantryQty))}<span class="font-medium" style="color:rgb(var(--text-dim-rgb));">/${esc(formatQty(item.needed))} ${esc(unitLabel(item.unit))}</span></span>
|
||||||
</div>
|
</div>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
@@ -579,16 +579,16 @@ function shortfallTileHtml(item) {
|
|||||||
function sufficientTileHtml(item) {
|
function sufficientTileHtml(item) {
|
||||||
const clamp = item.name.length > 25 ? ' min-w-0' : '';
|
const clamp = item.name.length > 25 ? ' min-w-0' : '';
|
||||||
return `
|
return `
|
||||||
<button type="button" class="pv2-tile text-left rounded-2xl flex flex-col gap-2 px-2.5 py-2${clamp} transition-all active:scale-[0.98]" style="flex:1 0 auto; min-width:6rem; max-width:100%; background:#393937; border:none; box-shadow:0 2px 8px rgba(0,0,0,0.28);" data-id="${esc(item.ingredientId)}">
|
<button type="button" class="pv2-tile text-left rounded-2xl flex flex-col gap-2 px-2.5 py-2${clamp} transition-all active:scale-[0.98]" style="flex:1 0 auto; min-width:6rem; max-width:100%; background:rgb(var(--card-rgb)); border:none; box-shadow:0 2px 8px rgba(0,0,0,0.28);" data-id="${esc(item.ingredientId)}">
|
||||||
<div class="flex items-center gap-1.5 min-w-0">
|
<div class="flex items-center gap-1.5 min-w-0">
|
||||||
${tileIconHtml(item)}
|
${tileIconHtml(item)}
|
||||||
<p class="text-[11px] font-normal leading-tight truncate min-w-0" style="color:#ddd6ca;">${esc(item.name)}</p>
|
<p class="text-[11px] font-normal leading-tight truncate min-w-0" style="color:rgb(var(--text-body-rgb));">${esc(item.name)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full flex items-center gap-2">
|
<div class="w-full flex items-center gap-2">
|
||||||
<div class="flex-1 h-1 rounded-full overflow-hidden" style="background:#2a2a28;">
|
<div class="flex-1 h-1 rounded-full overflow-hidden" style="background:rgb(var(--app-bg-rgb));">
|
||||||
<div class="h-full rounded-full" style="width:100%; background:#6ee7b7;"></div>
|
<div class="h-full rounded-full" style="width:100%; background:rgb(var(--success-rgb));"></div>
|
||||||
</div>
|
</div>
|
||||||
<span class="shrink-0 text-[10px] font-semibold tabular-nums" style="color:#6ee7b7;">${esc(formatQty(item.pantryQty))}<span class="font-medium" style="color:#9b978f;">/${esc(formatQty(item.needed))} ${esc(unitLabel(item.unit))}</span></span>
|
<span class="shrink-0 text-[10px] font-semibold tabular-nums" style="color:rgb(var(--success-rgb));">${esc(formatQty(item.pantryQty))}<span class="font-medium" style="color:rgb(var(--text-dim-rgb));">/${esc(formatQty(item.needed))} ${esc(unitLabel(item.unit))}</span></span>
|
||||||
</div>
|
</div>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
@@ -597,10 +597,10 @@ function notPlannedChipHtml(item) {
|
|||||||
const hasStock = item.qty > 0;
|
const hasStock = item.qty > 0;
|
||||||
const clamp = item.name.length > 25 ? ' min-w-0' : '';
|
const clamp = item.name.length > 25 ? ' min-w-0' : '';
|
||||||
return `
|
return `
|
||||||
<button type="button" class="pv2-tile text-left rounded-2xl flex items-center gap-1.5 px-2.5 py-2${clamp} transition-all active:scale-[0.98]" style="flex:1 0 auto; min-width:6rem; max-width:100%; background:#393937; border:none; box-shadow:0 2px 8px rgba(0,0,0,0.28);" data-id="${esc(item.ingredientId)}">
|
<button type="button" class="pv2-tile text-left rounded-2xl flex items-center gap-1.5 px-2.5 py-2${clamp} transition-all active:scale-[0.98]" style="flex:1 0 auto; min-width:6rem; max-width:100%; background:rgb(var(--card-rgb)); border:none; box-shadow:0 2px 8px rgba(0,0,0,0.28);" data-id="${esc(item.ingredientId)}">
|
||||||
${tileIconHtml(item)}
|
${tileIconHtml(item)}
|
||||||
<p class="text-[11px] font-normal leading-tight truncate min-w-0" style="color:${hasStock ? '#b7ada1' : '#9b978f'};">${esc(item.name)}</p>
|
<p class="text-[11px] font-normal leading-tight truncate min-w-0" style="color:${hasStock ? 'rgb(var(--text-muted-rgb))' : 'rgb(var(--text-dim-rgb))'};">${esc(item.name)}</p>
|
||||||
<span class="text-[10px] font-semibold tabular-nums shrink-0 ml-auto" style="color:${hasStock ? '#9b978f' : '#6d6c67'};">${esc(formatQty(item.qty))} ${esc(unitLabel(item.unit))}</span>
|
<span class="text-[10px] font-semibold tabular-nums shrink-0 ml-auto" style="color:${hasStock ? 'rgb(var(--text-dim-rgb))' : 'rgb(var(--text-subdued-rgb))'};">${esc(formatQty(item.qty))} ${esc(unitLabel(item.unit))}</span>
|
||||||
</button>`;
|
</button>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -610,7 +610,7 @@ function sectionHeaderHtml(icon, iconBg, iconColor, title, titleColor, count) {
|
|||||||
return `
|
return `
|
||||||
<div class="flex items-center gap-2 mb-2.5 px-0.5">
|
<div class="flex items-center gap-2 mb-2.5 px-0.5">
|
||||||
<span class="text-[10px] font-bold uppercase tracking-wider" style="color:${titleColor};">${esc(title)}</span>
|
<span class="text-[10px] font-bold uppercase tracking-wider" style="color:${titleColor};">${esc(title)}</span>
|
||||||
<span class="text-[10px]" style="color:#6d6c67;">${count}</span>
|
<span class="text-[10px]" style="color:rgb(var(--text-subdued-rgb));">${count}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,7 +624,7 @@ function renderBoard() {
|
|||||||
|
|
||||||
const totalVisible = shortfalls.length + sufficient.length + notPlanned.length;
|
const totalVisible = shortfalls.length + sufficient.length + notPlanned.length;
|
||||||
if (totalVisible === 0 && (q || hasFilters)) {
|
if (totalVisible === 0 && (q || hasFilters)) {
|
||||||
root.innerHTML = `<p class="text-sm text-center py-10" style="color:#9b978f;">Brak wyników — zmień filtry lub wyszukiwanie.</p>`;
|
root.innerHTML = `<p class="text-sm text-center py-10" style="color:rgb(var(--text-dim-rgb));">Brak wyników — zmień filtry lub wyszukiwanie.</p>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,7 +633,7 @@ function renderBoard() {
|
|||||||
// Section 1: Potrzebne (shortfalls)
|
// Section 1: Potrzebne (shortfalls)
|
||||||
if (shortfalls.length > 0) {
|
if (shortfalls.length > 0) {
|
||||||
html += `<section class="mb-5">`;
|
html += `<section class="mb-5">`;
|
||||||
html += sectionHeaderHtml('fa-exclamation', '#2f2f2d', SHORTFALL_ACCENT, 'Potrzebne', '#7B756D', shortfalls.length);
|
html += sectionHeaderHtml('fa-exclamation', 'rgb(var(--card-soft-rgb))', SHORTFALL_ACCENT, 'Potrzebne', 'rgb(var(--text-faint-rgb))', shortfalls.length);
|
||||||
html += `<div class="flex flex-wrap gap-2">`;
|
html += `<div class="flex flex-wrap gap-2">`;
|
||||||
html += shortfalls.sort((a, b) => a.name.length - b.name.length).map(shortfallTileHtml).join('');
|
html += shortfalls.sort((a, b) => a.name.length - b.name.length).map(shortfallTileHtml).join('');
|
||||||
html += `</div></section>`;
|
html += `</div></section>`;
|
||||||
@@ -642,7 +642,7 @@ function renderBoard() {
|
|||||||
// Section 2: W spiżarni (sufficient)
|
// Section 2: W spiżarni (sufficient)
|
||||||
if (sufficient.length > 0) {
|
if (sufficient.length > 0) {
|
||||||
html += `<section class="mb-5">`;
|
html += `<section class="mb-5">`;
|
||||||
html += sectionHeaderHtml('fa-check', '#1a2e22', '#6ee7b7', 'W spiżarni', '#7B756D', sufficient.length);
|
html += sectionHeaderHtml('fa-check', 'rgba(var(--success-rgb), 0.14)', 'rgb(var(--success-rgb))', 'W spiżarni', 'rgb(var(--text-faint-rgb))', sufficient.length);
|
||||||
html += `<div class="flex flex-wrap gap-2">`;
|
html += `<div class="flex flex-wrap gap-2">`;
|
||||||
html += sufficient.sort((a, b) => a.name.length - b.name.length).map(sufficientTileHtml).join('');
|
html += sufficient.sort((a, b) => a.name.length - b.name.length).map(sufficientTileHtml).join('');
|
||||||
html += `</div></section>`;
|
html += `</div></section>`;
|
||||||
@@ -651,7 +651,7 @@ function renderBoard() {
|
|||||||
// Section 3: Poza planem
|
// Section 3: Poza planem
|
||||||
if (notPlanned.length > 0) {
|
if (notPlanned.length > 0) {
|
||||||
html += `<section class="mb-5">`;
|
html += `<section class="mb-5">`;
|
||||||
html += sectionHeaderHtml('fa-minus', '#2a2a28', '#6d6c67', 'Poza planem', '#7B756D', notPlanned.length);
|
html += sectionHeaderHtml('fa-minus', 'rgb(var(--app-bg-rgb))', 'rgb(var(--text-subdued-rgb))', 'Poza planem', 'rgb(var(--text-faint-rgb))', notPlanned.length);
|
||||||
html += `<div class="flex flex-wrap gap-2">`;
|
html += `<div class="flex flex-wrap gap-2">`;
|
||||||
html += notPlanned.map(notPlannedChipHtml).join('');
|
html += notPlanned.map(notPlannedChipHtml).join('');
|
||||||
html += `</div></section>`;
|
html += `</div></section>`;
|
||||||
@@ -661,11 +661,11 @@ function renderBoard() {
|
|||||||
if (shortfalls.length === 0 && sufficient.length === 0 && !q && !hasFilters) {
|
if (shortfalls.length === 0 && sufficient.length === 0 && !q && !hasFilters) {
|
||||||
html = `
|
html = `
|
||||||
<div class="flex flex-col items-center justify-center py-10 text-center mb-6">
|
<div class="flex flex-col items-center justify-center py-10 text-center mb-6">
|
||||||
<div class="w-12 h-12 rounded-2xl flex items-center justify-center mb-3" style="background:#393937;">
|
<div class="w-12 h-12 rounded-2xl flex items-center justify-center mb-3" style="background:rgb(var(--card-rgb));">
|
||||||
<i class="fas fa-calendar-xmark text-lg" style="color:#6d6c67;"></i>
|
<i class="fas fa-calendar-xmark text-lg" style="color:rgb(var(--text-subdued-rgb));"></i>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[13px] font-semibold mb-1" style="color:#ddd6ca;">Brak zaplanowanych posiłków</p>
|
<p class="text-[13px] font-semibold mb-1" style="color:rgb(var(--text-body-rgb));">Brak zaplanowanych posiłków</p>
|
||||||
<p class="text-[11px] max-w-[16rem]" style="color:#9b978f;">Zaplanuj posiłki, a spiżarnia pokaże czego potrzebujesz i co masz na stanie.</p>
|
<p class="text-[11px] max-w-[16rem]" style="color:rgb(var(--text-dim-rgb));">Zaplanuj posiłki, a spiżarnia pokaże czego potrzebujesz i co masz na stanie.</p>
|
||||||
</div>` + html;
|
</div>` + html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ function escapeHtml(s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const RD_THEME = Object.freeze({
|
const RD_THEME = Object.freeze({
|
||||||
surface: '#393937',
|
surface: 'rgb(var(--card-rgb))',
|
||||||
surfaceSoft: '#2f2f2d',
|
surfaceSoft: 'rgb(var(--card-soft-rgb))',
|
||||||
surfaceActive: '#23221e',
|
surfaceActive: 'rgb(var(--sunken-rgb))',
|
||||||
border: '#444442',
|
border: 'rgb(var(--card-strong-rgb))',
|
||||||
borderSoft: '#56534f',
|
borderSoft: 'rgba(var(--border-input-rgb), 0.58)',
|
||||||
borderStrong: '#787876',
|
borderStrong: 'rgb(var(--border-input-rgb))',
|
||||||
textPrimary: '#ddd6ca',
|
textPrimary: 'rgb(var(--text-body-rgb))',
|
||||||
textSecondary: '#d7d2c8',
|
textSecondary: 'rgb(var(--text-body-soft-rgb))',
|
||||||
textMuted: '#9b978f',
|
textMuted: 'rgb(var(--text-dim-rgb))',
|
||||||
});
|
});
|
||||||
|
|
||||||
function forceBg(bg) {
|
function forceBg(bg) {
|
||||||
@@ -31,27 +31,27 @@ function forceBgBorder(bg, border) {
|
|||||||
|
|
||||||
export function getRecipeDetailHTML() {
|
export function getRecipeDetailHTML() {
|
||||||
return `
|
return `
|
||||||
<div id="recipe-detail-view" class="absolute inset-0 bg-[#2d2e2b] z-30 transition-all duration-300 ease-in-out translate-x-full opacity-0 pointer-events-none overflow-hidden" style="background:#2d2e2b !important; background-image:none !important;">
|
<div id="recipe-detail-view" class="absolute inset-0 bg-[rgb(var(--app-bg-rgb))] z-30 transition-all duration-300 ease-in-out translate-x-full opacity-0 pointer-events-none overflow-hidden" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important;">
|
||||||
<div class="absolute top-0 w-full p-3.5 flex justify-between z-40 mt-3">
|
<div class="absolute top-0 w-full p-3.5 flex justify-between z-40 mt-3">
|
||||||
<button id="rd-back-btn" onclick="closeRecipeDetail()" class="w-9 h-9 rounded-full flex items-center justify-center transition-opacity opacity-95 hover:opacity-100" style="background:rgba(57,57,55,0.93) !important; backdrop-filter:none !important; box-shadow:0 4px 9px rgba(0,0,0,0.33) !important; color:#ddd6ca !important; transition:box-shadow 180ms ease, background-color 180ms ease, opacity 180ms ease;">
|
<button id="rd-back-btn" onclick="closeRecipeDetail()" class="w-9 h-9 rounded-full flex items-center justify-center transition-opacity opacity-95 hover:opacity-100" style="background:rgba(var(--card-rgb),0.93) !important; backdrop-filter:none !important; box-shadow:0 4px 9px rgba(0,0,0,0.33) !important; color:rgb(var(--text-body-rgb)) !important; transition:box-shadow 180ms ease, background-color 180ms ease, opacity 180ms ease;">
|
||||||
<i class="fas fa-arrow-left text-[13px]"></i>
|
<i class="fas fa-arrow-left text-[13px]"></i>
|
||||||
</button>
|
</button>
|
||||||
<button id="rd-add-to-planner-btn" class="h-9 px-3 rounded-full flex items-center justify-center gap-1.5 transition-opacity opacity-95 hover:opacity-100 text-[12px] font-semibold" style="background:rgba(57,57,55,0.93) !important; backdrop-filter:none !important; box-shadow:0 3px 8px rgba(0,0,0,0.28) !important; color:#ddd6ca !important; transition:box-shadow 180ms ease, background-color 180ms ease, opacity 180ms ease;">
|
<button id="rd-add-to-planner-btn" class="h-9 px-3 rounded-full flex items-center justify-center gap-1.5 transition-opacity opacity-95 hover:opacity-100 text-[12px] font-semibold" style="background:rgba(var(--card-rgb),0.93) !important; backdrop-filter:none !important; box-shadow:0 3px 8px rgba(0,0,0,0.28) !important; color:rgb(var(--text-body-rgb)) !important; transition:box-shadow 180ms ease, background-color 180ms ease, opacity 180ms ease;">
|
||||||
<i class="fas fa-calendar-plus text-[11px]"></i> Zaplanuj
|
<i class="fas fa-calendar-plus text-[11px]"></i> Zaplanuj
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="rd-scroll-container" class="absolute inset-0 z-10 overflow-y-auto no-scrollbar" style="overscroll-behavior-y:none;">
|
<div id="rd-scroll-container" class="absolute inset-0 z-10 overflow-y-auto no-scrollbar" style="overscroll-behavior-y:none;">
|
||||||
<div id="rd-hero" class="h-[236px] w-full relative overflow-hidden" style="background:linear-gradient(180deg, #3a3937 0%, #23221e 100%) !important; will-change:height,opacity;">
|
<div id="rd-hero" class="h-[236px] w-full relative overflow-hidden" style="background:linear-gradient(180deg, rgb(var(--card-raised-rgb)) 0%, rgb(var(--sunken-rgb)) 100%) !important; will-change:height,opacity;">
|
||||||
<img id="rd-hero-img" src="" alt="" class="w-full h-full object-cover hidden" style="will-change:transform;">
|
<img id="rd-hero-img" src="" alt="" class="w-full h-full object-cover hidden" style="will-change:transform;">
|
||||||
<div class="absolute inset-0 pointer-events-none" style="background:linear-gradient(to bottom, rgba(45,46,43,0.1), rgba(45,46,43,0.4), rgba(45,46,43,0.92));"></div>
|
<div class="absolute inset-0 pointer-events-none" style="background:linear-gradient(to bottom, rgba(var(--app-bg-rgb),0.1), rgba(var(--app-bg-rgb),0.4), rgba(var(--app-bg-rgb),0.92));"></div>
|
||||||
<span id="rd-hero-label" class="absolute inset-0 z-10 flex items-center justify-center font-medium text-[15px]" style="color:#ddd6ca;"></span>
|
<span id="rd-hero-label" class="absolute inset-0 z-10 flex items-center justify-center font-medium text-[15px]" style="color:rgb(var(--text-body-rgb));"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="rd-content-body" class="bg-[#2d2e2b] rounded-t-3xl -mt-6 relative z-30 pt-6 min-h-screen" style="background:#2d2e2b !important; background-image:none !important; box-shadow:0 -8px 20px rgba(0,0,0,0.35) !important;">
|
<div id="rd-content-body" class="bg-[rgb(var(--app-bg-rgb))] rounded-t-3xl -mt-6 relative z-30 pt-6 min-h-screen" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important; box-shadow:0 -8px 20px rgba(0,0,0,0.35) !important;">
|
||||||
<div class="mb-3 px-5">
|
<div class="mb-3 px-5">
|
||||||
<div class="flex justify-between items-start mb-2.5">
|
<div class="flex justify-between items-start mb-2.5">
|
||||||
<h1 id="rd-title" class="text-xl font-bold leading-tight" style="color:#ddd6ca;"></h1>
|
<h1 id="rd-title" class="text-xl font-bold leading-tight" style="color:rgb(var(--text-body-rgb));"></h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -253,17 +253,17 @@ function renderNutritionSummary(recipe) {
|
|||||||
? `
|
? `
|
||||||
<div class="mt-3 flex items-center justify-between gap-3">
|
<div class="mt-3 flex items-center justify-between gap-3">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Porcje</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Porcje</p>
|
||||||
<p class="pr-1 text-[13px] font-semibold leading-none text-[#d7d2c8] tabular-nums">${currentServings}</p>
|
<p class="pr-1 text-[13px] font-semibold leading-none text-[rgb(var(--text-body-soft-rgb))] tabular-nums">${currentServings}</p>
|
||||||
</div>`
|
</div>`
|
||||||
: `
|
: `
|
||||||
<div class="mt-3 flex items-center justify-between gap-3">
|
<div class="mt-3 flex items-center justify-between gap-3">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Porcje</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider">Porcje</p>
|
||||||
<div class="flex h-[2rem] w-[5.25rem] shrink-0 items-center gap-0.5 rounded-full border px-0.5" style="background:#2f2f2d;border-color:#444442;box-shadow:0 2px 8px rgba(0,0,0,0.25);">
|
<div class="flex h-[2rem] w-[5.25rem] shrink-0 items-center gap-0.5 rounded-full border px-0.5" style="background:rgb(var(--card-soft-rgb));border-color:rgb(var(--card-strong-rgb));box-shadow:0 2px 8px rgba(0,0,0,0.25);">
|
||||||
<button type="button" id="rd-serv-minus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[#d7d2c8] transition-colors" aria-label="Zmniejsz liczbę porcji">
|
<button type="button" id="rd-serv-minus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[rgb(var(--text-body-soft-rgb))] transition-colors" aria-label="Zmniejsz liczbę porcji">
|
||||||
<i class="fas fa-minus text-[10px]"></i>
|
<i class="fas fa-minus text-[10px]"></i>
|
||||||
</button>
|
</button>
|
||||||
<span id="rd-servings" class="flex-1 h-full inline-flex items-center justify-center px-0.5 text-[12px] font-semibold leading-none text-[#d7d2c8] tabular-nums">${currentServings}</span>
|
<span id="rd-servings" class="flex-1 h-full inline-flex items-center justify-center px-0.5 text-[12px] font-semibold leading-none text-[rgb(var(--text-body-soft-rgb))] tabular-nums">${currentServings}</span>
|
||||||
<button type="button" id="rd-serv-plus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[#d7d2c8] transition-colors" aria-label="Zwiększ liczbę porcji">
|
<button type="button" id="rd-serv-plus" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full border-0 bg-transparent text-[rgb(var(--text-body-soft-rgb))] transition-colors" aria-label="Zwiększ liczbę porcji">
|
||||||
<i class="fas fa-plus text-[10px]"></i>
|
<i class="fas fa-plus text-[10px]"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -271,23 +271,23 @@ function renderNutritionSummary(recipe) {
|
|||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<div class="h-full pb-2 flex flex-col" style="background:#2d2e2b !important; background-image:none !important; box-shadow:none !important;">
|
<div class="h-full pb-2 flex flex-col" style="background:rgb(var(--app-bg-rgb)) !important; background-image:none !important; box-shadow:none !important;">
|
||||||
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Wartości odżywcze</p>
|
<p class="text-[10px] font-bold text-gray-400 uppercase tracking-wider mb-2">Wartości odżywcze</p>
|
||||||
<div class="flex-1 flex items-center">
|
<div class="flex-1 flex items-center">
|
||||||
<div class="grid grid-cols-4 gap-1.5 w-full">
|
<div class="grid grid-cols-4 gap-1.5 w-full">
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-gray-100 tabular-nums leading-tight">${total.kcal}</p>
|
<p class="text-[15px] font-bold text-gray-100 tabular-nums leading-tight">${total.kcal}</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">kcal</p>
|
<p class="text-[9px] text-gray-500 font-medium">kcal</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">${total.protein}g</p>
|
<p class="text-[15px] font-bold text-blue-400 tabular-nums leading-tight">${total.protein}g</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">białko</p>
|
<p class="text-[9px] text-gray-500 font-medium">białko</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">${total.fat}g</p>
|
<p class="text-[15px] font-bold text-amber-400 tabular-nums leading-tight">${total.fat}g</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">tłuszcz</p>
|
<p class="text-[9px] text-gray-500 font-medium">tłuszcz</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:#393937;">
|
<div class="rounded-xl px-2 py-[0.5625rem] text-center" style="background:rgb(var(--card-rgb));">
|
||||||
<p class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">${total.carbs}g</p>
|
<p class="text-[15px] font-bold text-orange-400 tabular-nums leading-tight">${total.carbs}g</p>
|
||||||
<p class="text-[9px] text-gray-500 font-medium">węglowodany</p>
|
<p class="text-[9px] text-gray-500 font-medium">węglowodany</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -306,12 +306,12 @@ function renderIngredients(recipe) {
|
|||||||
const items = buildVisibleIngredients(recipe);
|
const items = buildVisibleIngredients(recipe);
|
||||||
const rows = items.map((item) => {
|
const rows = items.map((item) => {
|
||||||
const rowClass = 'rd-ing-row rounded-xl px-3 py-3 w-full text-left cursor-pointer transition-colors active:scale-[0.99]';
|
const rowClass = 'rd-ing-row rounded-xl px-3 py-3 w-full text-left cursor-pointer transition-colors active:scale-[0.99]';
|
||||||
const rowStyle = 'background:#393937 !important; background-image:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.25) !important; border:none !important;';
|
const rowStyle = 'background:rgb(var(--card-rgb)) !important; background-image:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.25) !important; border:none !important;';
|
||||||
const productBadge = item.productName
|
const productBadge = item.productName
|
||||||
? `<div class="flex items-center gap-1 mt-0.5"><span class="text-[10px] text-emerald-400 truncate">${escapeHtml(item.productName)}</span></div>`
|
? `<div class="flex items-center gap-1 mt-0.5"><span class="text-[10px] text-emerald-400 truncate">${escapeHtml(item.productName)}</span></div>`
|
||||||
: '';
|
: '';
|
||||||
const addedMark = item.added
|
const addedMark = item.added
|
||||||
? '<span class="shrink-0 inline-flex items-center justify-center text-[#8f8b84]" title="Dodany składnik" aria-label="Dodany składnik"><i class="fas fa-plus text-[8px]"></i></span>'
|
? '<span class="shrink-0 inline-flex items-center justify-center text-[rgb(var(--text-faint-rgb))]" title="Dodany składnik" aria-label="Dodany składnik"><i class="fas fa-plus text-[8px]"></i></span>'
|
||||||
: '';
|
: '';
|
||||||
return `<li>
|
return `<li>
|
||||||
<button type="button" class="${rowClass}" style="${rowStyle}" data-rd-open-ingredient data-rd-ingredient-id="${escapeHtml(item.ingredientId)}" data-rd-product-id="${escapeHtml(item.productId || '')}">
|
<button type="button" class="${rowClass}" style="${rowStyle}" data-rd-open-ingredient data-rd-ingredient-id="${escapeHtml(item.ingredientId)}" data-rd-product-id="${escapeHtml(item.productId || '')}">
|
||||||
@@ -364,7 +364,7 @@ function renderIngredients(recipe) {
|
|||||||
const scaledAmount = ing.amount * currentServings;
|
const scaledAmount = ing.amount * currentServings;
|
||||||
const isExpanded = expandedAlternatives.has(origId);
|
const isExpanded = expandedAlternatives.has(origId);
|
||||||
const rowClass = 'rd-ing-row rounded-xl px-3 py-3';
|
const rowClass = 'rd-ing-row rounded-xl px-3 py-3';
|
||||||
const rowStyle = 'background:#393937 !important; background-image:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.25) !important; border:none !important;';
|
const rowStyle = 'background:rgb(var(--card-rgb)) !important; background-image:none !important; box-shadow:0 2px 8px rgba(0,0,0,0.25) !important; border:none !important;';
|
||||||
|
|
||||||
const toggleBtn = hasAlts
|
const toggleBtn = hasAlts
|
||||||
? `<button type="button" class="rd-alt-toggle shrink-0 w-5 h-5 flex items-center justify-center transition-colors text-gray-400 hover:text-gray-300" style="background:transparent !important; box-shadow:none !important;" data-original-id="${escapeHtml(origId)}" aria-label="Wybierz zamiennik składnika"><i class="fas fa-shuffle text-[10px]"></i></button>`
|
? `<button type="button" class="rd-alt-toggle shrink-0 w-5 h-5 flex items-center justify-center transition-colors text-gray-400 hover:text-gray-300" style="background:transparent !important; box-shadow:none !important;" data-original-id="${escapeHtml(origId)}" aria-label="Wybierz zamiennik składnika"><i class="fas fa-shuffle text-[10px]"></i></button>`
|
||||||
@@ -392,14 +392,14 @@ function renderIngredients(recipe) {
|
|||||||
const altNutrition = nutritionForAmount(altId, scaledAmount, ing.unit);
|
const altNutrition = nutritionForAmount(altId, scaledAmount, ing.unit);
|
||||||
const checkbox = `
|
const checkbox = `
|
||||||
<span class="ml-auto self-center w-[18px] h-[18px] rounded-full shrink-0 flex items-center justify-center"
|
<span class="ml-auto self-center w-[18px] h-[18px] rounded-full shrink-0 flex items-center justify-center"
|
||||||
style="border:1.5px solid #56534f; background:transparent;">
|
style="border:1.5px solid rgba(var(--border-input-rgb), 0.58); background:transparent;">
|
||||||
${isSelected ? '<i class="fas fa-check" style="color:#9b978f; font-size:8px; line-height:1; display:block; transform:translateY(0.5px);"></i>' : ''}
|
${isSelected ? '<i class="fas fa-check" style="color:rgb(var(--text-dim-rgb)); font-size:8px; line-height:1; display:block; transform:translateY(0.5px);"></i>' : ''}
|
||||||
</span>`;
|
</span>`;
|
||||||
const nutritionLine = altNutrition
|
const nutritionLine = altNutrition
|
||||||
? `<div class="text-[10px] text-gray-400 mt-0.5 tabular-nums">${altNutrition.kcal} kcal · ${altNutrition.protein}g B · ${altNutrition.fat}g T · ${altNutrition.carbs}g W</div>`
|
? `<div class="text-[10px] text-gray-400 mt-0.5 tabular-nums">${altNutrition.kcal} kcal · ${altNutrition.protein}g B · ${altNutrition.fat}g T · ${altNutrition.carbs}g W</div>`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
return `<button type="button" class="rd-alt-pick w-full text-left p-2.5 rounded-lg transition-all" style="background:#2f2f2d !important; background-image:none !important; border:none !important; box-shadow:none !important;" data-original-id="${escapeHtml(origId)}" data-alt-id="${escapeHtml(altId)}"><div class="flex items-center gap-3"><div class="min-w-0 flex-1"><div class="text-[11px] font-semibold text-gray-900">${escapeHtml(altName)}</div>${nutritionLine}</div>${checkbox}</div></button>`;
|
return `<button type="button" class="rd-alt-pick w-full text-left p-2.5 rounded-lg transition-all" style="background:rgb(var(--card-soft-rgb)) !important; background-image:none !important; border:none !important; box-shadow:none !important;" data-original-id="${escapeHtml(origId)}" data-alt-id="${escapeHtml(altId)}"><div class="flex items-center gap-3"><div class="min-w-0 flex-1"><div class="text-[11px] font-semibold text-gray-900">${escapeHtml(altName)}</div>${nutritionLine}</div>${checkbox}</div></button>`;
|
||||||
});
|
});
|
||||||
altListHtml = `
|
altListHtml = `
|
||||||
<div class="mt-2 ml-1 space-y-1 rd-alt-options" data-original-id="${escapeHtml(origId)}">
|
<div class="mt-2 ml-1 space-y-1 rd-alt-options" data-original-id="${escapeHtml(origId)}">
|
||||||
@@ -507,7 +507,7 @@ export function setupRecipeDetail() {
|
|||||||
const effectiveShadowBlur = isRoundButton ? shadowBlur + 1 : shadowBlur;
|
const effectiveShadowBlur = isRoundButton ? shadowBlur + 1 : shadowBlur;
|
||||||
const effectiveShadowAlpha = isRoundButton ? shadowAlpha + 0.05 : shadowAlpha;
|
const effectiveShadowAlpha = isRoundButton ? shadowAlpha + 0.05 : shadowAlpha;
|
||||||
button.style.boxShadow = `0 ${effectiveShadowY}px ${effectiveShadowBlur}px rgba(0,0,0,${effectiveShadowAlpha})`;
|
button.style.boxShadow = `0 ${effectiveShadowY}px ${effectiveShadowBlur}px rgba(0,0,0,${effectiveShadowAlpha})`;
|
||||||
button.style.background = `rgba(57,57,55,${backgroundAlpha})`;
|
button.style.background = `rgba(var(--card-rgb),${backgroundAlpha})`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,31 +113,31 @@ function renderGrid() {
|
|||||||
|
|
||||||
export function getRecipeListHTML() {
|
export function getRecipeListHTML() {
|
||||||
return `
|
return `
|
||||||
<div id="main-view" class="flex flex-col h-full absolute inset-0 bg-[#2d2e2b] z-10" style="background:#2d2e2b !important;">
|
<div id="main-view" class="flex flex-col h-full absolute inset-0 bg-[rgb(var(--app-bg-rgb))] z-10" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div id="recipe-top-bar" class="pointer-events-none absolute inset-x-0 top-0 z-[12] px-4 pt-4 pb-4" style="background:#2d2e2b !important; border:none !important;">
|
<div id="recipe-top-bar" class="pointer-events-none absolute inset-x-0 top-0 z-[12] px-4 pt-4 pb-4" style="background:rgb(var(--app-bg-rgb)) !important; border:none !important;">
|
||||||
<div class="pointer-events-auto relative z-[1] w-full">
|
<div class="pointer-events-auto relative z-[1] w-full">
|
||||||
<div id="recipe-topbar" class="relative min-h-12">
|
<div id="recipe-topbar" class="relative min-h-12">
|
||||||
|
|
||||||
<div id="recipe-default-row" class="flex min-h-12 items-center gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
|
<div id="recipe-default-row" class="flex min-h-12 items-center gap-2 transition-all duration-200" style="opacity:1; transform:translateY(0) scale(1);">
|
||||||
<h1 class="min-w-0 flex-1 truncate" style="margin:0;padding:0;color:#f2efe8;font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Katalog przepisów</h1>
|
<h1 class="min-w-0 flex-1 truncate" style="margin:0;padding:0;color:rgb(var(--text-emphasis-rgb));font-family:var(--app-font);font-size:18px;font-weight:700;line-height:1.2;letter-spacing:-0.02em;">Katalog przepisów</h1>
|
||||||
|
|
||||||
<div id="recipe-filter-wrap" class="relative shrink-0">
|
<div id="recipe-filter-wrap" class="relative shrink-0">
|
||||||
<button type="button" id="recipe-filter-btn" class="relative w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:#393937; border:1px solid #41423f; box-shadow:${SEARCH_SHELL_SHADOW}; color:#ddd6ca;" aria-label="Otwórz filtry">
|
<button type="button" id="recipe-filter-btn" class="relative w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:rgb(var(--card-rgb)); border:1px solid rgb(var(--border-card-rgb)); box-shadow:${SEARCH_SHELL_SHADOW}; color:rgb(var(--text-body-rgb));" aria-label="Otwórz filtry">
|
||||||
<i class="fas fa-sliders-h text-[12px]" aria-hidden="true"></i>
|
<i class="fas fa-sliders-h text-[12px]" aria-hidden="true"></i>
|
||||||
<span id="recipe-filter-count" class="hidden absolute -top-1 -right-1 min-w-[1.1rem] h-[1.1rem] px-1 rounded-full text-[9px] font-bold leading-none items-center justify-center" style="background:#23221e; border:1px solid #787876; color:#f2efe8;"></span>
|
<span id="recipe-filter-count" class="hidden absolute -top-1 -right-1 min-w-[1.1rem] h-[1.1rem] px-1 rounded-full text-[9px] font-bold leading-none items-center justify-center" style="background:rgb(var(--sunken-rgb)); border:1px solid rgb(var(--border-input-rgb)); color:rgb(var(--text-emphasis-rgb));"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" id="recipe-search-toggle" class="w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:#393937 !important; border:1px solid #41423f !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; color:#ddd6ca;" aria-label="Szukaj">
|
<button type="button" id="recipe-search-toggle" class="w-11 h-11 rounded-full shrink-0 flex items-center justify-center transition-all duration-200" style="background:rgb(var(--card-rgb)) !important; border:1px solid rgb(var(--border-card-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; color:rgb(var(--text-body-rgb));" aria-label="Szukaj">
|
||||||
<i class="fas fa-search text-[13px]" aria-hidden="true"></i>
|
<i class="fas fa-search text-[13px]" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="recipe-search-shell" class="absolute inset-0 flex items-center gap-2 rounded-full px-3 transition-all duration-200 pointer-events-none" style="background:#23221e !important; border:1px solid #787876 !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-2px) scale(0.98);">
|
<div id="recipe-search-shell" class="absolute inset-0 flex items-center gap-2 rounded-full px-3 transition-all duration-200 pointer-events-none" style="background:rgb(var(--sunken-rgb)) !important; border:1px solid rgb(var(--border-input-rgb)) !important; box-shadow:${SEARCH_SHELL_SHADOW} !important; opacity:0; transform:translateY(-2px) scale(0.98);">
|
||||||
<i class="fas fa-search text-[13px] shrink-0" style="color:#9b978f;"></i>
|
<i class="fas fa-search text-[13px] shrink-0" style="color:rgb(var(--text-dim-rgb));"></i>
|
||||||
<input type="search" id="recipe-search-input" autocomplete="off" placeholder="Szukaj przepisów…"
|
<input type="search" id="recipe-search-input" autocomplete="off" placeholder="Szukaj przepisów…"
|
||||||
class="flex-1 min-w-0 h-full bg-transparent outline-none text-[15px] leading-none py-0" style="background:transparent !important; border:none !important; box-shadow:none !important; color:#ddd6ca; margin:0;">
|
class="flex-1 min-w-0 h-full bg-transparent outline-none text-[15px] leading-none py-0" style="background:transparent !important; border:none !important; box-shadow:none !important; color:rgb(var(--text-body-rgb)); margin:0;">
|
||||||
<button type="button" id="recipe-search-close" class="w-8 h-8 rounded-full shrink-0 flex items-center justify-center transition-colors" style="background:#2f2f2d; border:none; color:#9b978f;">
|
<button type="button" id="recipe-search-close" class="w-8 h-8 rounded-full shrink-0 flex items-center justify-center transition-colors" style="background:rgb(var(--card-soft-rgb)); border:none; color:rgb(var(--text-dim-rgb));">
|
||||||
<i class="fas fa-xmark text-[13px]"></i>
|
<i class="fas fa-xmark text-[13px]"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -149,8 +149,8 @@ export function getRecipeListHTML() {
|
|||||||
scrollId: 'recipe-scroll',
|
scrollId: 'recipe-scroll',
|
||||||
gridId: 'recipe-grid',
|
gridId: 'recipe-grid',
|
||||||
emptyStateId: 'recipe-empty-state',
|
emptyStateId: 'recipe-empty-state',
|
||||||
scrollClassName: 'relative flex-1 overflow-y-auto px-4 pt-[5.35rem] pb-24 bg-[#2d2e2b]',
|
scrollClassName: 'relative flex-1 overflow-y-auto px-4 pt-[5.35rem] pb-24 bg-[rgb(var(--app-bg-rgb))]',
|
||||||
gridClassName: 'grid grid-cols-3 gap-2 bg-[#2d2e2b]',
|
gridClassName: 'grid grid-cols-3 gap-2 bg-[rgb(var(--app-bg-rgb))]',
|
||||||
emptyTitle: 'Brak wyników',
|
emptyTitle: 'Brak wyników',
|
||||||
emptyMessage: 'Zmień kryteria wyszukiwania lub filtry',
|
emptyMessage: 'Zmień kryteria wyszukiwania lub filtry',
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const DAY_NAMES_SHORT = ['nd.', 'pon.', 'wt.', 'śr.', 'czw.', 'pt.', 'sob.'];
|
|||||||
const WEEKDAY_SHORT = ['pn', 'wt', 'śr', 'cz', 'pt', 'sb', 'nd'];
|
const WEEKDAY_SHORT = ['pn', 'wt', 'śr', 'cz', 'pt', 'sb', 'nd'];
|
||||||
const MONTHS_LONG = ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'];
|
const MONTHS_LONG = ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'];
|
||||||
const MONTHS_SHORT = ['sty','lut','mar','kwi','maj','cze','lip','sie','wrz','paź','lis','gru'];
|
const MONTHS_SHORT = ['sty','lut','mar','kwi','maj','cze','lip','sie','wrz','paź','lis','gru'];
|
||||||
const CALENDAR_DIM_TEXT = '#888278';
|
const CALENDAR_DIM_TEXT = 'rgb(var(--text-faint-rgb))';
|
||||||
const CALENDAR_DIM_OPACITY = '0.58';
|
const CALENDAR_DIM_OPACITY = '0.58';
|
||||||
|
|
||||||
/* ── module state ── */
|
/* ── module state ── */
|
||||||
@@ -118,36 +118,36 @@ export function getShoppingListHTML() {
|
|||||||
.join('');
|
.join('');
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div id="shopping-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden z-10" style="background:#2d2e2b !important;">
|
<div id="shopping-view" class="hidden flex flex-col h-full absolute inset-0 overflow-hidden z-10" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
|
|
||||||
<!-- ── header ── -->
|
<!-- ── header ── -->
|
||||||
<div class="shrink-0 px-4 pt-5 pb-0">
|
<div class="shrink-0 px-4 pt-5 pb-0">
|
||||||
|
|
||||||
<!-- title row + pill (position:relative anchors the popup) -->
|
<!-- title row + pill (position:relative anchors the popup) -->
|
||||||
<div class="flex items-center gap-2 mb-3" style="position:relative;">
|
<div class="flex items-center gap-2 mb-3" style="position:relative;">
|
||||||
<h1 class="flex-1 text-[18px] font-bold" style="color:#f2efe8;">Lista zakupów</h1>
|
<h1 class="flex-1 text-[18px] font-bold" style="color:rgb(var(--text-emphasis-rgb));">Lista zakupów</h1>
|
||||||
<button type="button" id="sl-range-pill" class="min-w-0 max-w-[10rem] h-10 rounded-full flex items-center gap-1.5 px-2.5 transition-all shrink" style="background:#393937; border:1px solid #41423f; box-shadow:${SL_SHADOW};">
|
<button type="button" id="sl-range-pill" class="min-w-0 max-w-[10rem] h-10 rounded-full flex items-center gap-1.5 px-2.5 transition-all shrink" style="background:rgb(var(--card-rgb)); border:1px solid rgb(var(--border-card-rgb)); box-shadow:${SL_SHADOW};">
|
||||||
<span id="sl-range-label" class="min-w-0 flex-1 text-left text-[13px] font-normal truncate" style="color:#ddd6ca;"></span>
|
<span id="sl-range-label" class="min-w-0 flex-1 text-left text-[13px] font-normal truncate" style="color:rgb(var(--text-body-rgb));"></span>
|
||||||
<i id="sl-range-chevron" class="fas fa-chevron-down text-[10px] shrink-0 transition-transform duration-200" style="color:#9b978f;"></i>
|
<i id="sl-range-chevron" class="fas fa-chevron-down text-[10px] shrink-0 transition-transform duration-200" style="color:rgb(var(--text-dim-rgb));"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- popup calendar (absolute, overlays content below) -->
|
<!-- popup calendar (absolute, overlays content below) -->
|
||||||
<div id="sl-calendar-popup" style="position:absolute; top:calc(100% + 0.5rem); left:0; right:0; z-index:50; pointer-events:none; opacity:0; transform:translateY(-6px) scale(0.98); transition: opacity 0.2s ease, transform 0.2s ease;">
|
<div id="sl-calendar-popup" style="position:absolute; top:calc(100% + 0.5rem); left:0; right:0; z-index:50; pointer-events:none; opacity:0; transform:translateY(-6px) scale(0.98); transition: opacity 0.2s ease, transform 0.2s ease;">
|
||||||
<div class="rounded-[1.35rem] px-3 py-3" style="background:#23221e; border:1px solid #787876; box-shadow:${SL_SHADOW};">
|
<div class="rounded-[1.35rem] px-3 py-3" style="background:rgb(var(--sunken-rgb)); border:1px solid rgb(var(--border-input-rgb)); box-shadow:${SL_SHADOW};">
|
||||||
<!-- month nav topbar -->
|
<!-- month nav topbar -->
|
||||||
<div class="pb-3 flex items-center justify-end gap-3">
|
<div class="pb-3 flex items-center justify-end gap-3">
|
||||||
<div class="flex h-[2.05rem] min-w-0 max-w-[min(100%,20rem)] items-center gap-px rounded-full border px-0.5" style="background:#272622; border-color:#34312c;">
|
<div class="flex h-[2.05rem] min-w-0 max-w-[min(100%,20rem)] items-center gap-px rounded-full border px-0.5" style="background:rgb(var(--app-bg-rgb)); border-color:rgb(var(--card-raised-rgb));">
|
||||||
<button type="button" id="sl-cal-prev" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full bg-transparent transition-colors" style="color:#d7d2c8;">
|
<button type="button" id="sl-cal-prev" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full bg-transparent transition-colors" style="color:rgb(var(--text-body-soft-rgb));">
|
||||||
<i class="fas fa-chevron-left text-[10px]"></i>
|
<i class="fas fa-chevron-left text-[10px]"></i>
|
||||||
</button>
|
</button>
|
||||||
<span id="sl-cal-month-label" class="h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center px-1.5 text-[10px] font-semibold leading-none tabular-nums whitespace-nowrap" style="color:#d7d2c8;"></span>
|
<span id="sl-cal-month-label" class="h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center px-1.5 text-[10px] font-semibold leading-none tabular-nums whitespace-nowrap" style="color:rgb(var(--text-body-soft-rgb));"></span>
|
||||||
<button type="button" id="sl-cal-next" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full bg-transparent transition-colors" style="color:#d7d2c8;">
|
<button type="button" id="sl-cal-next" class="shrink-0 w-7 h-full flex items-center justify-center rounded-full bg-transparent transition-colors" style="color:rgb(var(--text-body-soft-rgb));">
|
||||||
<i class="fas fa-chevron-right text-[10px]"></i>
|
<i class="fas fa-chevron-right text-[10px]"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- weekday header -->
|
<!-- weekday header -->
|
||||||
<div class="grid grid-cols-7 gap-1.5 text-center text-[8px] font-medium uppercase tracking-wide mb-1 leading-none" style="color:#9b978f;">${weekdayHeader}</div>
|
<div class="grid grid-cols-7 gap-1.5 text-center text-[8px] font-medium uppercase tracking-wide mb-1 leading-none" style="color:rgb(var(--text-dim-rgb));">${weekdayHeader}</div>
|
||||||
<!-- day grid -->
|
<!-- day grid -->
|
||||||
<div id="sl-cal-grid" class="grid grid-cols-7 gap-1.5"></div>
|
<div id="sl-cal-grid" class="grid grid-cols-7 gap-1.5"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -156,12 +156,12 @@ export function getShoppingListHTML() {
|
|||||||
|
|
||||||
<!-- progress -->
|
<!-- progress -->
|
||||||
<div id="sl-progress-wrap" class="mb-3">
|
<div id="sl-progress-wrap" class="mb-3">
|
||||||
<span class="text-[12px] font-semibold block mb-1.5" style="color:#9b978f;">Kupione <span id="sl-progress-text">0/0</span></span>
|
<span class="text-[12px] font-semibold block mb-1.5" style="color:rgb(var(--text-dim-rgb));">Kupione</span>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<div class="flex-1 h-1.5 rounded-full overflow-hidden" style="background:#393937;">
|
<div class="flex-1 h-1.5 rounded-full overflow-hidden" style="background:rgb(var(--card-rgb));">
|
||||||
<div id="sl-progress-bar" class="h-full rounded-full transition-all duration-300" style="background:rgb(var(--success-rgb)); width:0%;"></div>
|
<div id="sl-progress-bar" class="h-full rounded-full transition-all duration-300" style="background:rgb(var(--success-rgb)); width:0%;"></div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" id="sl-clear-session" class="flex items-center justify-center flex-shrink-0" style="color:#6b6965;" aria-label="Wyczyść kupione">
|
<button type="button" id="sl-clear-session" class="flex items-center justify-center flex-shrink-0" style="color:rgb(var(--text-subdued-rgb));" aria-label="Wyczyść kupione">
|
||||||
<i class="fas fa-trash-can" style="font-size:14px;" aria-hidden="true"></i>
|
<i class="fas fa-trash-can" style="font-size:14px;" aria-hidden="true"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -169,12 +169,12 @@ export function getShoppingListHTML() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ── scrollable list ── -->
|
<!-- ── scrollable list ── -->
|
||||||
<div id="sl-scroll" class="flex-1 overflow-y-auto no-scrollbar px-4 pt-3 pb-24" style="background:#2d2e2b !important;">
|
<div id="sl-scroll" class="flex-1 overflow-y-auto no-scrollbar px-4 pt-3 pb-24" style="background:rgb(var(--app-bg-rgb)) !important;">
|
||||||
<div id="sl-board"></div>
|
<div id="sl-board"></div>
|
||||||
|
|
||||||
<!-- bought section -->
|
<!-- bought section -->
|
||||||
<div id="sl-bought-section" class="mt-3 hidden">
|
<div id="sl-bought-section" class="mt-3 hidden">
|
||||||
<button type="button" id="sl-bought-toggle" class="flex items-center gap-2 w-full py-2 px-1 text-left" style="color:#9b978f;">
|
<button type="button" id="sl-bought-toggle" class="flex items-center gap-2 w-full py-2 px-1 text-left" style="color:rgb(var(--text-dim-rgb));">
|
||||||
<i id="sl-bought-chevron" class="fas fa-chevron-right text-[10px] transition-transform duration-200"></i>
|
<i id="sl-bought-chevron" class="fas fa-chevron-right text-[10px] transition-transform duration-200"></i>
|
||||||
<span class="text-[11px] font-bold uppercase tracking-wider">Kupione (<span id="sl-bought-count">0</span>)</span>
|
<span class="text-[11px] font-bold uppercase tracking-wider">Kupione (<span id="sl-bought-count">0</span>)</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -222,15 +222,15 @@ function renderCalendarGrid(previewDays = null) {
|
|||||||
|
|
||||||
let bg, borderColor, color, opacity, borderClass;
|
let bg, borderColor, color, opacity, borderClass;
|
||||||
if (isSel) {
|
if (isSel) {
|
||||||
bg = '#393937'; borderColor = '#787876'; color = '#f2efe8'; opacity = '1'; borderClass = 'border';
|
bg = 'rgb(var(--card-rgb))'; borderColor = 'rgb(var(--border-input-rgb))'; color = 'rgb(var(--text-emphasis-rgb))'; opacity = '1'; borderClass = 'border';
|
||||||
} else if (!inMonth) {
|
} else if (!inMonth) {
|
||||||
bg = 'transparent'; borderColor = 'transparent'; color = CALENDAR_DIM_TEXT; opacity = CALENDAR_DIM_OPACITY; borderClass = 'border-0';
|
bg = 'transparent'; borderColor = 'transparent'; color = CALENDAR_DIM_TEXT; opacity = CALENDAR_DIM_OPACITY; borderClass = 'border-0';
|
||||||
} else {
|
} else {
|
||||||
bg = '#272622'; borderColor = '#34312c'; color = '#d7d2c8'; opacity = '1'; borderClass = 'border';
|
bg = 'rgb(var(--app-bg-rgb))'; borderColor = 'rgb(var(--card-raised-rgb))'; color = 'rgb(var(--text-body-soft-rgb))'; opacity = '1'; borderClass = 'border';
|
||||||
}
|
}
|
||||||
|
|
||||||
const dot = isToday && !isSel
|
const dot = isToday && !isSel
|
||||||
? `<span class="absolute left-1/2 -translate-x-1/2 w-1 h-1 rounded-full opacity-75" style="bottom:0.24rem; background:#7d7a74;"></span>`
|
? `<span class="absolute left-1/2 -translate-x-1/2 w-1 h-1 rounded-full opacity-75" style="bottom:0.24rem; background:rgb(var(--text-faint-rgb));"></span>`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
return `<button type="button" class="sl-cal-day mx-auto flex h-[2.05rem] w-full min-w-0 max-w-full items-center justify-center rounded-full ${borderClass} text-xs font-medium leading-tight overflow-hidden"
|
return `<button type="button" class="sl-cal-day mx-auto flex h-[2.05rem] w-full min-w-0 max-w-full items-center justify-center rounded-full ${borderClass} text-xs font-medium leading-tight overflow-hidden"
|
||||||
@@ -315,8 +315,8 @@ function openCalendar() {
|
|||||||
}
|
}
|
||||||
if (chevron) chevron.style.transform = 'rotate(180deg)';
|
if (chevron) chevron.style.transform = 'rotate(180deg)';
|
||||||
if (pill) {
|
if (pill) {
|
||||||
pill.style.background = '#23221e';
|
pill.style.background = 'rgb(var(--sunken-rgb))';
|
||||||
pill.style.borderColor = '#787876';
|
pill.style.borderColor = 'rgb(var(--border-input-rgb))';
|
||||||
}
|
}
|
||||||
renderCalendarGrid();
|
renderCalendarGrid();
|
||||||
}
|
}
|
||||||
@@ -333,8 +333,8 @@ function closeCalendar() {
|
|||||||
}
|
}
|
||||||
if (chevron) chevron.style.transform = '';
|
if (chevron) chevron.style.transform = '';
|
||||||
if (pill) {
|
if (pill) {
|
||||||
pill.style.background = '#393937';
|
pill.style.background = 'rgb(var(--card-rgb))';
|
||||||
pill.style.borderColor = '#41423f';
|
pill.style.borderColor = 'rgb(var(--border-card-rgb))';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,44 +344,48 @@ function toggleCalendar() {
|
|||||||
|
|
||||||
/* ══════════════════════ ITEM ROWS ══════════════════════ */
|
/* ══════════════════════ ITEM ROWS ══════════════════════ */
|
||||||
|
|
||||||
function activeItemHtml(item, isPartial) {
|
function activeItemHtml(item) {
|
||||||
const def = INGREDIENTS[item.ingredientId];
|
const def = INGREDIENTS[item.ingredientId];
|
||||||
const icon = CATEGORY_ICONS[def?.category] || 'fa-jar';
|
const icon = CATEGORY_ICONS[def?.category] || 'fa-jar';
|
||||||
const image = def?.image;
|
const image = def?.image;
|
||||||
const mediaFit = image?.endsWith('.svg') ? 'object-contain' : 'object-cover';
|
const mediaFit = image?.endsWith('.svg') ? 'object-contain' : 'object-cover';
|
||||||
const mediaHtml = image
|
const mediaHtml = image
|
||||||
? `<img src="${esc(image)}" alt="" class="w-8 h-8 rounded-lg ${mediaFit} shrink-0">`
|
? `<img src="${esc(image)}" alt="" class="w-8 h-8 rounded-lg ${mediaFit} shrink-0">`
|
||||||
: `<div class="w-8 h-8 rounded-lg flex items-center justify-center shrink-0" style="background:#2f2f2d;"><i class="fas ${icon} text-xs" style="color:#8f8b84;"></i></div>`;
|
: `<div class="w-8 h-8 rounded-lg flex items-center justify-center shrink-0" style="background:rgb(var(--card-soft-rgb));"><i class="fas ${icon} text-xs" style="color:rgb(var(--text-faint-rgb));"></i></div>`;
|
||||||
|
|
||||||
const isExpanded = expandedIngredientId === item.ingredientId;
|
const isExpanded = expandedIngredientId === item.ingredientId;
|
||||||
const step = stepForUnit(item.unit);
|
const step = stepForUnit(item.unit);
|
||||||
const stepAmt = isExpanded ? expandedAmount : Math.max(step, Math.round(item.shortfall / step) * step);
|
const stepAmt = isExpanded ? expandedAmount : Math.max(step, Math.round(item.shortfall / step) * step);
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="sl-swipe-wrap relative rounded-xl mb-1.5 overflow-hidden" style="background:#4a7c59; box-shadow:0 2px 8px rgba(0,0,0,0.28);">
|
<div class="sl-swipe-wrap relative rounded-xl mb-1.5 overflow-hidden" style="background:rgb(var(--success-rgb)); box-shadow:0 2px 8px rgba(0,0,0,0.28);">
|
||||||
<div class="sl-swipe-bg-buy absolute inset-0 flex items-center pr-5 justify-end">
|
<div class="sl-swipe-bg-buy absolute inset-0 flex items-center pr-5 justify-end">
|
||||||
<i class="fas fa-check text-white text-lg"></i>
|
<i class="fas fa-check text-white text-lg"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="sl-swipe-inner rounded-xl" style="background:#393937; position:relative;"
|
<div class="sl-swipe-inner rounded-xl" style="background:rgb(var(--card-rgb)); position:relative;"
|
||||||
data-id="${esc(item.ingredientId)}" data-unit="${esc(item.unit)}" data-shortfall="${item.shortfall}">
|
data-id="${esc(item.ingredientId)}" data-unit="${esc(item.unit)}" data-shortfall="${item.shortfall}">
|
||||||
<div class="sl-item-main flex items-center gap-3 py-1.5 px-3 cursor-pointer select-none">
|
<div class="sl-item-main flex items-center gap-3 py-1.5 px-3 cursor-pointer select-none">
|
||||||
${mediaHtml}
|
${mediaHtml}
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
<span class="block text-[13px] font-medium leading-tight truncate" style="color:#ddd6ca;">${esc(item.name)}</span>
|
<span class="block text-[13px] font-medium leading-tight truncate" style="color:rgb(var(--text-body-rgb));">${esc(item.name)}</span>
|
||||||
${isPartial ? `<span class="text-[10px]" style="color:rgb(var(--accent-rgb));">część już w spiżarni</span>` : ''}
|
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[13px] font-semibold tabular-nums shrink-0" style="color:#b7ada1;">${esc(formatQty(item.shortfall))} ${esc(unitLabel(item.unit))}</span>
|
<span class="text-[13px] font-semibold tabular-nums shrink-0" style="color:rgb(var(--text-muted-rgb));">${esc(formatQty(item.shortfall))} ${esc(unitLabel(item.unit))}</span>
|
||||||
<i class="fas fa-chevron-${isExpanded ? 'up' : 'down'} text-[9px] shrink-0" style="color:#6d6c67;"></i>
|
<i class="fas fa-chevron-${isExpanded ? 'up' : 'down'} text-[9px] shrink-0" style="color:rgb(var(--text-subdued-rgb));"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="sl-step-row overflow-hidden" data-step-for="${esc(item.ingredientId)}"
|
<div class="sl-step-row overflow-hidden" data-step-for="${esc(item.ingredientId)}"
|
||||||
style="max-height:${isExpanded ? '52px' : '0'}; transition: max-height 0.2s ease;">
|
style="max-height:${isExpanded ? '60px' : '0'}; transition: max-height 0.2s ease;">
|
||||||
<div class="flex items-center gap-3 px-3 pb-3">
|
<div class="flex items-center gap-2 px-3 pb-3">
|
||||||
<button type="button" class="sl-step-minus w-8 h-8 rounded-full flex items-center justify-center text-lg font-bold shrink-0 active:scale-95" style="background:#2f2f2d; color:#ddd6ca; border:1px solid #444442;">−</button>
|
<button type="button" class="sl-step-minus w-9 h-9 rounded-xl flex items-center justify-center shrink-0 active:scale-95" style="background:rgb(var(--card-soft-rgb)); color:rgb(var(--text-body-soft-rgb));" aria-label="Zmniejsz ilość">
|
||||||
<span class="sl-exp-amount text-[15px] font-bold tabular-nums" style="color:#f2efe8; min-width:40px; text-align:center;">${esc(formatQty(stepAmt))}</span>
|
<i class="fas fa-minus text-xs"></i>
|
||||||
<span class="text-[12px]" style="color:#9b978f;">${esc(unitLabel(item.unit))}</span>
|
</button>
|
||||||
<button type="button" class="sl-step-plus w-8 h-8 rounded-full flex items-center justify-center text-lg font-bold shrink-0 active:scale-95" style="background:#2f2f2d; color:#ddd6ca; border:1px solid #444442;">+</button>
|
<div class="flex-1 rounded-xl px-3 py-2 flex items-center justify-center gap-2" style="background:rgb(var(--card-soft-rgb));">
|
||||||
<div class="flex-1"></div>
|
<span class="sl-exp-amount text-[14px] font-semibold tabular-nums" style="color:rgb(var(--text-body-rgb));">${esc(formatQty(stepAmt))}</span>
|
||||||
<button type="button" class="sl-step-confirm px-3 py-1.5 rounded-lg text-[12px] font-semibold shrink-0 active:scale-95" style="background:rgb(var(--accent-rgb)); color:#1a1a1a;">Dodaj</button>
|
<span class="text-[12px] font-medium shrink-0" style="color:rgb(var(--text-dim-rgb));">${esc(unitLabel(item.unit))}</span>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="sl-step-plus w-9 h-9 rounded-xl flex items-center justify-center shrink-0 active:scale-95" style="background:rgb(var(--card-soft-rgb)); color:rgb(var(--text-body-soft-rgb));" aria-label="Zwiększ ilość">
|
||||||
|
<i class="fas fa-plus text-xs"></i>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="sl-step-confirm px-3 py-1.5 rounded-lg text-[12px] font-semibold shrink-0 active:scale-95" style="background:rgb(var(--text-body-rgb)); color:rgb(var(--app-bg-rgb));">Dodaj</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -395,22 +399,22 @@ function boughtItemHtml(entry) {
|
|||||||
const mediaFit = image?.endsWith('.svg') ? 'object-contain' : 'object-cover';
|
const mediaFit = image?.endsWith('.svg') ? 'object-contain' : 'object-cover';
|
||||||
const mediaHtml = image
|
const mediaHtml = image
|
||||||
? `<img src="${esc(image)}" alt="" class="w-8 h-8 rounded-lg ${mediaFit} shrink-0 opacity-50">`
|
? `<img src="${esc(image)}" alt="" class="w-8 h-8 rounded-lg ${mediaFit} shrink-0 opacity-50">`
|
||||||
: `<div class="w-8 h-8 rounded-lg flex items-center justify-center shrink-0 opacity-50" style="background:#2f2f2d;"><i class="fas ${icon} text-xs" style="color:#8f8b84;"></i></div>`;
|
: `<div class="w-8 h-8 rounded-lg flex items-center justify-center shrink-0 opacity-50" style="background:rgb(var(--card-soft-rgb));"><i class="fas ${icon} text-xs" style="color:rgb(var(--text-faint-rgb));"></i></div>`;
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="sl-swipe-wrap relative rounded-xl mb-1.5 overflow-hidden" style="background:#7c4a4a; box-shadow:0 2px 8px rgba(0,0,0,0.28);">
|
<div class="sl-swipe-wrap relative rounded-xl mb-1.5 overflow-hidden" style="background:rgb(var(--danger-rgb)); box-shadow:0 2px 8px rgba(0,0,0,0.28);">
|
||||||
<div class="sl-swipe-bg-undo absolute inset-0 flex items-center pl-5 justify-start">
|
<div class="sl-swipe-bg-undo absolute inset-0 flex items-center pl-5 justify-start">
|
||||||
<i class="fas fa-rotate-left text-white text-lg"></i>
|
<i class="fas fa-rotate-left text-white text-lg"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="sl-swipe-inner flex items-center gap-3 py-1.5 px-3 rounded-xl" style="background:#2f2f2d; position:relative;" data-entry-id="${esc(entry.id)}">
|
<div class="sl-swipe-inner flex items-center gap-3 py-1.5 px-3 rounded-xl" style="background:rgb(var(--card-soft-rgb)); position:relative;" data-entry-id="${esc(entry.id)}">
|
||||||
<div class="shrink-0 w-6 h-6 rounded-full flex items-center justify-center" style="background:rgb(var(--success-rgb));">
|
<div class="shrink-0 w-6 h-6 rounded-full flex items-center justify-center" style="background:rgb(var(--success-rgb));">
|
||||||
<i class="fas fa-check text-[10px]" style="color:#1a1a1a;"></i>
|
<i class="fas fa-check text-[10px]" style="color:rgb(var(--on-accent-rgb));"></i>
|
||||||
</div>
|
</div>
|
||||||
${mediaHtml}
|
${mediaHtml}
|
||||||
<div class="flex-1 min-w-0 opacity-60">
|
<div class="flex-1 min-w-0 opacity-60">
|
||||||
<span class="block text-[13px] font-medium leading-tight truncate line-through" style="color:#ddd6ca;">${esc(entry.name)}</span>
|
<span class="block text-[13px] font-medium leading-tight truncate line-through" style="color:rgb(var(--text-body-rgb));">${esc(entry.name)}</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-[13px] tabular-nums shrink-0 opacity-60" style="color:#b7ada1;">${esc(formatQty(entry.addedAmount))} ${esc(unitLabel(entry.unit))}</span>
|
<span class="text-[13px] tabular-nums shrink-0 opacity-60" style="color:rgb(var(--text-muted-rgb));">${esc(formatQty(entry.addedAmount))} ${esc(unitLabel(entry.unit))}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
@@ -514,14 +518,12 @@ function undoBoughtEntry(entryId) {
|
|||||||
/* ══════════════════════ RENDERING ══════════════════════ */
|
/* ══════════════════════ RENDERING ══════════════════════ */
|
||||||
|
|
||||||
function renderProgress(activeItems, sessionLog) {
|
function renderProgress(activeItems, sessionLog) {
|
||||||
const activeIds = new Set(activeItems.map((i) => i.ingredientId));
|
const touchedIds = new Set(sessionLog.map((e) => e.ingredientId));
|
||||||
const coveredIds = new Set(sessionLog.filter((e) => !activeIds.has(e.ingredientId)).map((e) => e.ingredientId));
|
const bought = touchedIds.size;
|
||||||
const bought = coveredIds.size;
|
const untouched = activeItems.filter((i) => !touchedIds.has(i.ingredientId)).length;
|
||||||
const total = activeItems.length + bought;
|
const total = bought + untouched;
|
||||||
|
|
||||||
const textEl = document.getElementById('sl-progress-text');
|
|
||||||
const barEl = document.getElementById('sl-progress-bar');
|
const barEl = document.getElementById('sl-progress-bar');
|
||||||
if (textEl) textEl.textContent = `${bought}/${total}`;
|
|
||||||
if (barEl) barEl.style.width = total > 0 ? `${Math.round((bought / total) * 100)}%` : '0%';
|
if (barEl) barEl.style.width = total > 0 ? `${Math.round((bought / total) * 100)}%` : '0%';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,27 +535,25 @@ function renderBoard() {
|
|||||||
if (selectedDays.length === 0) {
|
if (selectedDays.length === 0) {
|
||||||
root.innerHTML = `
|
root.innerHTML = `
|
||||||
<div class="flex flex-col items-center justify-center py-16 text-center">
|
<div class="flex flex-col items-center justify-center py-16 text-center">
|
||||||
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mb-4" style="background:#393937;">
|
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mb-4" style="background:rgb(var(--card-rgb));">
|
||||||
<i class="fas fa-calendar-days text-xl" style="color:#6d6c67;"></i>
|
<i class="fas fa-calendar-days text-xl" style="color:rgb(var(--text-subdued-rgb));"></i>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[14px] font-semibold mb-1" style="color:#ddd6ca;">Wybierz dni</p>
|
<p class="text-[14px] font-semibold mb-1" style="color:rgb(var(--text-body-rgb));">Wybierz dni</p>
|
||||||
<p class="text-[12px] max-w-[14rem]" style="color:#9b978f;">Otwórz kalendarz i zaznacz dni, na które chcesz zrobić zakupy.</p>
|
<p class="text-[12px] max-w-[14rem]" style="color:rgb(var(--text-dim-rgb));">Otwórz kalendarz i zaznacz dni, na które chcesz zrobić zakupy.</p>
|
||||||
</div>`;
|
</div>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const activeItems = computeActiveItems();
|
const activeItems = computeActiveItems();
|
||||||
const sessionLog = getSessionLog();
|
|
||||||
const sessionIds = new Set(sessionLog.map((e) => e.ingredientId));
|
|
||||||
|
|
||||||
if (activeItems.length === 0) {
|
if (activeItems.length === 0) {
|
||||||
root.innerHTML = `
|
root.innerHTML = `
|
||||||
<div class="flex flex-col items-center justify-center py-16 text-center">
|
<div class="flex flex-col items-center justify-center py-16 text-center">
|
||||||
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mb-4" style="background:#393937;">
|
<div class="w-14 h-14 rounded-2xl flex items-center justify-center mb-4" style="background:rgb(var(--card-rgb));">
|
||||||
<i class="fas fa-check text-xl" style="color:rgb(var(--success-rgb));"></i>
|
<i class="fas fa-check text-xl" style="color:rgb(var(--success-rgb));"></i>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[14px] font-semibold mb-1" style="color:#ddd6ca;">Wszystko masz</p>
|
<p class="text-[14px] font-semibold mb-1" style="color:rgb(var(--text-body-rgb));">Wszystko masz</p>
|
||||||
<p class="text-[12px] max-w-[14rem]" style="color:#9b978f;">Spiżarnia pokrywa zapotrzebowanie na wybrane dni.</p>
|
<p class="text-[12px] max-w-[14rem]" style="color:rgb(var(--text-dim-rgb));">Spiżarnia pokrywa zapotrzebowanie na wybrane dni.</p>
|
||||||
</div>`;
|
</div>`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -564,11 +564,11 @@ function renderBoard() {
|
|||||||
return `
|
return `
|
||||||
<section class="mb-4">
|
<section class="mb-4">
|
||||||
<div class="flex items-center gap-1.5 mb-2 px-1">
|
<div class="flex items-center gap-1.5 mb-2 px-1">
|
||||||
<i class="fas ${icon} text-[10px]" style="color:#9b978f;"></i>
|
<i class="fas ${icon} text-[10px]" style="color:rgb(var(--text-dim-rgb));"></i>
|
||||||
<p class="text-[10px] font-bold uppercase tracking-wider" style="color:#9b978f;">${esc(categoryLabel(cat))}</p>
|
<p class="text-[10px] font-bold uppercase tracking-wider" style="color:rgb(var(--text-dim-rgb));">${esc(categoryLabel(cat))}</p>
|
||||||
<span class="text-[10px]" style="color:#6d6c67;">${catItems.length}</span>
|
<span class="text-[10px]" style="color:rgb(var(--text-subdued-rgb));">${catItems.length}</span>
|
||||||
</div>
|
</div>
|
||||||
${catItems.map((item) => activeItemHtml(item, sessionIds.has(item.ingredientId))).join('')}
|
${catItems.map((item) => activeItemHtml(item)).join('')}
|
||||||
</section>`;
|
</section>`;
|
||||||
}).join('');
|
}).join('');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user