Add carryover management for overtime, update weekday naming to German, and enhance reset functionality.

This commit is contained in:
T.Landgraf committed 2026-08-14 13:26:02 +02:00
1 parent 21ed1e7744
commit ceb18d1d8d
2 files changed
+47 -19

No files matched your search

+47 -18
View File
@@ -1,8 +1,8 @@
import { SegmentedControl, Center, Stack, Button, Text, NumberInput } from '@mantine/core';
import { SegmentedControl, Center, Stack, Button, Text, NumberInput, Space } from '@mantine/core';
import { TimePicker } from '@mantine/dates';
import * as React from 'react';
type Workday = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday';
type Workday = 'Montag' | 'Dienstag' | 'Mittwoch' | 'Donnerstag' | 'Freitag';
interface DayRecord {
start: string;
@@ -15,9 +15,12 @@ interface DayRecord {
type Records = Partial<Record<Workday, DayRecord>>;
const STORAGE_KEY = 'workTrackerRecords';
const CARRYOVER_KEY = 'workTrackerCarryover';
const DEFAULT_RECORD: DayRecord = { start: '', end: '', breakMins: 0, workedHrs: 0, overtimeMinutes: 0 };
const WEEKDAYS: Workday[] = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag'];
const loadRecords = (): Records => {
try {
const raw = localStorage.getItem(STORAGE_KEY);
@@ -27,6 +30,15 @@ const loadRecords = (): Records => {
}
};
const loadCarryover = (): number => {
try {
const val = Number(localStorage.getItem(CARRYOVER_KEY));
return Number.isFinite(val) ? val : 0;
} catch {
return 0;
}
};
const toMinutes = (time: string): number | null => {
const match = /^(\d{2}):(\d{2})$/.exec(time);
if (!match) return null;
@@ -42,6 +54,7 @@ const fromMinutes = (mins: number): string => {
function App() {
const [selectedDay, setSelectedDay] = React.useState<Workday>('Monday');
const [records, setRecords] = React.useState<Records>(loadRecords);
const [carryoverMinutes, setCarryoverMinutes] = React.useState<number>(loadCarryover);
const record = records[selectedDay] ?? DEFAULT_RECORD;
@@ -49,6 +62,10 @@ function App() {
localStorage.setItem(STORAGE_KEY, JSON.stringify(records));
}, [records]);
React.useEffect(() => {
localStorage.setItem(CARRYOVER_KEY, String(carryoverMinutes));
}, [carryoverMinutes]);
const updateRecord = (patch: Partial<DayRecord>) => {
setRecords((prev) => ({
...prev,
@@ -64,14 +81,14 @@ function App() {
}
const getWeeklyBalance = () => {
const days: Workday[] = ['Monday', 'Tuesday', 'Wednesday', 'Thursday'];
return days.reduce((sum, day) => sum + (records[day]?.overtimeMinutes ?? 0), 0);
const days: Workday[] = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag'];
return days.reduce((sum, day) => sum + (records[day]?.overtimeMinutes ?? 0), 0) + carryoverMinutes;
}
const getWorkEndTime = () => {
const start = toMinutes(record.start);
if (start === null) return '—';
const balance = selectedDay === 'Friday' ? getWeeklyBalance() : 0;
if (start === null) return '-';
const balance = selectedDay === 'Freitag' ? getWeeklyBalance() : 0;
return fromMinutes(start + 8 * 60 - balance + record.breakMins);
}
@@ -80,16 +97,21 @@ function App() {
updateRecord({ workedHrs: hours, overtimeMinutes: Math.round((hours - 8) * 60) });
}
const handleReset = () => {
localStorage.removeItem(STORAGE_KEY);
const handleResetWorkdays = () => {
const totalOvertime = WEEKDAYS.reduce((sum, day) => sum + (records[day]?.overtimeMinutes ?? 0), 0) + carryoverMinutes;
setCarryoverMinutes(totalOvertime);
setRecords({});
}
const handleResetOvertime = () => {
setCarryoverMinutes(0);
}
return (
<Center>
<Center className={"my-auto"}>
<Stack>
<SegmentedControl
data={['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']}
data={['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag']}
onChange={(value) => setSelectedDay(value as Workday)}
className={"mt-2"}
/>
@@ -117,26 +139,33 @@ function App() {
/>
<Button onClick={handleSave}>
Speichern
Berechnen + Speichern
</Button>
<Text>Gearbeitete Stunden heute: {record.workedHrs.toFixed(2)}</Text>
{selectedDay === 'Friday' && (
<Text c={"green"}>Übertragen aus Montag bis Donnerstag: {getWeeklyBalance()} Minuten</Text>
{carryoverMinutes !== 0 && (
<Text c={"blue"}>Übernommene Überstunden aus Vorwoche: {carryoverMinutes} Minuten</Text>
)}
{selectedDay === 'Freitag' && (
<Text c={"green"}>Übertragen aus Montag bis Donnerstag (inkl. Vorwoche): {getWeeklyBalance()} Minuten</Text>
)}
<Text>Wann du gehen kannst für 8 Stunden: {getWorkEndTime()}</Text>
{record.overtimeMinutes === 0 && (
{record.start && record.end && record.overtimeMinutes === 0 && (
<Text>Du hast genau 8 Stunden gearbeitet.</Text>
)}
{record.overtimeMinutes > 0 && (
{record.start && record.end && record.overtimeMinutes > 0 && (
<Text c="yellow">Überstunden: {record.overtimeMinutes} Minuten</Text>
)}
{record.overtimeMinutes < 0 && (
{record.start && record.end && record.overtimeMinutes < 0 && (
<Text c={"red"}>Fehlende Minuten für 8 Stunden: {-record.overtimeMinutes} Minuten</Text>
)}
<Button color="red" variant="outline" onClick={handleReset}>
Reset saved records
<Space h={"xl"} />
<Button color="red" variant="outline" onClick={handleResetWorkdays}>
Arbeitstage zurücksetzen
</Button>
<Button color="red" variant="outline" onClick={handleResetOvertime}>
Überstunden zurücksetzen
</Button>
</Stack>
</Center>
-1
View File
@@ -1,5 +1,4 @@
import '@mantine/core/styles.css';
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'