feat: KoePi bestellmagazin-Filter, KW ohne Klammern erkannt, kommende Prospekte nach Woche unterteilt, Bier-Icon-Prospekte nach oben sortiert

This commit is contained in:
2026-07-18 10:57:49 +02:00
parent c1693c93c8
commit 824e76a107
2 changed files with 53 additions and 9 deletions

View File

@@ -45,6 +45,39 @@ function fmtDate(str) {
catch { return str; }
}
// Prospekte mit Bier-Icon (König Pilsener im Angebot) immer nach oben,
// ansonsten Reihenfolge vom Backend (chronologisch) beibehalten
function sortBeerFirst(arr) {
return [...arr].sort((a, b) => (b.hasKoenigPilsener?1:0) - (a.hasKoenigPilsener?1:0));
}
// ISO-Kalenderwoche aus einem Datum berechnen
function getISOWeek(dateStr) {
const d = new Date(dateStr);
d.setHours(0,0,0,0);
d.setDate(d.getDate() + 4 - (d.getDay() || 7));
const yearStart = new Date(d.getFullYear(), 0, 1);
return { week: Math.ceil((((d - yearStart) / 86400000) + 1) / 7), year: d.getFullYear() };
}
// Kommende Prospekte nach Kalenderwoche gruppieren, Gruppen chronologisch sortiert
function groupByWeek(arr) {
const groups = new Map();
for (const b of arr) {
if (!b.validFrom) { // kein Datum -> eigene Sammelgruppe ganz unten
const key = 'unbekannt';
if (!groups.has(key)) groups.set(key, { label: 'Ohne Datum', sortKey: Infinity, items: [] });
groups.get(key).items.push(b);
continue;
}
const { week, year } = getISOWeek(b.validFrom);
const key = `${year}-${week}`;
if (!groups.has(key)) groups.set(key, { label: `KW${week}`, sortKey: year*100+week, items: [] });
groups.get(key).items.push(b);
}
return [...groups.values()].sort((a,b) => a.sortKey - b.sortKey);
}
// ── Angebots-Karte (marktguru) ────────────────────────────────────────────────
function OfferCard({ offer }) {
const color = publisherColor(offer.retailer);
@@ -301,7 +334,7 @@ export default function Koepi({ toast }) {
<>
<div style={{ ...S.head, marginBottom:12 }}>DEINE MÄRKTE AKTUELL ({prospekte.current.length})</div>
<div style={{ display:'grid', gridTemplateColumns:'repeat(2,1fr)', gap:12, marginBottom:24 }}>
{prospekte.current.map(b=><ProspektCard key={b.id} b={b}/>)}
{sortBeerFirst(prospekte.current).map(b=><ProspektCard key={b.id} b={b}/>)}
</div>
</>
)}
@@ -311,9 +344,16 @@ export default function Koepi({ toast }) {
color:'rgba(255,255,255,0.35)' }}>
KOMMENDE PROSPEKTE ({prospekte.future.length})
</div>
<div style={{ display:'grid', gridTemplateColumns:'repeat(2,1fr)', gap:12, opacity:0.75 }}>
{prospekte.future.map(b=><ProspektCard key={b.id} b={b}/>)}
</div>
{groupByWeek(prospekte.future).map(group => (
<div key={group.label} style={{ marginBottom:20 }}>
<div style={{ color:'rgba(255,255,255,0.3)', fontFamily:'monospace', fontSize:10, letterSpacing:1, marginBottom:8 }}>
{group.label}
</div>
<div style={{ display:'grid', gridTemplateColumns:'repeat(2,1fr)', gap:12, opacity:0.75 }}>
{sortBeerFirst(group.items).map(b=><ProspektCard key={b.id} b={b}/>)}
</div>
</div>
))}
</>
)}
{!prospekte.current?.length && !prospekte.future?.length && (