Commit graph

14 commits

Author SHA1 Message Date
Maaxxs
438131fad0 Move FAQ management into the admin panel and cover it plus the gallery in export/import
FAQ entries were previously hardcoded in the i18n dictionaries; they now live
in a new bilingual `faqs` table with full CRUD in the admin panel, a
reset-to-defaults action seeded with the current 6 questions, and the
homepage (incl. FAQPage JSON-LD) fetches them live per language. Export/
import was also extended to include FAQs and the full image gallery
(brands, projects, photos), which had been missing from that mechanism.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 19:25:06 +02:00
Maaxxs
ec84b438ca PageSpeed/Lighthouse fixes: caching, images, touch targets, console noise
Based on a Lighthouse audit of the live site (95 performance / 91
accessibility / 96 best-practices / 100 SEO), addressing everything
except the flagged color-contrast issues (kept as-is, reversible
color changes need a separate decision):

- Cache-Control headers for hashed/immutable static assets via
  mod_headers (no mod_expires dependency, since that's not enabled
  everywhere) - ~1.1MB saved on repeat visits
- Converted the code-bundled homepage photos to WebP (skipped
  DB-managed/admin-uploaded images - those are content, not code) and
  added explicit width/height so the browser can reserve space before
  images load
- Bumped footer/contact-sidebar phone and email links to a 24px+
  touch target via padding
- /auth/me now returns 200 + {authenticated:false} instead of 401 for
  logged-out visitors - it's called on every public page load to
  check session state, so "not logged in" is the normal case, not an
  error; the 401 was showing up as a console error on literally every
  page view

