TGA-Shop Demo: Storefront (kein Passwort, Umami, Stripe-Checkout mit Demo-Fallback) + Shopify-Style-Admin; Datenschicht sqlite|directus

This commit is contained in:
2026-06-16 08:41:43 +00:00
commit 4f9a2cf512
77 changed files with 11485 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
const BASE = (process.env.UMAMI_API_URL || (process.env.UMAMI_SRC || 'https://analytics.heidrich-digital.de/script.js').replace(/\/script\.js$/, '')).replace(/\/$/, '');
export function umamiInfo() {
return { base: BASE, websiteId: process.env.UMAMI_WEBSITE_ID || '', hasCreds: !!(process.env.UMAMI_USER && process.env.UMAMI_PASS), shareUrl: process.env.UMAMI_SHARE_URL || '' };
}
export async function umamiStats() {
const id = process.env.UMAMI_WEBSITE_ID, user = process.env.UMAMI_USER, pass = process.env.UMAMI_PASS;
if (!id || !user || !pass) return { configured: false };
try {
const login = await fetch(`${BASE}/api/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username: user, password: pass }), signal: AbortSignal.timeout(7000) });
if (!login.ok) throw new Error('login');
const { token } = await login.json();
const end = Date.now(), start = end - 7 * 86400000;
const r = await fetch(`${BASE}/api/websites/${id}/stats?startAt=${start}&endAt=${end}`, { headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(7000) });
if (!r.ok) throw new Error('stats');
const s = await r.json();
const v = (x) => (x && typeof x === 'object') ? (x.value ?? 0) : (x ?? 0);
return { configured: true, pageviews: v(s.pageviews), visitors: v(s.visitors), visits: v(s.visits ?? s.sessions), bounces: v(s.bounces) };
} catch { return { configured: false, error: true }; }
}