Files
awo-hamburg-intranet/module/tasks/pages/user/my_tasks.php
Moritz Weinmann 743476f64a Module tasks + knowledgecenter_update aus Kundenprojekt übernehmen (bereinigt)
Beide Module wurden aus einem anderen Kundenprojekt kopiert und bereinigt:

Knowledgecenter:
- Bild-Cache (1.985 Dateien) geleert, Ordnerstruktur mit .gitkeep behalten
- Files-Gallery-Lizenzschlüssel entfernt (config.php)
- Kundenspezifische Kategorien gelöscht: Teil I/II/III QM-Struktur,
  nummerierte QM-Kapitel, Gremien (Präsidium/Finanzausschuss/Landesausschuss),
  Sitzungsservice-Serie, Protokoll-Abteilungen, Testeinträge
- 56 generische Kategorien bleiben (Downloads, Onboarding, Personalthemen …)

Tasks:
- Alle Betriebsdaten gelöscht (114 Tasks, 914 Submissions, 579 Assignments)
- Task-Definitionen und Verlinkungen geleert
- Kategoriestruktur bleibt (Allgemein, IT, Personal, Buchhaltung …)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 09:20:02 +02:00

285 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
if (!isset($assignments) && !isset($error)) {
require_once dirname(dirname(__DIR__)) . '/actions/user/my_tasks_action.php';
$viewData = task_cert_user_my_tasks_action();
if (is_array($viewData)) {
extract($viewData, EXTR_SKIP);
}
}
$error = $error ?? null;
$assignments = $assignments ?? [];
$statusLabels = TaskCertConstants::assignmentStatusLabels();
$completedStatuses = TaskCertConstants::COMPLETED_STATUSES;
if (!function_exists('task_cert_render_styles')) {
require_once dirname(dirname(__DIR__)) . '/bootstrap.php';
}
task_cert_render_styles(['user']);
$taskDetailUrl = task_cert_view_url('user.task_detail');
$myTasksUrl = task_cert_view_url('user.my_tasks');
$now = new DateTimeImmutable('now');
$statusFilter = TaskCertRequest::queryString('status', '');
if ($statusFilter !== '' && !array_key_exists($statusFilter, $statusLabels)) {
$statusFilter = '';
}
if ($statusFilter !== '') {
$assignments = array_values(array_filter($assignments, static function (array $a) use ($statusFilter): bool {
return ($a['status'] ?? '') === $statusFilter;
}));
}
// Active & completed assignments: alle Zyklen separat anzeigen.
// Aktive: älteste zuerst (überfällige Rückstände oben).
// Abgeschlossene: neueste zuerst (unter <details> im UI eingeklappt).
$byTaskId = [];
foreach ($assignments as $a) {
$byTaskId[(int) ($a['task_id'] ?? 0)][] = $a;
}
$assignments = [];
foreach ($byTaskId as $taskAssignments) {
$active = [];
$completed = [];
foreach ($taskAssignments as $a) {
if (in_array($a['status'] ?? '', $completedStatuses, true)) {
$completed[] = $a;
} else {
$active[] = $a;
}
}
if ($active !== []) {
usort($active, static function (array $a, array $b): int {
$aDue = strtotime((string) ($a['due_at'] ?? '9999-12-31'));
$bDue = strtotime((string) ($b['due_at'] ?? '9999-12-31'));
return $aDue <=> $bDue;
});
foreach ($active as $a) {
$assignments[] = $a;
}
}
if ($completed !== []) {
usort($completed, static function (array $a, array $b): int {
return strtotime((string) ($b['completed_at'] ?? '0')) - strtotime((string) ($a['completed_at'] ?? '0'));
});
foreach ($completed as $a) {
$assignments[] = $a;
}
}
}
$formatDateShort = static function ($value): string {
$value = trim((string) $value);
if ($value === '') {
return '';
}
try {
return (new DateTimeImmutable($value))->format('d.m.Y');
} catch (Throwable $throwable) {
return $value;
}
};
$getCardMeta = static function (array $assignment) use ($formatDateShort): string {
$parts = [];
$dueAt = trim((string) ($assignment['due_at'] ?? ''));
if ($dueAt !== '') {
$parts[] = 'Fällig bis ' . $formatDateShort($dueAt);
} else {
$parts[] = 'Kein Fälligkeitsdatum';
}
// Zyklus-Zeitraum nur anzeigen, wenn die Aufgabe wiederkehrend ist
// (bei 'once' irrelevant). So versteht der User bei Rückständen,
// welcher Zyklus welcher Karte zugeordnet ist.
$cycleKey = (string) ($assignment['cycle_key'] ?? '');
$cycleStart = trim((string) ($assignment['cycle_start_at'] ?? ''));
$cycleEnd = trim((string) ($assignment['cycle_end_at'] ?? ''));
$showCyclePeriod = (int) ($assignment['show_cycle_period'] ?? 0) === 1;
if ($showCyclePeriod && $cycleKey !== '' && $cycleKey !== 'once' && $cycleStart !== '' && $cycleEnd !== '') {
$parts[] = 'Zeitraum ' . $formatDateShort($cycleStart) . '' . $formatDateShort($cycleEnd);
}
return implode(' · ', $parts);
};
$isAssignmentOverdueByDate = static function (array $assignment, DateTimeImmutable $now): bool {
$status = (string) ($assignment['status'] ?? '');
if ($status === 'completed') {
return false;
}
$dueAt = trim((string) ($assignment['due_at'] ?? ''));
if ($dueAt === '') {
return false;
}
try {
return (new DateTimeImmutable($dueAt)) < $now;
} catch (Throwable $throwable) {
return false;
}
};
$groupedAssignments = [];
$categoryOrder = [];
foreach ($assignments as $assignment) {
$categoryName = trim((string) ($assignment['task_category_name'] ?? ''));
if ($categoryName === '') {
$categoryName = 'Allgemein';
}
if (!array_key_exists($categoryName, $groupedAssignments)) {
$groupedAssignments[$categoryName] = [];
$categoryOrder[] = $categoryName;
}
$groupedAssignments[$categoryName][] = $assignment;
}
?>
<div class="task-cert task-cert-user-my-tasks">
<?php if ($error): ?>
<div class="task-cert-error"><?php echo TaskCertView::e($error); ?></div>
<?php endif; ?>
<form method="get" action="<?php echo TaskCertView::e($myTasksUrl); ?>" class="task-cert-user-filter-bar">
<label for="task-cert-user-status-filter" class="task-cert-sr-only">Status filtern</label>
<select name="status" id="task-cert-user-status-filter" aria-label="Status filtern" onchange="this.form.submit()">
<option value="">Alle Status</option>
<?php foreach ($statusLabels as $key => $label): ?>
<option value="<?php echo TaskCertView::e($key); ?>" <?php echo $statusFilter === $key ? 'selected' : ''; ?>>
<?php echo TaskCertView::e($label); ?>
</option>
<?php endforeach; ?>
</select>
<?php if ($statusFilter !== ''): ?>
<a href="<?php echo TaskCertView::e($myTasksUrl); ?>" class="task-cert-user-filter-reset">Zurücksetzen</a>
<?php endif; ?>
</form>
<?php if ($assignments === []): ?>
<div class="task-cert-block">
<?php if ($statusFilter !== ''): ?>
Keine Aufgaben mit Status &bdquo;<?php echo TaskCertView::e($statusLabels[$statusFilter] ?? $statusFilter); ?>&ldquo; vorhanden.
<?php else: ?>
Aktuell sind keine Aufgaben vorhanden.
<?php endif; ?>
</div>
<?php else: ?>
<?php foreach ($categoryOrder as $categoryName): ?>
<?php
$categoryAssignments = $groupedAssignments[$categoryName] ?? [];
if ($categoryAssignments === []) { continue; }
$activeAssignments = [];
$completedAssignments = [];
foreach ($categoryAssignments as $a) {
if (in_array($a['status'] ?? '', $completedStatuses, true)) {
$completedAssignments[] = $a;
} else {
$activeAssignments[] = $a;
}
}
usort($completedAssignments, static function (array $a, array $b): int {
return strtotime((string) ($b['completed_at'] ?? '0')) - strtotime((string) ($a['completed_at'] ?? '0'));
});
$activeCount = count($activeAssignments);
$completedCount = count($completedAssignments);
?>
<section class="task-cert-user-category-group">
<header class="task-cert-user-category-head">
<h3><?php echo TaskCertView::e($categoryName); ?></h3>
<span><?php echo $activeCount; ?> offen<?php echo $completedCount > 0 ? ', ' . $completedCount . ' abgeschlossen' : ''; ?></span>
</header>
<?php if ($activeAssignments !== []): ?>
<div class="task-cert-user-task-cards">
<?php foreach ($activeAssignments as $assignment): ?>
<?php
$status = (string) ($assignment['status'] ?? '');
$title = (string) ($assignment['title'] ?? 'Aufgabe');
$metaText = $getCardMeta($assignment);
$isOverdueByDate = $isAssignmentOverdueByDate($assignment, $now);
$isEscalated = (int) ($assignment['escalation_level'] ?? 0) > 0;
$cardClasses = [
'task-cert-user-task-card',
'status-' . $status,
];
if ($isOverdueByDate) {
$cardClasses[] = 'is-overdue-date';
}
if ($isEscalated) {
$cardClasses[] = 'is-escalated';
}
?>
<a
href="<?php echo TaskCertView::e($taskDetailUrl . '?assignment_id=' . (int) $assignment['id']); ?>"
class="<?php echo TaskCertView::e(implode(' ', $cardClasses)); ?>"
>
<div class="task-cert-user-task-card-head">
<strong><?php echo TaskCertView::e($title); ?></strong>
<span class="task-cert-user-status-badge status-<?php echo TaskCertView::e($status); ?>">
<?php echo TaskCertView::e($statusLabels[$status] ?? $status); ?>
</span>
</div>
<div class="task-cert-user-task-card-meta">
<?php echo TaskCertView::e($metaText); ?>
</div>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($completedAssignments !== []): ?>
<details class="task-cert-user-completed-group">
<summary>
<?php echo $completedCount; ?> abgeschlossene Aufgabe<?php echo $completedCount === 1 ? '' : 'n'; ?> anzeigen
</summary>
<div class="task-cert-user-task-cards">
<?php foreach ($completedAssignments as $assignment): ?>
<?php
$status = (string) ($assignment['status'] ?? '');
$title = (string) ($assignment['title'] ?? 'Aufgabe');
$metaText = $getCardMeta($assignment);
$cardClasses = ['task-cert-user-task-card', 'status-' . $status];
?>
<a
href="<?php echo TaskCertView::e($taskDetailUrl . '?assignment_id=' . (int) $assignment['id']); ?>"
class="<?php echo TaskCertView::e(implode(' ', $cardClasses)); ?>"
>
<div class="task-cert-user-task-card-head">
<strong><?php echo TaskCertView::e($title); ?></strong>
<span class="task-cert-user-status-badge status-<?php echo TaskCertView::e($status); ?>">
<?php echo TaskCertView::e($statusLabels[$status] ?? $status); ?>
</span>
</div>
<div class="task-cert-user-task-card-meta">
<?php echo TaskCertView::e($metaText); ?>
</div>
</a>
<?php endforeach; ?>
</div>
</details>
<?php endif; ?>
<?php if ($activeAssignments === [] && $completedAssignments === []): ?>
<div class="task-cert-block">Keine Aufgaben in dieser Kategorie.</div>
<?php endif; ?>
</section>
<?php endforeach; ?>
<?php endif; ?>
</div>