first commit

This commit is contained in:
exercict
2026-07-14 08:10:11 +04:00
commit fdfb0dd62e
60 changed files with 9930 additions and 0 deletions
+170
View File
@@ -0,0 +1,170 @@
<?php
$deadlineRank = function (array $task): int {
$deadline = taskDeadlineState($task['planned_at'] ?? null, $task['status'] ?? null);
return match ($deadline['code'] ?? '') {
'red' => 1,
'yellow' => 2,
'green' => 3,
default => 4,
};
};
foreach ($boards as &$board) {
if (empty($board['tasks']) || !is_array($board['tasks'])) {
continue;
}
usort($board['tasks'], function (array $a, array $b) use ($deadlineRank): int {
$rankA = $deadlineRank($a);
$rankB = $deadlineRank($b);
if ($rankA !== $rankB) {
return $rankA <=> $rankB;
}
return strtotime((string)($a['planned_at'] ?? '9999-12-31'))
<=> strtotime((string)($b['planned_at'] ?? '9999-12-31'));
});
}
unset($board);
?>
<div class="container-fluid py-3">
<div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h3 mb-0">Главная</h1>
</div>
<?php if (empty($boards)): ?>
<div class="alert alert-light border text-muted">
Нет досок для отображения на главной.
</div>
<?php else: ?>
<div class="row g-3">
<?php foreach ($boards as $board): ?>
<div class="col-12 col-md-6 col-xl-4">
<div class="card shadow-sm h-100">
<div class="card-header bg-white">
<div class="d-flex justify-content-between align-items-start gap-2">
<div>
<a href="/boards/<?= htmlspecialchars((string)$board['code']) ?>"
class="text-decoration-none fw-semibold fs-5">
<?= htmlspecialchars((string)$board['name']) ?>
</a>
<?php if (!empty($board['description'])): ?>
<div class="text-muted small mt-1">
<?= htmlspecialchars((string)$board['description']) ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
<div class="card-body">
<div class="d-flex flex-wrap gap-2 mb-3">
<span class="badge text-bg-secondary">
Всего: <?= (int)$board['stats']['total_count'] ?>
</span>
<span class="badge text-bg-secondary">
Новые: <?= (int)$board['stats']['new_count'] ?>
</span>
<span class="badge text-bg-primary">
В работе: <?= (int)$board['stats']['in_progress_count'] ?>
</span>
<span class="badge text-bg-success">
Завершено: <?= (int)$board['stats']['done_count'] ?>
</span>
</div>
<div class="list-group list-group-flush">
<?php if (empty($board['tasks'])): ?>
<div class="text-muted small">
В этой доске пока нет задач.
</div>
<?php else: ?>
<?php foreach ($board['tasks'] as $task): ?>
<?php
$deadline = taskDeadlineState($task['planned_at'] ?? null, $task['status'] ?? null);
$commentCount = (int)($task['comment_count'] ?? 0);
$lastCommentId = (int)($task['last_comment_id'] ?? 0);
$lastReadCommentId = (int)($task['last_read_comment_id'] ?? 0);
$isUnread = $commentCount > 0 && $lastCommentId > $lastReadCommentId;
$badgeClass = $isUnread ? 'bg-primary' : 'bg-secondary';
$statusClass = match ($task['status']) {
'NEW' => 'bg-secondary',
'IN_PROGRESS' => 'bg-primary',
'REVIEW' => 'bg-warning text-dark',
'DONE' => 'bg-success',
'CANCELED' => 'bg-dark',
'OVERDUE' => 'bg-danger',
default => 'bg-secondary',
};
?>
<div class="list-group-item px-2 <?= $deadline['class'] ?? '' ?>">
<div class="d-flex justify-content-between align-items-start gap-2">
<div class="flex-grow-1">
<a href="/tasks/show?id=<?= (int)$task['id'] ?>"
data-task-modal
data-task-id="<?= (int)$task['id'] ?>"
class="text-decoration-none fw-semibold">
<?= htmlspecialchars((string)$task['name']) ?>
</a>
<div class="small text-muted">
<?= htmlspecialchars((string)$task['crm_id']) ?>
</div>
<?php if (!empty($task['assignee_name'])): ?>
<div class="small text-muted">
Ответственный: <?= htmlspecialchars((string)$task['assignee_name']) ?>
</div>
<?php endif; ?>
<?php if (!empty($task['planned_at'])): ?>
<div class="small mt-1">
<span class="text-muted">План:</span>
<?= htmlspecialchars(date('d.m.Y H:i', strtotime((string)$task['planned_at']))) ?>
<?php if ($deadline): ?>
<span class="badge deadline-badge-<?= htmlspecialchars($deadline['code']) ?> ms-1">
<?= htmlspecialchars($deadline['text']) ?>
</span>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<div class="d-flex flex-column align-items-end gap-1">
<span class="badge <?= $statusClass ?>">
<?= htmlspecialchars(task_status_label((string)$task['status'])) ?>
</span>
<span
id="comment-badge-<?= (int)$task['id'] ?>"
class="badge <?= $badgeClass ?>"
data-task-id="<?= (int)$task['id'] ?>"
data-last-read-comment-id="<?= $lastReadCommentId ?>"
data-last-comment-id="<?= $lastCommentId ?>"
>
<?= $commentCount ?>
</span>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<div class="card-footer bg-white">
<a href="/boards/<?= htmlspecialchars((string)$board['code']) ?>" class="btn btn-sm btn-outline-primary">
Открыть доску
</a>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>