(int) $assignment['id']]) : task_cert_view_url('user.task_detail'); $wikiBasePath = '/' . trim(task_cert_site_code(), '/') . '/' . trim(task_cert_language_code(), '/') . '/wiki/'; $buildWikiPostUrl = static function (int $postId) use ($wikiBasePath): string { if ($postId <= 0) { return ''; } return $wikiBasePath . '?action=Post&id=' . $postId . '&embedded=1'; }; $formatDateTime = static function ($value): string { $value = trim((string) $value); if ($value === '') { return '-'; } try { return (new DateTimeImmutable($value))->format('d.m.Y H:i'); } catch (Throwable $throwable) { return $value; } }; $formatDueMessage = static function ($dueRaw): string { $dueRaw = trim((string) $dueRaw); if ($dueRaw === '') { return 'Kein Fälligkeitsdatum hinterlegt.'; } try { $dueAt = new DateTimeImmutable($dueRaw); $now = new DateTimeImmutable(); $days = (int) floor(($dueAt->getTimestamp() - $now->getTimestamp()) / 86400); if ($days === 0) { return 'Heute fällig (' . $dueAt->format('d.m.Y H:i') . ')'; } if ($days > 0) { return 'Fällig in ' . $days . ' Tag' . ($days === 1 ? '' : 'en') . ' (' . $dueAt->format('d.m.Y H:i') . ')'; } $overdueDays = abs($days); return 'Seit ' . $overdueDays . ' Tag' . ($overdueDays === 1 ? '' : 'en') . ' überfällig (' . $dueAt->format('d.m.Y H:i') . ')'; } catch (Throwable $throwable) { return $dueRaw; } }; $formFieldLabelsByMethod = []; foreach ($methods as $m) { $mId = (int) ($m['id'] ?? 0); if ((string) ($m['method_type'] ?? '') !== 'form_submit' || $mId <= 0) { continue; } $map = []; foreach ((array) ($m['form_fields'] ?? []) as $ff) { $fk = trim((string) ($ff['field_key'] ?? '')); if ($fk !== '') { $map[$fk] = trim((string) ($ff['label'] ?? $fk)); } } $formFieldLabelsByMethod[$mId] = $map; } $latestSubmissionByMethod = []; $allSubmissionsByMethod = []; foreach ($submissions as $submission) { $methodId = (int) ($submission['method_id'] ?? 0); if ($methodId <= 0) { continue; } if (!isset($latestSubmissionByMethod[$methodId])) { $latestSubmissionByMethod[$methodId] = $submission; } $allSubmissionsByMethod[$methodId][] = $submission; } $resolveMethodProgress = static function (int $methodId) use ($latestSubmissionByMethod, $submissionStatusLabels): array { $latest = $latestSubmissionByMethod[$methodId] ?? null; if (!is_array($latest)) { return [ 'state' => 'open', 'label' => 'Noch offen', 'note' => 'Bitte diesen Schritt ausführen.', ]; } $status = (string) ($latest['status'] ?? ''); if (in_array($status, ['auto_passed', 'approved'], true)) { return [ 'state' => 'done', 'label' => 'Erledigt', 'note' => 'Zuletzt am ' . ($latest['submitted_at'] ?? '-') . ' eingereicht.', ]; } if ($status === 'awaiting_approval') { return [ 'state' => 'pending', 'label' => 'Warten auf Freigabe', 'note' => 'Ihre Einreichung wird geprüft.', ]; } if ($status === 'rejected') { return [ 'state' => 'retry', 'label' => 'Erneut erforderlich', 'note' => 'Bitte Schritt erneut bearbeiten und abschicken.', ]; } return [ 'state' => 'open', 'label' => $submissionStatusLabels[$status] ?? 'Offen', 'note' => 'Bitte diesen Schritt abschließen.', ]; }; $isMethodCompleted = static function (int $methodId) use ($latestSubmissionByMethod): bool { $latest = $latestSubmissionByMethod[$methodId] ?? null; if (!is_array($latest)) { return false; } $status = (string) ($latest['status'] ?? ''); return in_array($status, ['auto_passed', 'approved'], true); }; $totalRequiredSteps = 0; $completedRequiredSteps = 0; foreach ($methods as $method) { if ((int) ($method['is_required'] ?? 1) !== 1) { continue; } $totalRequiredSteps++; if ($isMethodCompleted((int) ($method['id'] ?? 0))) { $completedRequiredSteps++; } } $remainingRequiredSteps = max(0, $totalRequiredSteps - $completedRequiredSteps); $methodCount = count($methods); ?>