Left unchanged: the lucide-react bundle splitting (a previous,
deliberate tradeoff - splitting per-icon created ~1600 tiny chunk
files that failed to upload on shared hosting) and video preload
(no concrete issue found in the audit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 02:40:57 +02:00
Maaxxs
24df7a602c Add Google Analytics dashboard widget (GA4 Data API integration)
New Dashboard section shows users/sessions/pageviews for the last 7
days plus top pages, fetched server-side via the GA4 Data API using a
Google service account (JWT-bearer flow, no OAuth consent screen
needed) - the same approach WordPress plugins like MonsterInsights use
to surface GA stats inline instead of linking out to analytics.google.com.

Backend: GoogleAnalyticsReporting support class (signs its own JWT with
openssl, exchanges it for an access token, calls runReport - no need
for the full Google API PHP client library for one endpoint) and
AnalyticsController (settings show/update, report fetch). The service
account JSON key is written to a gitignored config file, mirroring the
existing db.php/setup.php pattern for environment-specific secrets.

Admin: new "Dashboard-Anbindung" section in Website Settings (Property
ID + service account JSON paste, independent save action). Dashboard
gracefully shows a setup hint when not yet configured instead of an
error.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 01:57:32 +02:00
Maaxxs
93e245d3b9 Add SMTP debug logging and from/username mismatch warning to mail test
"Connection successful" only means the SMTP server accepted the
message, not that it was delivered. The test endpoint now captures the
full SMTP protocol exchange and shows it in the admin UI, plus flags
the common case where the sender address differs from the SMTP login
- many providers silently discard mail in that situation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 01:35:54 +02:00
Maaxxs
b5de375d7f Add Google Analytics integration with consent-gated loading
Adds a "Statistik" cookie category (alongside the existing external
media one), an admin-configurable Measurement ID field in Website
Settings, and a GoogleAnalytics component that only injects gtag.js
after the visitor has consented - mirrors the existing ExternalEmbed
pattern instead of loading tracking scripts unconditionally.

Also documents Google Analytics in the Datenschutzerklärung (new
section 8, remaining sections renumbered) since introducing a new
data processing purpose requires disclosure.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 01:32:44 +02:00
Maaxxs
0de35ef692 Add configurable SMTP email settings and contact-form email notifications
New admin panel "E-Mail" tab (Einstellungen -> E-Mail) lets the shop
owner configure their SMTP server, test the connection with a real
test email, set which address receives new-inquiry notifications, and
edit both the customer confirmation email and the shop notification
email as templates with {{placeholder}} variables.

Previously SMTP config only lived in a non-DB config.php file (with a
blank host, so mail sending was effectively off) and there was no
customer confirmation email at all - only a hardcoded owner
notification. ContactController now sends both emails using the
DB-configured (or config.php-fallback) settings; mail sending stays
best-effort so a contact form submission never fails because of it.

Backend: new Mailer support class (config resolution, PHPMailer setup,
placeholder rendering) and MailSettingsController (show/update/test),
following the existing WebsiteSettings/DatabaseSettings conventions
(password never returned in plaintext, empty password on save keeps
the existing one). New app_settings columns wired into Schema.php so
the "Datenbankstruktur aktualisieren" admin button picks them up on
existing installs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-07 00:54:17 +02:00
Maaxxs
e234a2435d Add photo gallery feature (brand -> project -> photos drill-down)
Mirrors the old site's Bildergalerie structure: a brand tile grid at
/galerie, project tiles within a brand, and a photo grid with a
lightbox for each project. Backed by new gallery_brands/gallery_projects/
gallery_photos tables and admin CRUD pages, gated by a new gallery.manage
permission.

Also fixes a real bug found while testing photo uploads: Apache's
mod_dir was redirecting POST /api/uploads to /api/uploads/ (a trailing
slash) because api/uploads/ exists as a real directory, silently
dropping the multipart body on every image upload across the whole
app. Fixed via DirectorySlash Off in .htaccess.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 17:04:46 +02:00
Maaxxs
95764039c7 Add admin-configurable website settings and VIN field to contact form
Adds a Website settings tab (hero image, phone, WhatsApp, email) that
feeds the navbar, footer and contact page via a new SiteSettingsContext,
redesigns the navbar with a bigger centered logo plus phone/WhatsApp/shop
links, and adds a VIN/chassis-number field to the contact form, admin
inbox and notification email.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 15:28:11 +02:00
Maaxxs
72a7cb928e Fix API responses silently becoming null on the live server
Symptom: Admin-Login zeigte "Cannot read properties of null (reading
'requires_2fa')". Ursache: falls vor den header()-Aufrufen in index.php
irgendeine Ausgabe passiert (z.B. eine PHP-Notice - passiert offenbar auf
PHP 8.4 anders als lokal auf 8.2), geht der Content-Type-Header verloren,
und der Client hat JSON-Antworten dann still als null behandelt statt
sie zu parsen. Backend puffert Ausgaben jetzt und verwirft ungewollten
Output vor den Headern; Client versucht JSON-Parsing jetzt unabhaengig
vom Content-Type-Header und wirft einen klaren Fehler statt still null
zurueckzugeben.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 16:16:11 +02:00
Maaxxs
75684df837 Simplify to always run at domain root instead of dual /hifi vs / support
Statt Env-Var-gesteuertem Dualbetrieb (lokal /hifi, live /) läuft jetzt
alles einheitlich unter der Domain-Wurzel - auch lokal (siehe neuer
VirtualHost auf Port 8080 in der Apache-Konfiguration, unabhängig von
Port 80 mit /hifi). Dabei einen Doppel-Slash-Bug in der Routenberechnung
gefunden und behoben (base_path '/' + '/api' ergab faelschlich '//api').

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 15:04:39 +02:00
Maaxxs
618a32182c Make base path configurable for root-domain deployment (IONOS)
Bisher war /hifi an mehreren Stellen fest einprogrammiert (vite base,
Router basename, API-Client, Upload-URLs, .htaccess). Fuer den geplanten
Deploy auf IONOS unter der Domain-Wurzel wird das jetzt ueber
VITE_BASE_PATH (Frontend-Build) bzw. eine optionale base_path.php
(Backend, gleiches Muster wie db.php/setup.php) gesteuert - lokal ohne
diese Werte bleibt alles unveraendert bei /hifi.

.htaccess.ionos enthaelt die Root-Domain-Variante fuer den CI-Build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 14:23:30 +02:00
Maaxxs
a3854fe5b8 Fix fatal error when db.php doesn't exist yet on a fresh deployment
config.php and SetupController beide luden db.php bisher ungeprueft per
require, was auf einem frischen Server (vor der Ersteinrichtung) zu
einem fatalen Fehler gefuehrt haette, noch bevor /setup ueberhaupt
erreichbar ist. Faellt jetzt auf eine leere Config zurueck.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 14:08:14 +02:00
Maaxxs
fe6b463135 Add first-time setup wizard (/setup)
Passwortgeschuetzter Assistent fuer die Ersteinrichtung auf einem neuen
Server: Datenbank-Zugangsdaten testen & speichern, Datenbankstruktur
anlegen, ersten Admin-Account erstellen. Sperrt sich danach dauerhaft
selbst, sobald ein Admin-Account existiert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 14:06:12 +02:00
Maaxxs
f3ab7d0816 Initial commit: HifiPlanet Car-Hifi Shop (Frontend + Backend)
React/Vite Frontend (hifi-src) + PHP/MariaDB Backend (hifi/api) fuer
den Car-Hifi Umbau-Shop HifiPlanet in Amorbach, inkl. Admin-Panel,
2FA, Wartungsmodus, Cookie-Consent und rechtlichen Pflichtseiten.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 13:37:06 +02:00