duimstok.prorail.nl/_docs/session-summary-2026-04-16.md

237 lines
11 KiB
Markdown

# Session Summary: Duimstok PWA MVP Build
**Date:** 2026-04-16
**Project:** ProRail Duimstok-inspecties Bovenbouw
**Repo:** https://git.en-masse.nl/randy/duimstok.prorail.nl.git
---
## Phase 1: Monolithic HTML Refactor
**Goal:** Split a single-file app (`duimstok-wissel-gw-sw.html`, 1566 lines) into a layered DDD structure.
**What was done:**
- Created `src/Domain/`, `src/Application/`, `src/Infrastructure/` layers
- Converted ES modules to classic IIFE scripts attaching to `window.App.*` namespace
- Embedded CSV seed data as a string constant in `seedOrders.js` (no `fetch()` needed)
- Removed all inline styles (`style=""`) and inline event handlers (`onclick`, `oninput`, etc.)
- Replaced inline styles with CSS classes (`.flex-spacer`, `.cap-arrow.lg`, `.section-sub.sm`, `.fotonummers-cell`)
- Wired all event listeners via `addEventListener` in `main.js` and service modules
**Result:** 30 files, ~2163 lines. Runs by double-clicking `public/index.html` -- no server needed.
**File structure:**
```
01_Applicatie/
├── public/
│ ├── index.html
│ ├── css/ base.css, overview.css, form.css, modals.css, responsive.css
│ └── js/ namespace.js, main.js
└── src/
├── Domain/ sectionMap.js, scoring.js, orderParser.js
├── Application/ state.js, persistence.js, screens.js, photoService.js,
│ inspectionForm.js, orderOverview.js, xmlImport.js, exportService.js
└── Infrastructure/ utils.js, geolocation.js, db.js, seedOrders.js, csvLoader.js
```
---
## Phase 2: PWA Research & Planning
**Prompt used:** "what are the next steps create a PWA version of this MVP, ideally with offline photo upload functionality which sync when back online. Whats the current supported state of PWA regarding these offline functionalities atm"
**Key findings:**
- Service Worker, Cache API, IndexedDB, Manifest, installability all work cross-browser (Chromium, Firefox, Safari/iOS 16.4+)
- Background Sync (`sync` event) only works on Chromium -- not Firefox, not Safari/iOS
- Periodic Background Sync: Chromium only (engagement-gated)
- Background Fetch: Chromium only
- Push notifications: universal for installed PWAs (iOS 16.4+)
- Persistent storage: universal, but Safari historically aggressive on eviction
**Key constraint:** iOS has no true background sync. Design around draining the queue when the user reopens the app and when the `online` event fires.
**6-step incremental plan identified:**
1. Installable shell (manifest + service worker cache)
2. Switch photo storage from data URLs to Blobs
3. Sync queue in IndexedDB
4. Trigger drain on every available signal (online event, app open, SW sync, manual button)
5. Persistent storage + install hint
6. Backend stub (Symfony controller for POST /api/inspections)
---
## Phase 3: PWA Scaffold Implementation
**Prompt used:** "Goal is still conversion later on to Symfony, but for now we do want the PWA functionality (add an additional installation and instruction screen for the PWA installation)"
**Constraint flagged:** PWA features require HTTPS or localhost -- they cannot work from `file://`.
**Resolution:** Dual-mode codebase:
- `file://` mode: app works exactly as before; PWA init gated by `location.protocol !== 'file:'` and quietly skipped
- `http://localhost` or deployed mode: service worker registers, app becomes installable, install screen shows platform-specific instructions
**Files created:**
- `public/manifest.webmanifest` -- app manifest with icons, standalone display, ProRail blue theme
- `public/sw.js` -- service worker with app shell precaching (cache-first for statics, network-first for API)
- `public/icons/icon.svg` -- SVG app icon (ProRail blue with white ruler lines)
- `public/css/install.css` -- styles for the install instruction screen
- `src/Application/pwa.js` -- service worker registration, `beforeinstallprompt` capture, standalone detection
- `src/Application/installScreen.js` -- platform-specific install instructions (Chrome/Edge, iOS Safari, Firefox, generic)
**HTML changes:**
- Added PWA meta tags (`theme-color`, `apple-mobile-web-app-capable`, manifest link, apple-touch-icon)
- Added "Installeren" button to overview toolbar
- Added `screen-install` section with back button and dynamic body
- Added `<link>` for `install.css`
- Added `<script>` tags for `pwa.js` and `installScreen.js`
---
## Phase 4: Git Repository Setup
**Prompt used:** "ini git repo and commit and push, add files and folders, repo https://git.en-masse.nl/randy/duimstok.prorail.nl.git" + "to the develop branch"
**Decisions made:**
- Repo root: `01_Applicatie/` (app code only; ProRail reference PDFs/photos stay outside)
- Deleted old monolithic files: `duimstok-wissel-gw-sw.html` and backup copy
- Created `.gitignore` (DS_Store, Thumbs.db, editors, node_modules, env files)
- Created `README.md` with project structure documentation
- Created `_docs/.gitkeep`
**Git Flow applied:**
1. Initialized repo with `develop` branch -- baseline commit (README, .gitignore, _docs/)
2. Created `feature/initial-pwa-scaffold` branch off develop
3. Committed all app code (30 files, 2163 insertions)
4. Pushed `develop` (baseline only, no staging deploy triggered)
5. Pushed `feature/initial-pwa-scaffold` (feature branch, no deploy implications)
6. Suggested PR creation on Forgejo before merging to develop
---
## Phase 5: Photo Blob Storage Refactor
**Branch:** `feature/photo-blob-storage` (off `feature/initial-pwa-scaffold`)
**What changed:**
- Photos now stored as native `Blob` objects instead of base64 data URLs (~33% smaller)
- `photoSrc()` helper uses `URL.createObjectURL(blob)` for rendering thumbnails
- `URL.revokeObjectURL()` called on lightbox close and when replacing images (memory cleanup)
- Removed `readFileAsDataUrl()` from `utils.js` (no longer needed)
- Removed `dataUrlToBlob()` from `utils.js` (no longer needed)
- `db.js`: removed `JSON.parse(JSON.stringify(formData))` deep-clone -- IndexedDB handles Blobs natively
- `exportService.js`: downloads `p.blob` directly instead of converting from data URL
**Files changed:** `photoService.js`, `exportService.js`, `db.js`, `utils.js`
---
## Phase 6: CSV Upload Persistence
**Branch:** `feature/csv-upload-persistence`
**What changed:**
- New IndexedDB object store `ordersCsv` (DB version bumped 3 -> 4)
- `db.js`: added `saveOrdersCsv(csvText)` and `loadOrdersCsv()` functions
- `csvLoader.js`: `loadOrdersFromUpload()` now returns `{ text, orders }` so raw CSV text gets persisted
- `main.js` init: loads stored CSV from IndexedDB, falls back to embedded seed data if none stored
- `main.js` upload handler: saves CSV text to IndexedDB after parsing
**Files changed:** `db.js`, `csvLoader.js`, `main.js`
---
## Phase 7: Persistent Storage Request
**Branch:** `feature/persistent-storage-request`
**What changed:**
- New file `src/Infrastructure/persistentStorage.js` with `isPersisted()` and `requestPersistence()`
- Calls `navigator.storage.persist()` after the first successful save (reduces iOS eviction risk)
- One-time flag `persistenceRequested` prevents repeated calls
- Updated SW cache version to `duimstok-v2`
- Added `persistentStorage.js` to both `index.html` script tags and SW precache list
**Files changed/created:** `persistentStorage.js` (new), `persistence.js`, `sw.js`, `index.html`
---
## Phase 8: Multi-Inspection Type Scoping (Not Yet Implemented)
**Prompt used:** "continue with question 1: spoor en overweg in map C:\...\04_Gegenereerd door SAP_incl WW_xslx_xlm\XML"
**Research done:**
- Read `_docs/switch-inspection-diagram.md` -- confirms existing wissel_GW photo layout
- Read SAP XML templates for Spoor and Overwegbevloering from reference folders
- Identified 3 inspection types: Wissel, Overwegbevloering, Spoor
**Proposed scope for `feature/inspection-type-routing`:**
1. Routing layer that derives type from `order.objectsoort`
2. Three form panels in `index.html`, shown based on type
3. Wissel: no visual change (existing 10-slot layout)
4. Overwegbevloering: stub form with photos section, no wissel diagram
5. Spoor: stub form emphasizing start/end-KM fields from CSV
6. Export works for all three types
**Status:** Scoped, awaiting answers to 3 questions before implementation.
---
## Global Rules Established
These rules were added to `~/.claude/CLAUDE.md` during the session:
| Rule | Context |
|------|---------|
| **No backwards compatibility in MVPs** | User corrected fallback code for old photo data format |
| **No `Co-Authored-By: Claude` in commits** | User interrupted a commit that included the attribution line |
| **Git Flow workflow** | User requested: develop = staging, master = production, feature branches for all work |
| **`_docs/` for project documentation** | User requested: all docs in project root `_docs/` folder |
| **`file://` runnable MVPs** | User requested: must work by opening `public/index.html` directly |
| **Vanilla HTML/JS/CSS, no frameworks** | Pre-existing rule (maps to eventual Symfony/Twig conversion) |
| **DDD folder structure** | Pre-existing rule (Domain/Application/Infrastructure layers) |
| **Forgejo at git.en-masse.nl** | User specified as default remote host |
---
## Shortcuts & Commands Used
| Command/Action | Purpose | Times Used |
|----------------|---------|------------|
| `/usage` | Check token consumption | 2x |
| `continue` | Resume after idle or interruption | Multiple |
| `merge` | Trigger merge-to-develop flow | Multiple |
| `yes` / `1` / `3` | Quick selection from numbered options | Multiple |
| Interrupted commits | Added global rules mid-flow (no co-author, no backwards compat) | 3x |
---
## Git History (Linear on develop)
```
b005193 Request persistent storage after first save
92ad6a9 Persist uploaded order CSVs across app restarts
e86aa5b Store photos as native Blobs instead of base64 data URLs
776bd63 Add PWA-ready MVP: split HTML/CSS/JS + DDD layering + service worker
367bbca Initial repo scaffold on develop
```
**Branch lifecycle:**
- All feature branches created off `develop` (or stacked off previous feature branch when develop was behind)
- All merged via fast-forward (`--ff-only`)
- All deleted (local + remote) after merge
- Only `develop` remains as active branch
- `master` not yet created (awaiting production readiness)
---
## Open Items
- [ ] Manual verify: capture photo, render thumbnail, reload, check thumbnail persists, export produces valid JPG
- [ ] Manual verify: upload CSV, hard-reload, confirm modified orders still appear
- [ ] Implement `feature/inspection-type-routing` (Wissel/Overwegbevloering/Spoor forms)
- [ ] Create `master` branch when ready for production deployment
- [ ] Set up CI on Forgejo
- [ ] Backend stub (Symfony POST /api/inspections) to enable sync queue testing
- [ ] Authentication for inspectors (currently free-text name -- needs SSO/token discussion with ProRail)