Ajout
This commit is contained in:
@@ -82,7 +82,7 @@ body {
|
||||
}
|
||||
|
||||
.cui-cards {
|
||||
padding: 10px;
|
||||
padding: 5px;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -185,19 +185,16 @@ body {
|
||||
}
|
||||
|
||||
.cui-view {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
background: #0a0d13;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.cui-iframe {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
.cui-iframe, .viewer-iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
display: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.cui-placeholder {
|
||||
@@ -295,6 +292,8 @@ body {
|
||||
/* quand la sidebar est réduite, même anneau interne */
|
||||
.cui-root.collapsed .cui-card.active {
|
||||
box-shadow: 0 0 0 2px var(--accent) inset;
|
||||
width: max-content;
|
||||
grid-template-columns: 29px 1fr;
|
||||
}
|
||||
|
||||
/* Titre de la barre du haut : ellipsis propre si le nom est long */
|
||||
|
||||
@@ -33,6 +33,15 @@
|
||||
const normalize = (s) => (s ?? "").toString().trim().toLowerCase();
|
||||
const proxify = (url) => url ? `/HelloFresh/ProxyPdf?url=${encodeURIComponent(url)}` : "";
|
||||
|
||||
// Détection iOS (iPhone/iPad et iPadOS mode desktop)
|
||||
const IS_IOS = /iPad|iPhone|iPod/.test(navigator.userAgent) || (navigator.userAgent.includes("Mac") && "ontouchend" in document);
|
||||
els.btnOpen?.addEventListener("click", () => {
|
||||
const r = RECIPES[CUR]; if (!r?.pdf) return;
|
||||
const u = `/HelloFresh/ProxyPdf?url=${encodeURIComponent(r.pdf)}`;
|
||||
if (IS_IOS) window.open(u, "_blank", "noopener"); else openViewer();
|
||||
});
|
||||
|
||||
|
||||
|
||||
function buildPdfSrc(rawUrl) {
|
||||
if (!rawUrl) return "";
|
||||
|
||||
@@ -5,7 +5,6 @@ let currentPage = 1;
|
||||
let lastPageGlobal = 1;
|
||||
const countPerPage = 12;
|
||||
let currentSearchTerm = '';
|
||||
const MAX_PORTIONS = 14;
|
||||
let CURRENT_CLIENT_LIST = null; // liste filtrée paginée côté client
|
||||
let ALL_RECIPES_CACHE = null; // toutes les recettes (toutes pages)
|
||||
|
||||
@@ -19,10 +18,19 @@ const labelMaps = { ingredients: {}, tags: {} };
|
||||
// idRecette -> portions (0..3)
|
||||
const ownedMap = new Map();
|
||||
|
||||
|
||||
const MAX_PER_RECIPE = null; // null = illimité par recette
|
||||
const MAX_TOTAL = null; // null = illimité au total
|
||||
const clampQty = (n) => {
|
||||
const v = Number(n) || 0;
|
||||
if (v < 0) return 0;
|
||||
// si bornes définies, on clamp ; sinon on laisse passer
|
||||
if (Number.isFinite(MAX_PER_RECIPE)) return Math.min(MAX_PER_RECIPE, v);
|
||||
return v;
|
||||
};
|
||||
/***********************
|
||||
* UTILS
|
||||
***********************/
|
||||
const clampQty = n => Math.max(0, Math.min(3, Number(n) || 0));
|
||||
const truncate = (s, m) => (s && s.length > m ? s.slice(0, m) + '…' : (s ?? ''));
|
||||
const normalize = (str) => (str ?? '').toString().normalize('NFD').replace(/[\u0300-\u036f]/g, '').toLowerCase().trim();
|
||||
const splitTags = (str) => (str || '').split(/[,•]/).map(t => t.trim()).filter(Boolean).filter(t => t !== '•');
|
||||
@@ -232,7 +240,12 @@ function buildRecipeCardList(recipe) {
|
||||
}
|
||||
|
||||
const current = clampQty(ownedMap.get(String(recipe.id)) || 0);
|
||||
if (current === 0 && !canAddPortion()) { alert(`Limite atteinte (${MAX_PORTIONS}).`); return; }
|
||||
if (current === 0 && !canAddPortion(recipe.id)) {
|
||||
// message seulement s'il y a vraiment une limite
|
||||
if (Number.isFinite(MAX_TOTAL)) alert(`Limite atteinte (${MAX_TOTAL}).`);
|
||||
else if (Number.isFinite(MAX_PER_RECIPE)) alert(`Limite par recette atteinte (${MAX_PER_RECIPE}).`);
|
||||
return;
|
||||
};
|
||||
const selectedNow = current > 0;
|
||||
if (!selectedNow) await saveRecipe(recipe.id); else await clearRecipe(recipe.id);
|
||||
applySelectionUIById(recipe.id);
|
||||
@@ -273,8 +286,15 @@ function buildRecipeCardOwned(recipe) {
|
||||
|
||||
// plus/moins existants
|
||||
card.querySelector('.btn-minus')?.addEventListener('click', (e) => { e.stopPropagation(); removeRecette(recipe.id); updateOwnedCountUI(); if (getTotalPortionsFromMap() === 0) closeOwnedIfOpen(); });
|
||||
card.querySelector('.btn-plus')?.addEventListener('click', (e) => { e.stopPropagation(); if (!canAddPortion()) { alert(`Limite atteinte (${MAX_PORTIONS}).`); return; } saveRecipe(recipe.id); updateOwnedCountUI(); });
|
||||
|
||||
card.querySelector('.btn-plus')?.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
if (!canAddPortion(recipe.id)) {
|
||||
if (Number.isFinite(MAX_TOTAL)) alert(`Limite atteinte (${MAX_TOTAL}).`);
|
||||
else if (Number.isFinite(MAX_PER_RECIPE)) alert(`Limite par recette atteinte (${MAX_PER_RECIPE}).`);
|
||||
return;
|
||||
}
|
||||
saveRecipe(recipe.id); updateOwnedCountUI();
|
||||
});
|
||||
// 🟢 Ctrl+clic = ouvrir le PDF (avec fallback GetRecipesDetails)
|
||||
card.addEventListener('click', async (e) => {
|
||||
if (!e.ctrlKey) return;
|
||||
@@ -743,12 +763,28 @@ function wireFooterButtons() {
|
||||
***********************/
|
||||
function getTotalPortionsFromMap() { let total = 0; ownedMap.forEach(v => { total += (Number(v) || 0); }); return total; }
|
||||
function updateOwnedCountUI() {
|
||||
const el = document.getElementById('ownedCount'); if (!el) return;
|
||||
const total = getTotalPortionsFromMap(); el.textContent = `(${total}/${MAX_PORTIONS})`;
|
||||
el.style.color = (total >= MAX_PORTIONS) ? '#c62828' : '';
|
||||
const el = document.getElementById('ownedCount'); if (!el) return;
|
||||
const total = getTotalPortionsFromMap();
|
||||
if (Number.isFinite(MAX_TOTAL)) {
|
||||
el.textContent = `(${total}/${MAX_TOTAL})`;
|
||||
el.style.color = (total >= MAX_TOTAL) ? '#c62828' : '';
|
||||
} else {
|
||||
// affichage sans borne
|
||||
el.textContent = `(${total})`;
|
||||
el.style.color = '';
|
||||
}
|
||||
}
|
||||
function canAddPortion(forRecipeId) {
|
||||
// limite globale
|
||||
if (Number.isFinite(MAX_TOTAL) && getTotalPortionsFromMap() >= MAX_TOTAL) return false;
|
||||
// limite par recette
|
||||
if (Number.isFinite(MAX_PER_RECIPE)) {
|
||||
const curr = Number(ownedMap.get(String(forRecipeId)) || 0);
|
||||
return curr < MAX_PER_RECIPE;
|
||||
}
|
||||
// illimité
|
||||
return true;
|
||||
}
|
||||
function canAddPortion() { return getTotalPortionsFromMap() < MAX_PORTIONS; }
|
||||
|
||||
/***********************
|
||||
* Ingredients meta attach (for page)
|
||||
***********************/
|
||||
|
||||
Reference in New Issue
Block a user