|
- <?php
-
- declare(strict_types=1);
-
- namespace App\Repositories;
-
- use Core\Database;
-
- class TaskRepository
- {
- public function __construct(protected ?Database $database = null)
- {
- $this->database ??= database();
- }
-
- public function create(int $projectId, array $data): int
- {
- $position = (int) ($this->database->first(
- 'SELECT COALESCE(MAX(position), 0) + 1 AS next_position FROM tasks WHERE project_id = :project_id AND status = :status',
- [
- 'project_id' => $projectId,
- 'status' => $data['status'] ?? 'backlog',
- ]
- )['next_position'] ?? 1);
-
- $this->database->execute(
- 'INSERT INTO tasks (
- project_id, title, description, status, priority, assignee, estimate_hours, due_date, position, completed_at
- ) VALUES (
- :project_id, :title, :description, :status, :priority, :assignee, :estimate_hours, :due_date, :position, :completed_at
- )',
- [
- 'project_id' => $projectId,
- 'title' => $data['title'],
- 'description' => $data['description'] ?? '',
- 'status' => $data['status'] ?? 'backlog',
- 'priority' => $data['priority'] ?? 'normal',
- 'assignee' => $data['assignee'] ?? '',
- 'estimate_hours' => $data['estimate_hours'] ?? null,
- 'due_date' => $data['due_date'] ?? null,
- 'position' => $position,
- 'completed_at' => ($data['status'] ?? 'backlog') === 'done' ? date('Y-m-d H:i:s') : null,
- ]
- );
-
- return (int) $this->database->pdo()->lastInsertId();
- }
-
- public function updateStatus(int $taskId, string $status): ?int
- {
- $task = $this->database->first('SELECT id, project_id, title, status FROM tasks WHERE id = :id', ['id' => $taskId]);
-
- if ($task === null) {
- return null;
- }
-
- $completedAt = $status === 'done' ? date('Y-m-d H:i:s') : null;
-
- $this->database->execute(
- 'UPDATE tasks
- SET status = :status,
- completed_at = :completed_at,
- updated_at = CURRENT_TIMESTAMP
- WHERE id = :id',
- [
- 'status' => $status,
- 'completed_at' => $completedAt,
- 'id' => $taskId,
- ]
- );
-
- return (int) $task['project_id'];
- }
-
- public function dueSoon(int $limit = 6): array
- {
- $limit = max(1, min(25, $limit));
-
- return $this->database->query(
- 'SELECT t.*, p.name AS project_name, p.code AS project_code
- FROM tasks t
- INNER JOIN projects p ON p.id = t.project_id
- WHERE t.status != "done"
- AND t.due_date IS NOT NULL
- AND date(t.due_date) BETWEEN date("now") AND date("now", "+7 day")
- ORDER BY date(t.due_date) ASC, CASE t.priority WHEN "urgent" THEN 0 WHEN "high" THEN 1 WHEN "normal" THEN 2 ELSE 3 END, t.id DESC
- LIMIT ' . $limit
- );
- }
-
- public function overdue(int $limit = 6): array
- {
- $limit = max(1, min(25, $limit));
-
- return $this->database->query(
- 'SELECT t.*, p.name AS project_name, p.code AS project_code
- FROM tasks t
- INNER JOIN projects p ON p.id = t.project_id
- WHERE t.status != "done"
- AND t.due_date IS NOT NULL
- AND date(t.due_date) < date("now")
- ORDER BY date(t.due_date) ASC, t.id DESC
- LIMIT ' . $limit
- );
- }
-
- public function countsByStatus(int $projectId): array
- {
- $rows = $this->database->query(
- 'SELECT status, COUNT(*) AS total
- FROM tasks
- WHERE project_id = :project_id
- GROUP BY status',
- ['project_id' => $projectId]
- );
-
- $counts = [];
- foreach ($rows as $row) {
- $counts[$row['status']] = (int) $row['total'];
- }
-
- return $counts;
- }
-
- public function forProject(int $projectId): array
- {
- return $this->database->query(
- 'SELECT *
- FROM tasks
- WHERE project_id = :project_id
- ORDER BY
- CASE status
- WHEN "backlog" THEN 0
- WHEN "in-progress" THEN 1
- WHEN "review" THEN 2
- WHEN "blocked" THEN 3
- WHEN "done" THEN 4
- ELSE 5
- END,
- CASE priority
- WHEN "urgent" THEN 0
- WHEN "high" THEN 1
- WHEN "normal" THEN 2
- ELSE 3
- END,
- due_date IS NULL,
- due_date ASC,
- position ASC,
- id ASC',
- ['project_id' => $projectId]
- );
- }
- }
|