From 0bae3b29dca9b22f67a3276804a6d2928c638928 Mon Sep 17 00:00:00 2001 From: elpatron Date: Sun, 31 May 2026 13:54:57 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Grauwasserstand=20beim=20neuen=20Reiset?= =?UTF-8?q?ag=20vom=20Vortag=20=C3=BCbernehmen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Übernimmt den Grauwasser-Füllstand analog zu Frischwasser und Kraftstoff beim Anlegen eines Reisetags und zeigt ihn im Übernahme-Dialog an. Co-authored-by: Cursor --- client/src/components/LogEntriesList.tsx | 9 +++-- client/src/i18n/locales/de.json | 2 +- client/src/i18n/locales/en.json | 2 +- client/src/utils/logEntryTankLevels.test.ts | 38 +++++++++++++++++++++ client/src/utils/logEntryTankLevels.ts | 15 ++++++-- 5 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 client/src/utils/logEntryTankLevels.test.ts diff --git a/client/src/components/LogEntriesList.tsx b/client/src/components/LogEntriesList.tsx index a58df73..df98047 100644 --- a/client/src/components/LogEntriesList.tsx +++ b/client/src/components/LogEntriesList.tsx @@ -241,14 +241,15 @@ export default function LogEntriesList({ decryptedEntries.sort(compareTravelDaysChronological) const previousEntry = decryptedEntries.at(-1) ?? null - let { freshwater, fuel, departure } = carryOverFromPreviousDay(previousEntry) + let { freshwater, fuel, greywaterLevel, departure } = carryOverFromPreviousDay(previousEntry) - if (previousEntry && hasCarryOverFromPreviousDay({ freshwater, fuel, departure })) { + if (previousEntry && hasCarryOverFromPreviousDay({ freshwater, fuel, greywaterLevel, departure })) { const confirmed = await showConfirm( t('logs.carry_over_tanks_confirm', { departure: departure || '—', fw: formatTankLiters(freshwater.morning), - fuel: formatTankLiters(fuel.morning) + fuel: formatTankLiters(fuel.morning), + greywater: formatTankLiters(greywaterLevel) }), t('logs.carry_over_tanks_title'), t('logs.carry_over_tanks_yes'), @@ -257,6 +258,7 @@ export default function LogEntriesList({ if (!confirmed) { freshwater = emptyTankLevels() fuel = emptyTankLevels() + greywaterLevel = 0 departure = '' } } @@ -274,6 +276,7 @@ export default function LogEntriesList({ destination: '', freshwater, fuel, + ...(greywaterLevel > 0 ? { greywater: { level: greywaterLevel } } : {}), signSkipper: '', signCrew: '', events: [] diff --git a/client/src/i18n/locales/de.json b/client/src/i18n/locales/de.json index 5460a3a..b5506ae 100644 --- a/client/src/i18n/locales/de.json +++ b/client/src/i18n/locales/de.json @@ -193,7 +193,7 @@ "delete_entry": "Tag löschen", "delete_confirm": "Bist du sicher, dass du diesen Reisetag unwiderruflich löschen möchtest?", "carry_over_tanks_title": "Daten vom Vortag übernehmen?", - "carry_over_tanks_confirm": "Start-Hafen, Frischwasser- und Kraftstoff-Morgenstände vom letzten Reisetag übernehmen?\n\nStart-Hafen: {{departure}}\nFrischwasser: {{fw}} L\nKraftstoff: {{fuel}} L", + "carry_over_tanks_confirm": "Start-Hafen, Frischwasser-, Kraftstoff- und Grauwasser-Startstände vom letzten Reisetag übernehmen?\n\nStart-Hafen: {{departure}}\nFrischwasser: {{fw}} L\nKraftstoff: {{fuel}} L\nGrauwasser: {{greywater}} L", "carry_over_tanks_yes": "Übernehmen", "carry_over_tanks_no": "Mit 0 starten", "event_title": "Chronologisches Ereignisprotokoll", diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json index 54621fb..8c616e0 100644 --- a/client/src/i18n/locales/en.json +++ b/client/src/i18n/locales/en.json @@ -193,7 +193,7 @@ "delete_entry": "Delete Day", "delete_confirm": "Are you sure you want to permanently delete this travel day?", "carry_over_tanks_title": "Carry over from previous day?", - "carry_over_tanks_confirm": "Use the previous travel day's destination as departure port and closing tank levels as morning levels?\n\nDeparture port: {{departure}}\nFreshwater: {{fw}} L\nFuel: {{fuel}} L", + "carry_over_tanks_confirm": "Use the previous travel day's destination as departure port and closing tank levels as morning levels?\n\nDeparture port: {{departure}}\nFreshwater: {{fw}} L\nFuel: {{fuel}} L\nGreywater: {{greywater}} L", "carry_over_tanks_yes": "Carry over", "carry_over_tanks_no": "Start at 0", "event_title": "Chronological Event Logbook", diff --git a/client/src/utils/logEntryTankLevels.test.ts b/client/src/utils/logEntryTankLevels.test.ts new file mode 100644 index 0000000..d862146 --- /dev/null +++ b/client/src/utils/logEntryTankLevels.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from 'vitest' +import { + carryOverFromPreviousDay, + getClosingGreywaterLevel, + hasCarryOverFromPreviousDay +} from './logEntryTankLevels.js' + +describe('logEntryTankLevels greywater carry-over', () => { + it('returns previous greywater level as starting value', () => { + const carryOver = carryOverFromPreviousDay({ + destination: 'Oslo', + freshwater: { morning: 100, refilled: 0, evening: 80, consumption: 20 }, + fuel: { morning: 200, refilled: 0, evening: 150, consumption: 50 }, + greywater: { level: 42 } + }) + + expect(carryOver.greywaterLevel).toBe(42) + expect(carryOver.freshwater.morning).toBe(80) + expect(carryOver.fuel.morning).toBe(150) + expect(carryOver.departure).toBe('Oslo') + }) + + it('defaults greywater to 0 when previous day has none', () => { + expect(carryOverFromPreviousDay(null).greywaterLevel).toBe(0) + expect(getClosingGreywaterLevel(undefined)).toBe(0) + }) + + it('treats greywater level as carry-over candidate', () => { + expect( + hasCarryOverFromPreviousDay({ + freshwater: { morning: 0, refilled: 0, evening: 0, consumption: 0 }, + fuel: { morning: 0, refilled: 0, evening: 0, consumption: 0 }, + greywaterLevel: 15, + departure: '' + }) + ).toBe(true) + }) +}) diff --git a/client/src/utils/logEntryTankLevels.ts b/client/src/utils/logEntryTankLevels.ts index 77575a1..ac85a0e 100644 --- a/client/src/utils/logEntryTankLevels.ts +++ b/client/src/utils/logEntryTankLevels.ts @@ -48,6 +48,7 @@ export interface LogEntryTankSource { export interface CarryOverFromPreviousDay { freshwater: TankLevels fuel: TankLevels + greywaterLevel: number departure: string } @@ -60,6 +61,10 @@ export function formatTankLiters(liters: number): string { return Number.isInteger(liters) ? String(liters) : liters.toFixed(1) } +export function getClosingGreywaterLevel(greywater?: { level?: number } | null): number { + return Number(greywater?.level) || 0 +} + export function carryOverTankLevelsFromPreviousDay(previousEntry?: LogEntryTankSource | null): { freshwater: TankLevels; fuel: TankLevels } { if (!previousEntry) { return { freshwater: emptyTankLevels(), fuel: emptyTankLevels() } @@ -74,10 +79,16 @@ export function carryOverTankLevelsFromPreviousDay(previousEntry?: LogEntryTankS export function carryOverFromPreviousDay(previousEntry?: LogEntryTankSource | null): CarryOverFromPreviousDay { const { freshwater, fuel } = carryOverTankLevelsFromPreviousDay(previousEntry) const departure = previousEntry?.destination?.trim() || '' + const greywaterLevel = getClosingGreywaterLevel(previousEntry?.greywater) - return { freshwater, fuel, departure } + return { freshwater, fuel, greywaterLevel, departure } } export function hasCarryOverFromPreviousDay(carryOver: CarryOverFromPreviousDay): boolean { - return carryOver.freshwater.morning > 0 || carryOver.fuel.morning > 0 || carryOver.departure.length > 0 + return ( + carryOver.freshwater.morning > 0 || + carryOver.fuel.morning > 0 || + carryOver.greywaterLevel > 0 || + carryOver.departure.length > 0 + ) }