Arbeitsblätter: Zeit für eigene Git-Pushes nachtragen
70 von 78 Arbeitsblättern sind Git-Pushes, die das Kundenportal mit
employeeId "gitea" anlegt; in employeeName steht der Gitea-Name des
Pushers ("knso", "ANDJ", "JUSN" oder der volle Name). Sie gehören dem
Mitarbeiter mit diesem Kürzel oder Namen - der eigene employees-Eintrag
kommt jetzt aus dem AuthContext.
Bei offenen Pushes heißt der Button "Zeit nachtragen": Beginn ist Pflicht,
das Ende ist der Push. Beim Speichern wird isComment false, damit die Zeit
in der Arbeitszeit zählt (wie früher im Modal der alten Ticketzeile).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
149b38b94b
commit
0c884a57d7
7 files changed
+69
-31
No files matched your search
@@ -22,7 +22,7 @@ import { StatusPill, PriorityPill } from './ui/StatusPill'
|
||||
import { useWorksheets } from '../hooks/useWorksheets'
|
||||
import { useAuth } from '../context/AuthContext'
|
||||
import { databases, DATABASE_ID, COLLECTIONS } from '../lib/appwrite'
|
||||
import { serviceTypeLabel } from '../lib/ticketForm'
|
||||
import { serviceTypeLabel, canEditWorksheetTimes } from '../lib/ticketForm'
|
||||
|
||||
const TABS = [
|
||||
{ id: 'details', label: 'Details' },
|
||||
@@ -33,7 +33,7 @@ const TABS = [
|
||||
]
|
||||
|
||||
export default function TicketCard({ ticket, onUpdate }) {
|
||||
const { user } = useAuth()
|
||||
const { user, employee } = useAuth()
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const [activeTab, setActiveTab] = useState('details')
|
||||
const [showCreateWorksheet, setShowCreateWorksheet] = useState(false)
|
||||
@@ -148,7 +148,7 @@ export default function TicketCard({ ticket, onUpdate }) {
|
||||
worksheets={worksheets}
|
||||
totalTime={getTotalTime()}
|
||||
loading={worksheetsLoading}
|
||||
currentUser={user}
|
||||
canEditTimes={(ws) => canEditWorksheetTimes(ws, user, employee)}
|
||||
onEditTimes={setEditTimesWorksheet}
|
||||
/>
|
||||
</div>
|
||||
@@ -174,7 +174,7 @@ export default function TicketCard({ ticket, onUpdate }) {
|
||||
<WorksheetTimesModal
|
||||
worksheet={editTimesWorksheet}
|
||||
onClose={() => setEditTimesWorksheet(null)}
|
||||
onSave={(ws, times) => updateWorksheetTimes(ws, times, user)}
|
||||
onSave={(ws, times) => updateWorksheetTimes(ws, times, user, employee)}
|
||||
/>
|
||||
)}
|
||||
<StatusHistoryModal isOpen={showHistoryModal} onClose={() => setShowHistoryModal(false)} worksheets={worksheets} ticket={ticket} />
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { FaClock, FaUser, FaExchangeAlt, FaComment, FaChevronDown, FaChevronUp, FaPen } from 'react-icons/fa'
|
||||
import { serviceTypeLabel, canEditWorksheetTimes } from '../lib/ticketForm'
|
||||
|
||||
function needsTimeEntry(ws) {
|
||||
return ws.serviceType === 'GIT' && (!ws.startTime || !Number(ws.totalTime))
|
||||
}
|
||||
import { serviceTypeLabel, needsTimeEntry } from '../lib/ticketForm'
|
||||
|
||||
const headerButtonStyle = {
|
||||
background: 'rgba(255,255,255,0.25)',
|
||||
@@ -16,7 +12,7 @@ const headerButtonStyle = {
|
||||
marginRight: '8px',
|
||||
}
|
||||
|
||||
export default function WorksheetList({ worksheets, totalTime, loading, onEditTime, onTogglePlan, currentUser, onEditTimes }) {
|
||||
export default function WorksheetList({ worksheets, totalTime, loading, onEditTime, onTogglePlan, canEditTimes, onEditTimes }) {
|
||||
const [expandedWorksheets, setExpandedWorksheets] = useState({})
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -176,7 +172,7 @@ export default function WorksheetList({ worksheets, totalTime, loading, onEditTi
|
||||
<FaClock className="me-1" /> Zeit nachtragen
|
||||
</button>
|
||||
)}
|
||||
{onEditTimes && canEditWorksheetTimes(ws, currentUser) && (
|
||||
{onEditTimes && canEditTimes?.(ws) && (
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm"
|
||||
@@ -187,7 +183,9 @@ export default function WorksheetList({ worksheets, totalTime, loading, onEditTi
|
||||
onEditTimes(ws)
|
||||
}}
|
||||
>
|
||||
<FaPen className="me-1" /> Zeiten bearbeiten
|
||||
{needsTimeEntry(ws)
|
||||
? <><FaClock className="me-1" /> Zeit nachtragen</>
|
||||
: <><FaPen className="me-1" /> Zeiten bearbeiten</>}
|
||||
</button>
|
||||
)}
|
||||
{onTogglePlan && !ws.isComment && Number(ws.totalTime) > 0 && (
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useState } from 'react'
|
||||
import { FaTimes } from 'react-icons/fa'
|
||||
import { isoToGermanDate, timeToWoms, germanDateToIso, womsTimeToInput, minutesBetween } from '../lib/ticketForm'
|
||||
import { isoToGermanDate, timeToWoms, germanDateToIso, womsTimeToInput, minutesBetween, isGitWorksheet, needsTimeEntry } 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),
|
||||
startDate: germanDateToIso(worksheet.startDate || worksheet.endDate),
|
||||
startTime: womsTimeToInput(worksheet.startTime),
|
||||
endDate: germanDateToIso(worksheet.endDate || worksheet.startDate),
|
||||
endTime: womsTimeToInput(worksheet.endTime)
|
||||
@@ -13,9 +13,10 @@ const formFromWorksheet = (worksheet) => ({
|
||||
|
||||
/**
|
||||
* Beginn, Ende und Arbeitszeit eines Arbeitsblatts nachtraeglich aendern.
|
||||
* Wer das darf, entscheidet canEditWorksheetTimes (useWorksheets).
|
||||
* Wer das darf, entscheidet canEditWorksheetTimes (lib/ticketForm).
|
||||
*/
|
||||
export default function WorksheetTimesModal({ worksheet, onClose, onSave }) {
|
||||
const isGit = isGitWorksheet(worksheet)
|
||||
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.
|
||||
@@ -72,8 +73,11 @@ export default function WorksheetTimesModal({ worksheet, onClose, onSave }) {
|
||||
</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>
|
||||
<h2 className="mb-2">{needsTimeEntry(worksheet) ? 'Zeit nachtragen' : 'Zeiten bearbeiten'}</h2>
|
||||
<p className="text-grey" style={{ fontSize: '14px', marginBottom: '16px' }}>
|
||||
WSID {worksheet.wsid}
|
||||
{isGit && <><br />Das Ende ist der Zeitpunkt des Git-Pushs. Trag ein, wann die Arbeit begonnen hat.</>}
|
||||
</p>
|
||||
|
||||
{error && (
|
||||
<div className="bg-red text-white p-2 mb-2" style={{ borderRadius: '4px' }}>
|
||||
@@ -88,6 +92,7 @@ export default function WorksheetTimesModal({ worksheet, onClose, onSave }) {
|
||||
id="worksheet-times-start"
|
||||
timeLabel="Uhrzeit Beginn"
|
||||
required
|
||||
timeRequired={isGit}
|
||||
date={formData.startDate}
|
||||
time={formData.startTime}
|
||||
onDateChange={handleStartDateChange}
|
||||
|
||||
@@ -9,7 +9,7 @@ const openCalendar = (e) => {
|
||||
|
||||
/* Datum mit Kalender und Uhrzeit nebeneinander. Werte wie die Browser-Felder:
|
||||
Datum "yyyy-mm-dd", Uhrzeit "hh:mm" - umgerechnet wird erst beim Speichern. */
|
||||
export default function DateTimeInput({ id, date, time, onDateChange, onTimeChange, min, required, timeLabel }) {
|
||||
export default function DateTimeInput({ id, date, time, onDateChange, onTimeChange, min, required, timeRequired, timeLabel }) {
|
||||
return (
|
||||
<div className="datetime-pair">
|
||||
<input
|
||||
@@ -26,6 +26,7 @@ export default function DateTimeInput({ id, date, time, onDateChange, onTimeChan
|
||||
type="time"
|
||||
className="form-control"
|
||||
aria-label={timeLabel}
|
||||
required={timeRequired}
|
||||
value={time}
|
||||
onChange={(e) => onTimeChange(e.target.value)}
|
||||
/>
|
||||
|
||||
Reference in new issue
Block a user