diff --git a/Changelog.md b/Changelog.md index 4a74004..ba241f9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,20 @@ ## [Niet vrijgegeven] +### Opgelost +- Het laatste label op de x-as viel over zijn buurman heen (`mei '26` en `26` + over elkaar). De stap werd vanaf het begin van de reeks geteld en het laatste + punt werd daar los bovenop geforceerd, zodat het op willekeurige afstand van + zijn voorganger landde — bij een reeks die niet toevallig op een veelvoud + uitkwam, pal ernaast. De stap telt nu terug vanaf het laatste punt: dat valt + daarmee per definitie op een stap en houdt volle tussenruimte, zonder dat er + nog een uitzondering voor nodig is +- De breedte waarop de grafiek rekent ging van 46 naar 54px per label, zodat er + lucht tussen staat in plaats van kop-aan-kop. Over reekslengtes van 13 tot 120 + punten blijft de tussenruimte nu minimaal 57px + +## [1.0.9] - 2026-09-17 + ### Gewijzigd - De x-as van beide grafieken toont korte maandlabels (`sep '26`) in plaats van een volledige datum bij elk punt, en ze staan rechtop in plaats van 45 graden diff --git a/README.md b/README.md index c1bae42..3c62ffe 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Eigen vermogen · Schulden · Voortgang · Gebruikersbeheer ![Node.js](https://img.shields.io/badge/Node.js_22-339933?style=flat&logo=node.js&logoColor=white) ![PostgreSQL](https://img.shields.io/badge/PostgreSQL_18-4169E1?style=flat&logo=postgresql&logoColor=white) ![Docker](https://img.shields.io/badge/Docker_Compose-2496ED?style=flat&logo=docker&logoColor=white) -![Version](https://img.shields.io/badge/versie-1.0.8-8b5cf6?style=flat) +![Version](https://img.shields.io/badge/versie-1.0.9-8b5cf6?style=flat) ![Built with Claude](https://img.shields.io/badge/Gebouwd_met-Claude.ai-8b5cf6?style=flat&logo=anthropic&logoColor=white) VibeFinance dashboard @@ -181,6 +181,16 @@ inleglijn is per definitie gelijk aan de KPI "Totaal geïnvesteerde fiat" — be rekenen het oudste voortgangsmoment als startinleg en tellen daar de stortingen per rij bij op. +De x-as noemt maanden (`sep '26`), niet losse datums: de grafiek rekent uit +hoeveel labels er naast elkaar passen en toont er zoveel, terugtellend vanaf het +laatste punt zodat dat er altijd bij staat. Bij een langere reeks dunt hij +vanzelf verder uit. De exacte dag lees je in de tooltip. De vermogenslijn is een +Catmull-Rom spline; de inleglijn krijgt bewust rechte segmenten, omdat een +spline tussen twee punten iets buiten hun bereik uitschiet en dat bij een reeks +die nooit terugloopt een daling zou tekenen die er niet is. Beide lijnen delen +de tekenhulp in +[`frontend/src/utils/grafiek.js`](frontend/src/utils/grafiek.js). + Onder **Instellingen** kies je een van de negen kleurthema's. Thema en licht/donker staan los van elkaar: het thema levert het accent, de schakelaar de ondergrond. De paletten staan in @@ -233,7 +243,8 @@ vibefinance/ │ ├── main.jsx │ ├── version.js # Draaiende versie (__APP_VERSION__ uit de build) │ ├── constants/ # index.js (kleuren, tabs, begindata), themas.js -│ ├── utils/ # format.js (bedragen/datums), storage.js +│ ├── utils/ # format.js (bedragen/datums), storage.js, +│ │ # grafiek.js (SVG-padberekening) │ ├── hooks/ # useTheme, useUpdateCheck, useKolomBreedtes │ ├── context/ # AppContext (global state + API sync + backup) │ ├── components/ diff --git a/frontend/package.json b/frontend/package.json index 5b171cc..1fe3c98 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "vibefinance-frontend", - "version": "1.0.8", + "version": "1.0.10-dev", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/pages/DashboardTab.jsx b/frontend/src/pages/DashboardTab.jsx index b5d952b..7e79f1b 100644 --- a/frontend/src/pages/DashboardTab.jsx +++ b/frontend/src/pages/DashboardTab.jsx @@ -179,9 +179,13 @@ function MiniLineChart({ vData, fiatData, darkMode, T }) { const mx = Math.max(...vals, ...fVals) * 1.05; const rng = mx - mn || 1; const iW = W - pl - pr, iH = H - pt - pb; - // Eén label "sep '26" is bij deze lettergrootte ongeveer 46px breed. Zoveel - // passen er dus naast elkaar; de rest wordt overgeslagen. - const labelStap = Math.max(1, Math.ceil(vData.length / Math.max(1, Math.floor(iW / 46)))); + // Eén label "sep '26" is bij deze lettergrootte ongeveer 54px breed inclusief + // wat lucht ernaast. Zoveel passen er naast elkaar; de rest wordt + // overgeslagen. De stap telt vanaf het láátste punt terug, niet vanaf het + // eerste: dat punt is de datum waar je naar kijkt en moet er altijd bij staan. + // Forceerden we hem er los bovenop, dan botste hij op willekeurige afstand + // tegen zijn voorganger — precies wat er eerst misging. + const labelStap = Math.max(1, Math.ceil(vData.length / Math.max(1, Math.floor(iW / 54)))); const xs = vData.map((_, i) => pl + (i / Math.max(vData.length - 1, 1)) * iW); const ys = vals.map((v) => pt + (1 - (v - mn) / rng) * iH); const fYs = fVals.map((v) => pt + (1 - (v - mn) / rng) * iH); @@ -316,7 +320,9 @@ function MiniLineChart({ vData, fiatData, darkMode, T }) { kijkt. De exacte dag lees je in de tooltip. */} {xs.map((x, i) => { const laatste = i === xs.length - 1; - if (i % labelStap !== 0 && !laatste) return null; + // Terugtellen vanaf het eind: het laatste punt valt zo vanzelf op een + // stap en houdt volle afstand tot zijn voorganger. + if ((xs.length - 1 - i) % labelStap !== 0) return null; return ( pts.map((p) => p[l.key] ?? 0)); const dataMin = Math.min(...allVals); const dataMax = Math.max(...allVals); @@ -116,7 +118,8 @@ function SvgLineChart({ pts, lines, T, H = 200 }) { onleesbare band. De exacte dag staat in de tooltip op elk punt. */} {pts.map((p, i) => { const laatste = i === pts.length - 1; - if (i % labelStap !== 0 && !laatste) return null; + // Terugtellen vanaf het eind, zodat het laatste punt op een stap valt. + if ((pts.length - 1 - i) % labelStap !== 0) return null; return (