Add carryover management for overtime, update weekday naming to German, and enhance reset functionality.
This commit is contained in:
1 parent
21ed1e7744
commit
ceb18d1d8d
2 files changed
+47
-19
No files matched your search
+47
-18
@@ -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,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'
|
||||
|
||||
Reference in new issue
Block a user