feat: Zeit nachtragen fuer Git-Push-Worksheets
Git-Pushes erzeugen Worksheets mit automatischer Endzeit (Push-Zeitpunkt), aber ohne Startzeit. Neu: - WorksheetList: Pille 'Zeit offen' + Button 'Zeit nachtragen' bei GIT-Worksheets ohne Startzeit/Arbeitszeit - EditWorksheetTimeModal: Startdatum/-zeit erfassen, Arbeitszeit wird live berechnet (inkl. Uebernacht-Logik), speichert via updateWorksheet und setzt isComment=false, damit der Eintrag in der Arbeitszeit-Statistik zaehlt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
142
src/components/EditWorksheetTimeModal.jsx
Normal file
142
src/components/EditWorksheetTimeModal.jsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { FaClock } from 'react-icons/fa'
|
||||
|
||||
/** Minuten zwischen hhmm-Zeiten, Übernacht (+24h) wie useWorksheets.calculateTime. */
|
||||
function calculateMinutes(startTime, endTime) {
|
||||
if (!startTime || !endTime) return null
|
||||
const sh = parseInt(startTime.substring(0, 2), 10)
|
||||
const sm = parseInt(startTime.substring(2, 4), 10)
|
||||
const eh = parseInt(endTime.substring(0, 2), 10)
|
||||
const em = parseInt(endTime.substring(2, 4), 10)
|
||||
if ([sh, sm, eh, em].some(Number.isNaN)) return null
|
||||
let diff = eh * 60 + em - (sh * 60 + sm)
|
||||
if (diff < 0) diff += 24 * 60
|
||||
return diff
|
||||
}
|
||||
|
||||
function formatMinutes(minutes) {
|
||||
if (minutes === null || minutes === undefined) return '–'
|
||||
const h = Math.floor(minutes / 60)
|
||||
const m = minutes % 60
|
||||
return h > 0 ? `${h}h ${m}min` : `${m}min`
|
||||
}
|
||||
|
||||
/**
|
||||
* Startzeit fuer Git-Push-Worksheets nachtragen: Die Endzeit wurde beim Push
|
||||
* automatisch gesetzt, hier wird der Arbeitsbeginn erfasst. Beim Speichern
|
||||
* wird totalTime berechnet und isComment auf false gesetzt, damit der Eintrag
|
||||
* in der Arbeitszeit-Statistik zaehlt.
|
||||
*/
|
||||
export default function EditWorksheetTimeModal({ isOpen, onClose, worksheet, onSave }) {
|
||||
const [startDate, setStartDate] = useState('')
|
||||
const [startTime, setStartTime] = useState('')
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [error, setError] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen && worksheet) {
|
||||
setStartDate(worksheet.startDate || worksheet.endDate || '')
|
||||
setStartTime(worksheet.startTime || '')
|
||||
setError('')
|
||||
}
|
||||
}, [isOpen, worksheet])
|
||||
|
||||
const totalTime = useMemo(
|
||||
() => calculateMinutes(startTime, worksheet?.endTime),
|
||||
[startTime, worksheet]
|
||||
)
|
||||
|
||||
if (!isOpen || !worksheet) return null
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
if (!/^\d{2}\.\d{2}\.\d{4}$/.test(startDate)) {
|
||||
setError('Startdatum bitte als TT.MM.JJJJ angeben.')
|
||||
return
|
||||
}
|
||||
if (!/^\d{4}$/.test(startTime)) {
|
||||
setError('Startzeit bitte als HHMM angeben (z.B. 0930).')
|
||||
return
|
||||
}
|
||||
if (totalTime === null) {
|
||||
setError('Zeit konnte nicht berechnet werden.')
|
||||
return
|
||||
}
|
||||
setSaving(true)
|
||||
setError('')
|
||||
const result = await onSave(worksheet, {
|
||||
startDate,
|
||||
startTime,
|
||||
totalTime,
|
||||
isComment: false,
|
||||
})
|
||||
setSaving(false)
|
||||
if (result?.success) {
|
||||
onClose()
|
||||
} else {
|
||||
setError(result?.error || 'Speichern fehlgeschlagen')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="overlay">
|
||||
<span className="overlay-close" onClick={onClose}>
|
||||
×
|
||||
</span>
|
||||
<div className="overlay-content">
|
||||
<h2 className="mb-2">
|
||||
<FaClock style={{ marginRight: 8 }} />
|
||||
Zeit nachtragen – WSID {worksheet.wsid}
|
||||
</h2>
|
||||
<p className="text-grey" style={{ fontSize: '14px' }}>
|
||||
Die Endzeit wurde beim Git-Push automatisch gesetzt
|
||||
({worksheet.endDate} {worksheet.endTime ? `${worksheet.endTime.substring(0, 2)}:${worksheet.endTime.substring(2, 4)}` : ''}).
|
||||
Trage hier ein, wann die Arbeit begonnen hat.
|
||||
</p>
|
||||
|
||||
{error && (
|
||||
<div className="bg-red text-white p-2 mb-2" style={{ borderRadius: '4px' }}>
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label className="form-label">Startdatum (TT.MM.JJJJ)</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
value={startDate}
|
||||
onChange={(e) => setStartDate(e.target.value)}
|
||||
placeholder="11.07.2026"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label className="form-label">Startzeit (HHMM)</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
value={startTime}
|
||||
onChange={(e) => setStartTime(e.target.value.replace(/[^0-9]/g, '').slice(0, 4))}
|
||||
placeholder="0930"
|
||||
maxLength={4}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label className="form-label">Berechnete Arbeitszeit</label>
|
||||
<div style={{ fontSize: '18px', fontWeight: 600, color: '#10b981' }}>
|
||||
{formatMinutes(totalTime)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-center mt-2">
|
||||
<button type="submit" className="btn btn-green" disabled={saving}>
|
||||
{saving ? 'Speichert...' : 'Zeit speichern'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user