Eigene Arbeitsblätter (employeeId = angemeldeter Benutzer, kein reiner Kommentar) bekommen im Kopf den Button "Zeiten bearbeiten". Der Dialog ändert Beginn, Ende und Arbeitszeit; die Minuten rechnen wie beim Anlegen mit, von Hand eingetragene Minuten bleiben stehen. Gespeichert werden nur die fünf Zeitfelder, wieder als dd.mm.yyyy / hhmm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
141 lines
5.1 KiB
React
141 lines
5.1 KiB
React
import { useState } from 'react'
|
|
import { FaTimes } from 'react-icons/fa'
|
|
import { isoToGermanDate, timeToWoms, germanDateToIso, womsTimeToInput, minutesBetween } from '../lib/ticketForm'
|
|
import { DateTimeInput } from './ui'
|
|
|
|
// Gespeichert ist dd.mm.yyyy / hhmm, die Kalender-Felder brauchen yyyy-mm-dd / hh:mm
|
|
const formFromWorksheet = (worksheet) => ({
|
|
startDate: germanDateToIso(worksheet.startDate),
|
|
startTime: womsTimeToInput(worksheet.startTime),
|
|
endDate: germanDateToIso(worksheet.endDate || worksheet.startDate),
|
|
endTime: womsTimeToInput(worksheet.endTime)
|
|
})
|
|
|
|
/**
|
|
* Beginn, Ende und Arbeitszeit eines Arbeitsblatts nachtraeglich aendern.
|
|
* Wer das darf, entscheidet canEditWorksheetTimes (useWorksheets).
|
|
*/
|
|
export default function WorksheetTimesModal({ worksheet, onClose, onSave }) {
|
|
const [formData, setFormData] = useState(() => formFromWorksheet(worksheet))
|
|
// null = die Arbeitszeit folgt Beginn und Ende. Passte sie schon vorher nicht dazu,
|
|
// wurde sie von Hand eingetragen (z.B. ohne Pause) und bleibt stehen.
|
|
const [manualTotal, setManualTotal] = useState(() => {
|
|
const stored = Number(worksheet.totalTime) || 0
|
|
return !stored || stored === minutesBetween(formData.startTime, formData.endTime) ? null : stored
|
|
})
|
|
const [saving, setSaving] = useState(false)
|
|
const [error, setError] = useState('')
|
|
|
|
const calculatedTotal = minutesBetween(formData.startTime, formData.endTime)
|
|
const totalTime = manualTotal ?? calculatedTotal ?? 0
|
|
|
|
const handleChange = (field, value) => {
|
|
setFormData(prev => ({ ...prev, [field]: value }))
|
|
}
|
|
|
|
// Das Ende darf nicht vor dem Start liegen, deshalb rueckt es mit
|
|
const handleStartDateChange = (value) => {
|
|
setFormData(prev => ({
|
|
...prev,
|
|
startDate: value,
|
|
endDate: value && prev.endDate && prev.endDate < value ? value : prev.endDate
|
|
}))
|
|
}
|
|
|
|
const handleSubmit = async (e) => {
|
|
e.preventDefault()
|
|
setSaving(true)
|
|
setError('')
|
|
try {
|
|
const result = await onSave(worksheet, {
|
|
startDate: isoToGermanDate(formData.startDate),
|
|
startTime: timeToWoms(formData.startTime),
|
|
endDate: isoToGermanDate(formData.endDate),
|
|
endTime: timeToWoms(formData.endTime),
|
|
totalTime: parseInt(totalTime, 10) || 0
|
|
})
|
|
if (result?.success) {
|
|
onClose()
|
|
return
|
|
}
|
|
setError(result?.error || 'Speichern fehlgeschlagen')
|
|
} catch (err) {
|
|
setError(err.message || 'Speichern fehlgeschlagen')
|
|
}
|
|
setSaving(false)
|
|
}
|
|
|
|
return (
|
|
<div className="overlay">
|
|
<span className="overlay-close" onClick={onClose}>
|
|
<FaTimes />
|
|
</span>
|
|
<div className="overlay-content" style={{ maxWidth: 560 }}>
|
|
{/* Kurzer Titel: auf dem Handy laeuft ein langer unter das Schliessen-X */}
|
|
<h2 className="mb-2">Zeiten bearbeiten</h2>
|
|
<p className="text-grey" style={{ fontSize: '14px', marginBottom: '16px' }}>WSID {worksheet.wsid}</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" htmlFor="worksheet-times-start">Beginn</label>
|
|
<DateTimeInput
|
|
id="worksheet-times-start"
|
|
timeLabel="Uhrzeit Beginn"
|
|
required
|
|
date={formData.startDate}
|
|
time={formData.startTime}
|
|
onDateChange={handleStartDateChange}
|
|
onTimeChange={(value) => handleChange('startTime', value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label" htmlFor="worksheet-times-end">Ende</label>
|
|
<DateTimeInput
|
|
id="worksheet-times-end"
|
|
timeLabel="Uhrzeit Ende"
|
|
required
|
|
min={formData.startDate}
|
|
date={formData.endDate}
|
|
time={formData.endTime}
|
|
onDateChange={(value) => handleChange('endDate', value)}
|
|
onTimeChange={(value) => handleChange('endTime', value)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="form-group">
|
|
<label className="form-label" htmlFor="worksheet-times-total">Arbeitszeit (Minuten)</label>
|
|
<input
|
|
id="worksheet-times-total"
|
|
type="number"
|
|
className="form-control"
|
|
min="0"
|
|
step="1"
|
|
value={totalTime}
|
|
onChange={(e) => setManualTotal(e.target.value)}
|
|
placeholder="0"
|
|
/>
|
|
<small style={{ color: '#a0aec0', fontSize: '12px' }}>
|
|
{manualTotal === null && calculatedTotal !== null
|
|
? '✓ Automatisch berechnet'
|
|
: 'Manuell eingeben'}
|
|
</small>
|
|
</div>
|
|
|
|
<div className="text-center mt-2">
|
|
<button type="submit" className="btn btn-dark" disabled={saving}>
|
|
{saving ? 'Speichert...' : 'Speichern'}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|