No description
  • TypeScript 100%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
eddy df05fb75dd fix: sync refactor — fix 6 bugs + cache refresh na sync
- setDeletedAt update nu ook updatedAt (bug 2)
- getAllMeasurements filtert deletedAt IS NULL, nieuwe getAllMeasurementsForSync voor sync
- mergeMeasurements detecteert server deleted:true → deletedAt (bug 1)
- syncAll: pull-push split met remoteUpdatedMap, geen double-push (bug 3)
- hard delete alleen na API-succes (bug 4)
- DashboardScreen: refreshCache() na syncAll zodat UI niet op Laden blijft hangen
- deleteMeasurement() dead code verwijderd (bug 5)
- tests: 3 nieuwe testcases voor deleted → deletedAt mapping, 15/15 pass
2026-07-25 15:33:22 +02:00
.claude Initial commit 2026-06-27 22:39:13 +02:00
assets assets: nieuw app icoon van weegschaal-app.jpeg 2026-07-20 19:34:40 +02:00
docs fix: sync refactor — fix 6 bugs + cache refresh na sync 2026-07-25 15:33:22 +02:00
src fix: sync refactor — fix 6 bugs + cache refresh na sync 2026-07-25 15:33:22 +02:00
tests fix: sync refactor — fix 6 bugs + cache refresh na sync 2026-07-25 15:33:22 +02:00
.gitignore feat: add MeasurementDetailScreen, 365-day charts, and edit support 2026-07-14 09:14:59 +02:00
AGENTS.md Initial commit 2026-06-27 22:39:13 +02:00
app.json fix: update adaptive icon foreground naar nieuw icoon 2026-07-20 20:01:19 +02:00
App.tsx feat: add MeasurementDetailScreen, 365-day charts, and edit support 2026-07-14 09:14:59 +02:00
CLAUDE.md Initial commit 2026-06-27 22:39:13 +02:00
eas.json feat: add EAS config and android package name for APK build 2026-06-28 00:05:04 +02:00
index.ts Initial commit 2026-06-27 22:39:13 +02:00
LICENSE Initial commit 2026-06-27 22:39:13 +02:00
package-lock.json feat: share knop op dashboard kaart — deelt kaart als PNG via expo-sharing 2026-07-20 18:58:24 +02:00
package.json fix: sync refactor — fix 6 bugs + cache refresh na sync 2026-07-25 15:33:22 +02:00
README.md docs: uitgebreide README met alle projectaspecten 2026-07-20 20:19:48 +02:00
tsconfig.json feat: wire up App.tsx with navigation 2026-06-27 22:42:33 +02:00
UNLICENSE docs: public domain (Unlicense) 2026-06-27 22:46:32 +02:00
upgrade.md db: fix insertMeasurement/upsertMeasurement — remove syncStatus param 2026-07-20 16:58:55 +02:00
weegschaal-app.jpeg assets: nieuw app icoon van weegschaal-app.jpeg 2026-07-20 19:34:40 +02:00

Weegschaal App

Gemaakt met vibecoding — DeepSeek V4 Pro

React Native (Expo) app voor het invoeren en synchroniseren van lichaamsmetingen (weegschaal). Data wordt lokaal opgeslagen in SQLite en gesynchroniseerd via een eigen REST API met timestamp-based delta-sync.

Inhoud

Functionaliteit

  • Metingen invoeren van een slimme weegschaal: gewicht, BMI, vetpercentage, vetmassa, spierpercentage, spiermassa, buikvet en stofwisseling
  • Dashboard met laatste en voorlaatste meting, gewichtsverschil, en grafiek
  • Delen van meetresultaten als PNG-afbeelding via WhatsApp, e-mail, etc.
  • Historie van alle metingen, gesorteerd op datum
  • Offline-first: metingen worden lokaal opgeslagen en later automatisch gesynchroniseerd
  • Instellingen voor API-configuratie en handmatige sync

Schermen

