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>
143 lines
4.6 KiB
JavaScript
143 lines
4.6 KiB
JavaScript
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>
|
||
)
|
||
}
|