/* Anzeige- und Rechenlogik der Arbeitsblatt-Zeilen und der Kennzahlen darueber. Kommentare haben keine Arbeitszeit und zaehlen nie mit. Die Zeit in der Zeile ist die gespeicherte Arbeitszeit (totalTime); die Kennzahlen rechnen die Unterstuetzung mit. */ import { worksheetMinutes, supportMinutes, parseSupporters, firstName } from './support' import { needsTimeEntry, worksheetTone, isGitWorksheet, serviceTypeLabel } from './ticketForm' import { statusLabel } from './ticketStatus' import { stepLabel } from './timeSteps' import { displayDate, displayTime } from './ticketView' // Summe der Arbeitszeit inklusive Unterstuetzung ueber alle Bloecke ohne Kommentare, optional gefiltert. // Dieselbe Funktion rechnet die Spalte "Zeit" der Ticketliste. export function sumWorksheetMinutes(worksheets, predicate = () => true) { return (worksheets || []) .filter((ws) => !ws.isComment && predicate(ws)) .reduce((sum, ws) => sum + worksheetMinutes(ws), 0) } // Kennzahlen ueber der Liste: Arbeitszeit gesamt, davon Abo-Stunden, Anzahl offener Git-Zeiten export function worksheetSums(worksheets) { const list = worksheets || [] return { totalMinutes: sumWorksheetMinutes(list), aboMinutes: sumWorksheetMinutes(list, (ws) => Boolean(ws.countsToPlan)), openCount: list.filter(needsTimeEntry).length, } } // Regel fuer den Abo-Schalter einer Zeile; ob die Seite ihn ueberhaupt anbietet (onTogglePlan), prueft die Komponente export function showAboToggle(ws, aboHoursAllowed) { return Boolean(!ws.isComment && Number(ws.totalTime) > 0 && (aboHoursAllowed || ws.countsToPlan)) } // Wann: Startzweig, wenn ein Startdatum gesetzt ist, sonst der Endzweig. Altwerte bleiben Rohtext. export function worksheetWhen(ws) { const start = String(ws?.startDate ?? '').trim() !== '' return start ? { date: displayDate(ws.startDate), time: displayTime(ws.startTime) } : { date: displayDate(ws?.endDate), time: displayTime(ws?.endTime) } } export function worksheetKindLabel(ws) { if (ws?.isComment && !isGitWorksheet(ws)) return 'Kommentar' return serviceTypeLabel(ws?.serviceType) || '' } // Git-Pushes: orange, bis die Zeit nachgetragen ist, danach gruen; sonst kein Abzeichen export function worksheetBadge(ws) { const tone = worksheetTone(ws) if (tone === 'git-open') return { tone: 'orange', text: 'Zeit offen' } if (tone === 'git-done') return { tone: 'green', text: 'Zeit eingetragen' } return null } // Nur wenn sich der Status geaendert hat export function statusAfterLabel(ws) { const next = ws?.newStatus if (!next || next === ws.oldStatus) return '' return `Status danach: ${statusLabel(next)}` } // Je unterstuetzender Person eine Zeile, z. B. "Unterstützung Anna · DNS · 30 min" export function supportLines(ws) { if (!ws || ws.isComment) return [] const minutes = stepLabel(supportMinutes(ws.totalTime)) return parseSupporters(ws.supporters).map((sup) => `${['Unterstützung', firstName(sup.name)].filter(Boolean).join(' ')} · ${sup.task} · ${minutes}`) } // Zeit rechts in der Zeile: Kommentare leer, ohne Arbeitszeit ein Strich export function timeLabel(ws) { if (ws?.isComment) return '' const minutes = Number(ws?.totalTime) || 0 return minutes <= 0 ? '–' : stepLabel(minutes) }