v2.3: Feature-Module live — Suche, Merkliste, Kundenkonten+Adressbuch, Bewertungen, Abandoned-Cart

- feature_search: Storefront-Header-Suche + /suche (SSR, SQLite LIKE, case-insensitiv; Name/Kurz/Desc/Material/Kategorie), Treffer als Karten, Leer-Zustand
- feature_wishlist: Herz-Button auf Karten/PDP (localStorage, public/wishlist.js) + /merkliste
- feature_accounts: getrennte Kunden-Session (Cookie hdc_customer, scrypt), /konto/registrieren|anmelden|abmelden, /konto (Bestellhistorie+Adressbuch), Tabelle customer_addresses, Checkout-Vorbefuellung + orders.customer_id-Zuordnung; Gast-Checkout bleibt
- feature_reviews: Tabelle reviews (1-5, Moderation), /api/review (approved=0), PDP-Anzeige Durchschnitt+Reviews + aggregateRating-JSON-LD, Admin /bewertungen (Freigeben/Verbergen/Loeschen) + Nav-Zaehler
- feature_abandoned_cart: Tabelle abandoned_carts, /api/cart-capture beim Checkout-Start, /api/cron/abandoned (CRON_TOKEN) sendet Erinnerungsmail (Mailer/Log) + reminded=1, recovered=1 bei Bestellung; Status in Einstellungen
- Gating: Flag aus => Storefront-Elemente weg, Routen 302/404, Admin-Nav-Punkt entfaellt; KEIN 'in Vorbereitung' mehr
- API/MCP: reviews CRUD + abandoned_carts (read) in admin-api + ai-admin.txt + MCP-Tools; Manifest v2.3
- README + .env.example (CRON_TOKEN, ABANDONED_AFTER_MINUTES); 16 neue Unit-Tests (Suche/Review-Avg/Kunden/Abandoned)
This commit is contained in:
2026-06-18 07:27:34 +00:00
parent 3fe80e76dd
commit 30c41c355e
32 changed files with 1181 additions and 42 deletions
+3
View File
@@ -238,3 +238,6 @@
.s-feed-row .t{color:var(--s-faint);margin-left:auto;font-size:12px;white-space:nowrap}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes pop{from{opacity:0;transform:translateY(-6px) scale(.98)}to{opacity:1;transform:none}}
/* v2.3 — Bewertungs-Zähler in der Nav */
.s-nav-badge{margin-left:auto;min-width:18px;height:18px;padding:0 5px;border-radius:999px;background:var(--accent);color:#fff;font-size:11px;font-weight:700;display:inline-flex;align-items:center;justify-content:center;line-height:1}
+75
View File
@@ -262,3 +262,78 @@ p{margin:0 0 1rem}
.blk-cta-box .btn-primary:hover{background:rgba(255,255,255,.9)}
.blk-html{padding:8px 0}
@media(max-width:760px){.blk-feat-grid{grid-template-columns:1fr}.blk-gal-grid{grid-template-columns:repeat(2,1fr)!important}}
/* ============ v2.3 Feature-Module: Suche, Merkliste, Konto, Bewertungen ============ */
/* Header-Suche */
.head-search{display:flex;align-items:center;gap:8px;background:var(--sunken);border:1px solid var(--border);border-radius:999px;padding:7px 14px;transition:.15s;max-width:220px}
.head-search:focus-within{border-color:var(--accent);background:var(--surface)}
.head-search svg{width:18px;height:18px;color:var(--faint);flex-shrink:0}
.head-search input{border:none;background:transparent;outline:none;font-size:14px;color:var(--ink);width:100%;min-width:0}
.search-page-form{display:flex;gap:10px;margin-top:18px;max-width:540px}
.search-page-form input{flex:1;padding:13px 16px;border:1px solid var(--border-2);border-radius:var(--radius-sm);font-size:15px;background:var(--surface)}
.search-page-form input:focus{outline:none;border-color:var(--accent)}
@media(max-width:760px){.head-search{display:none}}
/* Merkliste / Wunschliste */
.wish-badge{position:absolute;top:4px;right:4px;min-width:18px;height:18px;padding:0 4px;border-radius:999px;background:var(--accent);color:#fff;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center;line-height:1}
.wish-badge.show{display:flex}
.prod-card-wrap{position:relative;display:flex}
.prod-card-wrap .prod-card{flex:1}
.wish-btn{position:absolute;top:12px;right:12px;z-index:3;width:38px;height:38px;border-radius:999px;border:1px solid var(--border);background:rgba(255,255,255,.92);color:var(--subtle);display:grid;place-items:center;cursor:pointer;transition:.15s;backdrop-filter:blur(4px)}
.wish-btn:hover{color:var(--accent);border-color:var(--accent);transform:scale(1.06)}
.wish-btn svg{width:19px;height:19px;fill:none}
.wish-btn.active{color:var(--accent);border-color:var(--accent)}
.wish-btn.active svg{fill:var(--accent)}
.wish-btn-lg{position:static;width:54px;height:auto;border-radius:var(--radius-sm);flex-shrink:0}
.wish-btn-lg svg{width:22px;height:22px}
/* Konto / Auth */
.auth-card{max-width:440px;margin:56px auto;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:36px;box-shadow:var(--shadow)}
.auth-card h1{margin-bottom:6px}
.auth-error{background:color-mix(in srgb,#b3261e 10%,white);color:#b3261e;border:1px solid color-mix(in srgb,#b3261e 30%,white);padding:11px 14px;border-radius:var(--radius-sm);font-size:14px;margin-bottom:18px}
.auth-flash{background:color-mix(in srgb,var(--accent) 12%,white);color:var(--accent-dark);border:1px solid color-mix(in srgb,var(--accent) 28%,white);padding:11px 14px;border-radius:var(--radius-sm);font-size:14px;margin:18px 0}
.konto-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap;padding:44px 0 8px;border-bottom:1px solid var(--border);margin-bottom:8px}
.konto-orders{display:flex;flex-direction:column;gap:12px}
.konto-order{display:grid;grid-template-columns:auto 1fr auto;grid-template-areas:"num status total" "date items total";gap:4px 16px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:16px 20px;align-items:center}
.ko-top{grid-area:num;display:flex;gap:10px;align-items:center}
.ko-num{font-weight:700;color:var(--ink)}
.ko-status{font-size:12px;font-weight:700;padding:3px 9px;border-radius:999px;background:var(--sunken);color:var(--subtle)}
.ko-status.ko-paid,.ko-status.ko-fulfilled{background:color-mix(in srgb,#2e7d32 14%,white);color:#2e7d32}
.ko-status.ko-pending{background:color-mix(in srgb,#b8860b 16%,white);color:#8a6d00}
.ko-date{grid-area:date;font-size:13px;color:var(--faint)}
.ko-items{grid-area:items;font-size:14px;color:var(--subtle)}
.ko-total{grid-area:total;font-weight:700;font-size:17px;color:var(--ink);white-space:nowrap}
.konto-addr-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:16px;margin-bottom:20px}
.konto-addr{position:relative;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:18px 20px}
.konto-addr.is-default{border-color:var(--accent)}
.addr-default-badge{position:absolute;top:14px;right:14px;font-size:11px;font-weight:700;color:var(--accent);background:color-mix(in srgb,var(--accent) 12%,white);padding:3px 9px;border-radius:999px}
.addr-name{font-weight:700;color:var(--ink);margin-bottom:6px}
.addr-lines{font-size:14px;color:var(--subtle);line-height:1.55}
.addr-actions{margin-top:14px;display:flex;gap:14px}
.addr-link{background:none;border:none;padding:0;font-size:13px;color:var(--accent);cursor:pointer;font-weight:600}
.addr-link.danger{color:#b3261e}
.addr-add{margin-top:8px}
.addr-add summary{cursor:pointer;font-weight:600;color:var(--accent);display:inline-block;padding:8px 0}
.addr-form{margin-top:14px;max-width:520px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:22px}
/* Bewertungen (PDP) */
.pdp-rating{font-size:15px}
.rev-summary{margin-bottom:24px}
.rev-avg{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.rev-avg-num{font-family:var(--serif);font-size:42px;color:var(--ink);line-height:1}
.rev-stars{color:var(--accent);font-size:22px;letter-spacing:2px}
.rev-count{color:var(--faint);font-size:14px}
.rev-list{display:flex;flex-direction:column;gap:16px;margin-bottom:32px}
.rev-item{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:18px 20px}
.rev-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:6px}
.rev-name{font-weight:700;color:var(--ink)}
.rev-stars-sm{color:var(--accent);letter-spacing:1px}
.rev-text{color:var(--text);margin:6px 0;line-height:1.6}
.rev-date{font-size:12px;color:var(--faint)}
.rev-form-card{background:var(--sunken);border:1px solid var(--border);border-radius:var(--radius);padding:26px;max-width:560px}
.rev-stars-input{display:flex;gap:4px;margin-bottom:16px}
.rev-star-btn{background:none;border:none;font-size:32px;line-height:1;color:var(--border-2);cursor:pointer;padding:0;transition:.1s}
.rev-star-btn.on{color:var(--accent)}
.rev-form-card .field label{font-weight:600;font-size:14px;color:var(--ink)}
.rev-form-card input,.rev-form-card textarea{padding:11px 13px;border:1px solid var(--border-2);border-radius:var(--radius-sm);font-size:15px;font-family:inherit;background:var(--surface)}
.rev-form-card input:focus,.rev-form-card textarea:focus{outline:none;border-color:var(--accent)}