Refactor database handling to require PostgreSQL connection, removing fallback to JSON. Implement error handling for database unavailability in key files. Update .env.example to reflect mandatory DATABASE_URL for local development. Remove Firebase configuration and related code from the project.
This commit is contained in:
+28
-50
@@ -12,10 +12,10 @@ Dieses Dokument enthält den aktuellen Entwicklungsstand und detaillierte Aufgab
|
||||
- Fullscreen Overlay-Navigation (`LiquidOverlayMenu` & `SlideUpTextHover`)
|
||||
- Geschmeidiges Scrollverhalten (`LenisSmoothScroll` & `IndexSectionIndicator`)
|
||||
- Layout-Raster (`FloemaLayoutGrid`) & Premium-Buttons
|
||||
- [x] **Phase 2: Authentifizierung & Firebase Integration**
|
||||
- Firebase-Projekt Setup & Anbindung
|
||||
- Newsletter-System (Firebase Firestore)
|
||||
- Benutzerprofile (Registrierung, Login, Favoriten)
|
||||
- [x] **Phase 2: Profil & Personalisierung (lokal)**
|
||||
- Ernährungsziel & Favoriten im Browser (`fc-local.js`)
|
||||
- Newsletter per Mailto
|
||||
- Profilseite `login.php`
|
||||
- [x] **Phase 3: Nährwerte & Rezepterweiterung**
|
||||
- Datenmodell & Admin.php Erweiterung
|
||||
- Visuelles Nährwert-Widget (Floema-Präzision)
|
||||
@@ -28,12 +28,10 @@ Dieses Dokument enthält den aktuellen Entwicklungsstand und detaillierte Aufgab
|
||||
- Touch-Swipe-Karussell direkt auf index.php (unter Landing-Page)
|
||||
- Filteralgorithmus nach Benutzer-Ernährungszielen
|
||||
- Mikro-Animationen & Quick-Save Funktion
|
||||
- [/] **Phase 6: Firebase Firestore Datenbank-Migration & Seeding**
|
||||
- Firebase CLI-Login & Projekt-Initialisierung
|
||||
- .env-Konfiguration mit Firebase App Credentials
|
||||
- Client-seitiger "Seed Firestore"-Button in admin.php
|
||||
- Firestore REST API Integration in helpers.php
|
||||
- Echtzeit-Zwei-Wege-Sync bei Rezeptänderungen in admin.php
|
||||
- [x] **Phase 6: PostgreSQL Datenbank**
|
||||
- `DATABASE_URL` in `.env`, Docker Compose für lokale Dev-DB
|
||||
- `init_db()` / `save_recipes()` in `helpers.php`
|
||||
- Fallback auf `data/recipes.json`
|
||||
|
||||
---
|
||||
|
||||
@@ -66,26 +64,17 @@ Das visuelle Fundament der Website. Die Etablierung des Premium-Designs stellt s
|
||||
|
||||
---
|
||||
|
||||
### 🔒 Phase 2: Authentifizierung & Firebase Integration
|
||||
Das Fundament für Personalisierung und Newsletter-Abos über eine sichere Firebase-Anbindung (Auth & Firestore).
|
||||
### 🔒 Phase 2: Profil & Personalisierung (lokal)
|
||||
Favoriten, Ernährungsziel und Newsletter ohne Cloud-Backend.
|
||||
|
||||
- [x] **Firebase Setup & Initialisierung**
|
||||
- [x] Firebase SDK Client-Side Einbindung in `partials/head.php` or separaten Helper
|
||||
- [x] Firebase Config in umweltabhängigen Settings/Variablen auslagern
|
||||
- [x] Firestore-Datenbank initialisieren (`subscribers` und `users` Collections)
|
||||
- [x] **Premium Login- & Registrierungsseite**
|
||||
- [x] Erstellung der Seite `login.php` (und optional `signup.php`) im neuen Design-System-Stil
|
||||
- [x] Firebase Authentication (Email/Passwort Login & Registrierung) implementieren
|
||||
- [x] Responsive UI mit sanften Error- & Success-Meldungen und Eingabefeldern im Glasmorphismus-Look
|
||||
- [x] Client-seitige und Server-seitige Session-Synchronisation (z.B. Firebase Session Tokens an PHP-Session via Ajax senden)
|
||||
- [x] **Profilseite `login.php`**
|
||||
- [x] Ernährungsziel wählen und in `localStorage` speichern (`fc-local.js`)
|
||||
- [x] Gespeicherte Favoriten anzeigen
|
||||
- [x] **Favoriten-Funktion (Rezept-Bookmarks)**
|
||||
- [x] Firestore-Collection `user_favorites` anlegen (Format: `userId` -> Liste von `recipeSlugs`)
|
||||
- [x] "Rezept speichern" Button (Herz-Icon) auf den Rezeptkarten und Rezept-Details mit dynamischem Login-Check
|
||||
- [x] Mikro-Animationen für das Herz-Icon (Scale up/down, Fülleffekte mit `var(--ease-overshoot)`)
|
||||
- [x] **Firebase-gestütztes Newsletter-Abo**
|
||||
- [x] Newsletter-Eingabefeld im Footer (`partials/footer.php`) implementieren
|
||||
- [x] AJAX-Submit-Handler: E-Mail-Adresse prüfen und in Firestore Collection `subscribers` speichern
|
||||
- [x] Elegantes Feedback-UI (Erfolgsmeldung ohne Page-Reload)
|
||||
- [x] Herz-Icon auf Karten, Speicherung in `localStorage`
|
||||
- [x] Mikro-Animationen für das Herz-Icon
|
||||
- [x] **Newsletter**
|
||||
- [x] Footer-Formular mit `mailto:`-Weiterleitung
|
||||
|
||||
---
|
||||
|
||||
@@ -112,7 +101,7 @@ Jedes Rezept erhält präzise Makronährstoffe (Kalorien, Proteine, Kohlenhydrat
|
||||
Ein immersiver Kochmodus, der Anwendern Schritt-für-Schritt durch die Zubereitung führt – inklusive Videoanleitungen und integrierten Timern.
|
||||
|
||||
- [x] **Video-Verknüpfung im Admin-Panel**
|
||||
- [x] Rezeptstruktur in `data/recipes.json` erweitern, damit jeder Arbeitsschritt (`steps`) eine optionale `video_url` (MP4 aus Firebase Storage oder extern) besitzen kann
|
||||
- [x] Rezeptstruktur in `data/recipes.json` erweitern, damit jeder Arbeitsschritt (`steps`) eine optionale `video_url` (externe MP4-URL) besitzen kann
|
||||
- [x] `admin.php` erweitern, um Video-URLs pro Einzelschritt einzugeben
|
||||
- [x] **Fullscreen Cooking-Mode Overlay**
|
||||
- [x] Trigger-Button "Kochmodus starten" (`CapitoliumRevealButton` Stil) auf `recipe.php` einbauen
|
||||
@@ -134,36 +123,25 @@ Ein hochgradig interaktives, touch-freundliches Karussell direkt auf der Startse
|
||||
- [x] CSS-Klammern (`clamp()`) für responsive Skalierung der Karten
|
||||
- [x] Flüssiges Einblenden per Scroll-Reveal (`reveal-target`) mit Anbindung an `LenisSmoothScroll`
|
||||
- [x] **Personalisiertes Goal-Matching**
|
||||
- [x] Falls der Benutzer eingeloggt ist, sein Ernährungsziel aus den Firebase-Profildaten abrufen
|
||||
- [x] Ernährungsziel aus `localStorage` (`fc-local.js`) für Karussell-Filter
|
||||
- [x] Rezepte dynamisch filtern (z.B. High-Protein Rezepte bei Ziel "Muskelaufbau", Low-Carb Rezepte bei Ziel "Abnehmen")
|
||||
- [x] Personalisierte "Für dich empfohlen"-Badge auf den Karten anzeigen
|
||||
- [x] **Mikro-Interaktionen & Quick-Save**
|
||||
- [x] Touch-Gesten-Unterstützung (Wischen zum Blättern mit sanftem Trägheits-Feedback)
|
||||
- [x] Quick-Save Button direkt auf den Karussell-Karten (Herzeffekt mit direktem Firebase Firestore Sync)
|
||||
- [x] Quick-Save Button direkt auf den Karussell-Karten (Herzeffekt, `localStorage`)
|
||||
- [x] Hover-Reveal-Effekte für Rezeptdetails (Zutaten-Vorschau oder Kochzeit-Highlight schiebt sich weich hoch)
|
||||
|
||||
---
|
||||
|
||||
### 🔥 Phase 6: Firebase Firestore Datenbank-Migration & Seeding
|
||||
Migration des lokalen JSON-Flachdateispeichers auf eine skalierbare, cloudbasierte Firestore-Struktur.
|
||||
### 🔥 Phase 6: PostgreSQL Datenbank
|
||||
Rezepte in Postgres (JSONB), optional lokal per Docker.
|
||||
|
||||
- [/] **Firebase-Projekt & CLI-Setup**
|
||||
- [x] Firebase-Verzeichnis-Umgebung initialisieren und anbinden
|
||||
- [/] Firebase CLI Login durchführen und aktiven Account verknüpfen
|
||||
- [ ] Firebase Project & Web App ermitteln oder neu anlegen
|
||||
- [ ] Lokale `.env`-Konfiguration mit Firebase SDK Parametern befüllen
|
||||
- [ ] **Client-seitiges Daten-Seeding**
|
||||
- [ ] "Seed Firestore"-Aktion im Admin-Bereich (`admin.php`) einbauen
|
||||
- [ ] Batch-Dokumentenupload der `recipes.json`-Einträge in die Firestore Collection `recipes` über JS SDK
|
||||
- [ ] Firestore Security Rules für den öffentlichen Lesezugriff anpassen
|
||||
- [ ] **Firestore Server-seitiger Abruf (PHP REST API)**
|
||||
- [ ] Firestore REST API Parser-Helfer in `helpers.php` implementieren (Transformation von Firestore Key-Maps in Standard-Arrays)
|
||||
- [ ] `load_recipes()` auf REST API GET `/recipes` umstellen
|
||||
- [ ] Neue Funktion `load_recipe_by_slug($slug)` für gezielten Einzelabruf implementieren und in `recipe.php` integrieren
|
||||
- [ ] **Zwei-Wege-Echtzeit-Synchronisierung (Admin)**
|
||||
- [ ] `save_recipes()` so anpassen, dass lokales JSON als Fallback-Backup erhalten bleibt
|
||||
- [ ] Client-seitigen Trigger nach erfolgreichem PHP-Speichern in `admin.php` ausführen, um Änderungen sofort in Firestore zu spiegeln
|
||||
- [ ] Funktionstest: Hinzufügen, Editieren und Löschen von Rezepten über die Admin-Konsole verifizieren
|
||||
- [x] **`DATABASE_URL` & Docker Compose**
|
||||
- [x] `docker-compose.dev.yml` für lokale Postgres-Instanz
|
||||
- [x] `init_db()` legt Tabelle `recipes` an und seedet aus `recipes.json`
|
||||
- [x] **PHP-Datenzugriff**
|
||||
- [x] `load_recipes()` / `save_recipes()` mit JSON-Fallback
|
||||
- [x] `load_recipe_by_slug()` in `recipe.php`
|
||||
|
||||
---
|
||||
|
||||
|
||||
+25
-32
@@ -4,11 +4,11 @@ This document summarizes architectural knowledge, conventions, and learnings for
|
||||
|
||||
## 1. Project Architecture & Stack
|
||||
- **Backend:** Vanilla PHP. No heavy frameworks.
|
||||
- **Database:** PostgreSQL (optional) via `DATABASE_URL` in `.env`, with automatic seed from and backup to `data/recipes.json`. All data access lives in `helpers.php`; connection logic in `config.php`.
|
||||
- **Database:** PostgreSQL required (`DATABASE_URL` in `.env`). Normalized tables in `scripts/schema.sql`; `load_recipes()` / `save_recipe()` in `helpers.php`. No runtime JSON recipe file. One-time import: `php scripts/db-seed.php` from `data/recipes.json`.
|
||||
- **Site settings (legal pages):** Flat-file `data/site.json` via `load_site_settings()` / `save_site_settings()` — not in Postgres.
|
||||
- **Admin Panel (`admin.php`):** Lightweight CMS. Textareas use one line per array element (`ingredients`, `steps`, `step_videos`, `step_timers`).
|
||||
- **Frontend:** Server-rendered PHP (`index.php`, `recipe.php`, …), Vanilla JS/CSS. Firebase compat SDKs in `partials/head.php` for auth, Firestore (newsletter/bookmarks where used).
|
||||
- **Config:** `config.php` loads `.env`, exposes `get_firebase_config()`, `get_db_connection()`. Never commit `.env` (see `.gitignore`).
|
||||
- **Frontend:** Server-rendered PHP (`index.php`, `recipe.php`, …), Vanilla JS/CSS. Profile/favorites via `assets/fc-local.js`.
|
||||
- **Config:** `config.php` loads `.env`, `get_db_connection()`. Never commit `.env` (see `.gitignore`).
|
||||
|
||||
## 2. Design & Aesthetics
|
||||
- **CSS:** Custom properties (`var(--ease-out-expo)`, `var(--surface-1)`), glassmorphism, `FloemaLayoutGrid`.
|
||||
@@ -26,29 +26,27 @@ This document summarizes architectural knowledge, conventions, and learnings for
|
||||
|
||||
## 5. PostgreSQL — Schema & Data Flow
|
||||
|
||||
### Table `recipes` (only app table today)
|
||||
Created by `init_db()` in `helpers.php` if missing:
|
||||
### Relational schema (`scripts/schema.sql`)
|
||||
Created by `ensure_recipe_schema()` on first DB use. Legacy JSONB `recipes.data` is migrated once automatically.
|
||||
|
||||
| Column | Type | Role |
|
||||
|-------------|-------------|------|
|
||||
| `slug` | `VARCHAR(255)` PRIMARY KEY | Stable recipe ID (URLs: `recipe.php?slug=…`) |
|
||||
| `data` | `JSONB` NOT NULL | **Entire recipe document** (title, i18n, ingredients, steps, nutrition, …) |
|
||||
| `created_at`| `TIMESTAMP` | Auto on insert |
|
||||
| `updated_at`| `TIMESTAMP` | Set on `ON CONFLICT` update in `save_recipes()` |
|
||||
| Table | Role |
|
||||
|-------|------|
|
||||
| `recipes` | slug, hero, times, servings, nutrition columns, featured, coming_soon |
|
||||
| `recipe_translations` | title, description, category, difficulty (en/de) |
|
||||
| `recipe_tags`, `recipe_ingredients`, `recipe_utensils`, `recipe_steps` | Ordered lists per language |
|
||||
|
||||
**Design choice:** Document-in-a-row (JSONB), not normalized columns. PHP already works with JSON arrays; avoids schema migrations for every new recipe field. PostgreSQL can still query inside JSON (`data->'i18n'->'en'->>'title'`).
|
||||
PHP still exposes the same nested arrays (`i18n`, `nutrition`, …) via `hydrate_recipes_from_db()`.
|
||||
|
||||
### Runtime flow
|
||||
1. `get_db_connection()` in `config.php` parses `DATABASE_URL` → PDO `pgsql:` DSN.
|
||||
2. If no URL or connection fails → `load_recipes_local()` reads `data/recipes.json` only.
|
||||
3. If connected → `init_db()` once per request (static flag): `CREATE TABLE IF NOT EXISTS`, then if `COUNT(*) = 0` → seed all rows from `data/recipes.json`.
|
||||
4. `load_recipes()` / `load_recipe_by_slug()` decode `data` JSONB to PHP arrays.
|
||||
5. `save_recipes()` (admin): upsert all recipes in Postgres **and** write `data/recipes.json` as backup.
|
||||
1. `DATABASE_URL` required → `require_database()` or HTTP 503 (`maintenance/db-unavailable.php`).
|
||||
2. `load_recipes()` → SQL → PHP arrays for templates.
|
||||
3. Admin: `save_recipe()`, `delete_recipe()`, `clear_featured_recipes()`.
|
||||
4. One-time import: `php scripts/db-seed.php` from `data/recipes.json` (not read at runtime).
|
||||
|
||||
### `config.php` functions
|
||||
- `load_env()` — parses `.env` into `getenv()` / `$_ENV` / `$_SERVER`.
|
||||
- `get_firebase_config()` — returns Firebase web config array from `FIREBASE_*` env vars. **Required** by `partials/head.php` and `admin.php`. Was accidentally removed in postgres commit `e7f35d7`; restored (undefined function caused HTTP 500).
|
||||
- `get_db_connection()` — returns `PDO` or `null`; logs failures, does not throw.
|
||||
- `load_env()` — parses `.env`.
|
||||
- `get_db_connection()` — PDO or `null`.
|
||||
- `DatabaseUnavailableException` — thrown when DB is required but missing.
|
||||
|
||||
---
|
||||
|
||||
@@ -79,7 +77,7 @@ docker exec -it flixcooks-postgres-dev psql -U flixcooks -d flixcooks_dev
|
||||
```
|
||||
|
||||
### PHP requirements (WSL/Linux)
|
||||
- Extension **`php-pgsql`** (or `php8.5-pgsql`) required; without it: log `could not find driver`, fallback to JSON.
|
||||
- Extension **`php-pgsql`** (or `php8.5-pgsql`) required; without it the site cannot connect.
|
||||
- Install interactively: `sudo apt install php8.5-pgsql` (sudo in non-interactive agent shells may timeout).
|
||||
- Verify: `php -m | grep pgsql` → expect `pdo_pgsql`, `pgsql`.
|
||||
|
||||
@@ -92,14 +90,12 @@ php scripts/db-check.php # after .env + pgsql OK
|
||||
### `.env` rules for agents
|
||||
- Copy from `.env.example`; never commit `.env`.
|
||||
- **Local:** use `127.0.0.1` Docker URL above.
|
||||
- **Railway production:** `postgres.railway.internal` only works **inside** Railway network — not from local WSL. For local access to hosted DB use Railway **public** proxy URL from dashboard, or prefer Docker for dev.
|
||||
- **Firebase:** `FIREBASE_API_KEY`, `FIREBASE_AUTH_DOMAIN`, `FIREBASE_PROJECT_ID`, `FIREBASE_STORAGE_BUCKET`, `FIREBASE_MESSAGING_SENDER_ID`, `FIREBASE_APP_ID` — empty values break client `firebase.initializeApp()` in browser.
|
||||
- Omit `DATABASE_URL` entirely to force JSON-only mode (UI work without Postgres).
|
||||
- **`DATABASE_URL` is mandatory** for recipe pages; omitting it shows the DB unavailable page.
|
||||
|
||||
### Environment separation (important)
|
||||
- One database per environment (local Docker / staging / production).
|
||||
- Never point a dev branch `.env` at production Postgres.
|
||||
- Export/import between envs: `pg_dump` / `psql` when needed; document URLs in platform secrets (Railway variables), not in repo.
|
||||
- Export/import between envs: `pg_dump` / `psql` when needed; document URLs in hosting secrets, not in repo.
|
||||
|
||||
---
|
||||
|
||||
@@ -107,21 +103,18 @@ php scripts/db-check.php # after .env + pgsql OK
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
|--------|--------|-----|
|
||||
| HTTP 500, `Call to undefined function get_firebase_config()` | Function missing from `config.php` | Ensure `get_firebase_config()` exists in `config.php` |
|
||||
| HTTP 503, database unavailable | No `DATABASE_URL` or Postgres down | Fix `.env`, start Docker, `php scripts/db-check.php` |
|
||||
| Log: `could not find driver` | `php-pgsql` not installed | `sudo apt install php8.5-pgsql` |
|
||||
| Log: connection failed, host `postgres.railway.internal` | Internal Railway hostname from local machine | Use Docker local URL or Railway public URL |
|
||||
| Site loads, no recipes from DB | `DATABASE_URL` unset or DB empty and seed file missing | Set URL, ensure `data/recipes.json` exists, hit site or run `db-check.php` |
|
||||
| Recipes work without Docker | Expected fallback | `load_recipes_local()` uses JSON when `get_db_connection()` is null |
|
||||
| DB OK but 0 recipes | Empty tables | `php scripts/db-seed.php` |
|
||||
|
||||
---
|
||||
|
||||
## 8. Completed Milestones
|
||||
- **Phase 3 (Nutrition):** `calories`, `protein`, `carbs`, `fat` on recipes; admin + UI.
|
||||
- **Phase 4 (Cooking Mode):** `step_videos`, `step_timers`; fullscreen overlay.
|
||||
- **Phase 6 (Postgres):** `recipes` JSONB table; seed from JSON; admin dual-write.
|
||||
- **Phase 6 (Postgres):** Normalized SQL tables; `db-seed.php`; no runtime JSON recipes.
|
||||
- **Local dev Postgres:** `docker-compose.dev.yml`, README section, `scripts/db-check.php`, `.env.example` with `DATABASE_URL`.
|
||||
- **Bugfix (May 2026):** Restored `get_firebase_config()` after postgres migration regression.
|
||||
- **Local profile data:** Favorites/goals via `assets/fc-local.js` (`localStorage`). Newsletter may use `mailto:` or Firestore depending on page.
|
||||
- **Local profile data:** Favorites/goals via `assets/fc-local.js` (`localStorage`). Newsletter via `mailto:`.
|
||||
|
||||
## 9. Next Steps
|
||||
See `.agents/TODO.md` (e.g. PWA & offline support). README `Local Postgres (Docker)` and `Postgres in diesem Projekt` sections mirror setup for humans.
|
||||
|
||||
Reference in New Issue
Block a user