import { useState, useEffect } from 'react'; import { api, S } from '../lib.js'; const GOLD = '#f59e0b'; function getMyRole() { try { return JSON.parse(atob(localStorage.getItem('sk_token').split('.')[1])).role; } catch { return null; } } function publisherColor(name) { if (!name) return '#555'; const n = name.toLowerCase(); if (n.includes('rewe')) return '#e2001a'; if (n.includes('edeka') || n.includes('e center')) return '#e8a800'; if (n.includes('netto')) return '#0057a8'; if (n.includes('trinkgut')) return '#e87722'; if (n.includes('penny')) return '#e2001a'; if (n.includes('kaufland')) return '#e2001a'; return '#888'; } function fmtDate(str) { if (!str) return null; try { return new Date(str).toLocaleDateString('de-DE', { day:'2-digit', month:'2-digit', year:'numeric' }); } catch { return str; } } // ── Angebots-Karte (marktguru) ──────────────────────────────────────────────── function OfferCard({ offer }) { const color = publisherColor(offer.retailer); return (
{/* Produktbild */} {offer.image && (
König Pilsener { e.target.parentElement.style.display='none'; }} /> {offer.oldPrice && (
-29%
)}
)}
{/* Händler Badge + Adresse */}
{offer.retailer}
{offer.address && (
📍 {offer.address}
)}
{/* König Pilsener */}
König Pilsener
{/* Flaschengröße/Beschreibung */} {offer.description && (
{offer.description}
)} {/* Preis */}
{offer.price} {offer.oldPrice && ( {offer.oldPrice} )}
{/* Gültigkeit */}
{offer.validity && (
⏰ {offer.validity}
)} {offer.dateRange && (
📅 Gültig: {offer.dateRange}
)}
); } // ── Prospekt-Karte (kaufda) ─────────────────────────────────────────────────── function ProspektCard({ b }) { const color = publisherColor(b.publisher); const isNew = b.badges?.includes('new'); const expiring = b.badges?.includes('expiring_soon'); return (
{b.image && ( {b.title} { e.target.style.display='none'; }} /> )}
{isNew && NEU} {expiring && ENDET BALD}
{b.publisher}
{b.title}
📍 {b.street || b.store}
{(b.validFrom || b.validTo) && (
{b.validFrom && `Ab ${fmtDate(b.validFrom)}`}{b.validFrom&&b.validTo&&' · '}{b.validTo&&`Bis ${fmtDate(b.validTo)}`}
)}
); } // ── Hauptkomponente ─────────────────────────────────────────────────────────── export default function Koepi({ toast }) { const [tab, setTab] = useState('angebote'); const [offers, setOffers] = useState(null); const [prospekte, setProspekte] = useState(null); const [loading, setLoading] = useState(false); const [showAll, setShowAll] = useState(false); const isAdmin = getMyRole() === 'admin'; const loadOffers = async (force=false) => { if (offers && !force) return; setLoading(true); try { setOffers(await api('/tools/koepi/offers')); } catch(e) { toast?.(e.message||'Fehler','error'); } finally { setLoading(false); } }; const loadProspekte = async (force=false) => { if (prospekte && !force) return; setLoading(true); try { setProspekte(await api('/tools/koepi/prospekte')); } catch(e) { toast?.(e.message||'Fehler','error'); } finally { setLoading(false); } }; useEffect(() => { if (tab === 'angebote') loadOffers(); else loadProspekte(); }, [tab]); const clearCache = async () => { try { await api('/tools/koepi/clear-cache', { body:{} }); setOffers(null); setProspekte(null); toast('Cache geleert'); setTimeout(() => { if (tab==='angebote') loadOffers(true); else loadProspekte(true); }, 100); } catch(e) { toast?.(e.message,'error'); } }; return (
{/* Header */}

🍺 KÖPI — König Pilsener

{isAdmin && ( )}
Raum Duisburg 47259 · EDEKA · REWE · Netto · Kaufland · Penny · Trinkgut · Cache 1h
{/* Tabs */}
{[['angebote','🍺 Angebote'],['prospekte','📋 Prospekte']].map(([t,l]) => ( ))}
{/* Laden */} {loading && (
⏳ Lade… (kann bis zu 20 Sekunden dauern)
)} {/* Angebote */} {!loading && tab==='angebote' && offers && (
{offers.offers?.length > 0 ? ( <>
{offers.offers.length} AKTUELLE ANGEBOTE · Quelle: marktguru.de
{offers.offers.map((o,i) => )}
) : (
Aktuell keine König Pilsener Angebote bei deinen Märkten gefunden.
)}
→ Alle Angebote auf marktguru.de
)} {/* Prospekte */} {!loading && tab==='prospekte' && prospekte && (
{prospekte.targeted?.length > 0 && ( <>
DEINE MÄRKTE ({prospekte.targeted.length})
{prospekte.targeted.map(b=>)}
)} {prospekte.others?.length > 0 && ( <> {showAll && (
{prospekte.others.map(b=>)}
)} )} {!prospekte.targeted?.length && !prospekte.others?.length && (
Keine Prospekte gefunden.
)}
)}
); }