Scherm Beschrijving
Dashboard Laatste meting, voorlaatste meting met gewichtsverschil, grafiek, deel-knop
Nieuwe meting / Wijzigen Formulier met datumkiezer, waarden vooraf ingevuld vanaf laatste meting
Meting detail Alle meetwaarden met knoppen voor wijzigen en verwijderen
Historie FlatList van alle metingen, pull-to-refresh, tik voor detail
Instellingen API URL + token, opslaan/wissen, handmatige sync

Synchronisatie

De app synchroniseert via een zelfgebouwde REST API. Geen WebDAV, geen bestandssync — pure delta-sync.

Hoe het werkt

  1. Delta ophalen: GET /api/v1/measurements?since=lastSyncAt — alleen gewijzigde records van de server
  2. Mergen: last-writer-wins op updatedAt
  3. Pushen: alle lokale records met updatedAt > lastSyncAt → POST naar API
  4. Verwijderen: soft delete via deletedAt timestamp → DELETE naar API bij volgende sync
  5. High-water mark: lastSyncAt bijgewerkt na elke succesvolle sync

Waarom timestamp-based?

Geen syncStatus enum, geen speciale gevallen. Hetzelfde patroon dat CouchDB en PouchDB gebruiken:

  • updatedAt op elke wijziging (client-tijd)
  • deletedAt voor soft deletes
  • lastSyncAt (opgeslagen in SecureStore) voor delta-tracking
  • Merge: last-writer-wins, zonder uitzonderingen

Offline resilience

Bij netwerkfout tijdens opslaan blijft de meting lokaal staan. De volgende sync (updatedAt > lastSyncAt) pikt hem automatisch op. Geen handmatige tussenkomst nodig.

Server-side API

Stack: nginx, PHP 8.5 (Slim Framework 4), MariaDB, Let's Encrypt SSL, SELinux

Endpoints:

Methode Pad Auth Beschrijving
GET /api/v1/measurements?since=ISO Bearer Delta-sync
POST /api/v1/measurements Bearer Upsert (INSERT ON DUPLICATE KEY)
DELETE /api/v1/measurements/:id Bearer Soft delete (deleted=1, update updated_at)

Database: MariaDB met drie tabellen — users, auth_tokens, measurements. De measurements tabel gebruikt ON DUPLICATE KEY UPDATE voor conflictvrije upserts.

Bestandsstructuur:

/usr/share/nginx/html/weegschaal-api/
├── composer.json
├── config.php
├── public/
│   └── index.php
└── src/
    ├── Auth.php            ← Bearer token validatie middleware
    ├── Database.php        ← PDO singleton
    ├── Measurements.php    ← CRUD + sync queries
    └── helpers.php         ← JSON response, datetime conversie, logging

Beveiliging

Authenticatie

Bearer token-validatie via auth_tokens tabel. Tokens worden handmatig aangemaakt via SQL.

Logging

Elke mislukte authenticatie en 404 wordt gelogd naar /var/log/weegschaal-api/auth.log:

[2026-07-20 18:06:07] 401 94.157.121.179 GET /api/v1/measurements - invalid Bearer token
[2026-07-20 18:06:07] 404 94.157.121.179 GET /.env - unknown route

Fail2ban

Jail weegschaal-api: 5 foutieve pogingen binnen 5 minuten = 1 uur IP-ban. Filter regex:

^\[.*\] 401 <HOST> .* - .*$

Logrotering wekelijks, 12 weken retentie.

SELinux

Logmap heeft context httpd_log_t gezet via semanage fcontext.

Ontwikkeling

npm install
npx expo start

Scannen met Expo Go op Android of iOS.

Build & deploy

# APK bouwen (lokaal via EAS)
npx eas build --local --profile apk --platform android

# Draadloos sideloaden via ADB
adb-wireless-connect
adb install -r build-*.apk

Vereisten: Android SDK 36, OpenJDK 21, ADB 37+, Gradle 8.14.

Database migratie

Bestaande SQLite-databases worden automatisch gemigreerd. initDatabase() voegt de deletedAt kolom toe via ALTER TABLE als deze nog niet bestaat:

ALTER TABLE measurements ADD COLUMN deletedAt TEXT

Testen

npm test

Tests richten zich op de merge-logica (mergeMeasurements) en database-operaties.

Licentie

Public domain (Unlicense)