All files / main/services taskBoardService.ts

95.45% Statements 21/22
63.15% Branches 12/19
88.88% Functions 8/9
95.23% Lines 20/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57      1x     3x                         1x 1x       1x 1x   1x 5x 3x 5x 5x 5x     1x 3x 1x 2x   1x 3x   1x   1x                      
import type { TaskBoardItem, TaskBoardSnapshot } from '@shared/types'
import type { TaskRepository, TimerSessionRepository } from '@main/ports/repositories'
 
const buildTaskBoardItem = (
  task: Awaited<ReturnType<TaskRepository['list']>>[number],
  metrics: { focusMinutes: number; completedPomodoros: number }
): TaskBoardItem => ({
  id: task.id,
  title: task.title,
  sortOrder: task.sortOrder,
  completedAt: task.completedAt,
  createdAt: task.createdAt,
  updatedAt: task.updatedAt,
  focusMinutes: metrics.focusMinutes,
  completedPomodoros: metrics.completedPomodoros
})
 
export class TaskBoardService {
  constructor(
    private readonly tasks: TaskRepository,
    private readonly sessions: TimerSessionRepository
  ) {}
 
  async get(): Promise<TaskBoardSnapshot> {
    const [tasks, sessions] = await Promise.all([this.tasks.list(), this.sessions.list()])
    const metricsByTaskId = new Map<string, { focusMinutes: number; completedPomodoros: number }>()
 
    for (const session of sessions) {
      if (session.phase !== 'focus' || !session.completed || !session.taskId) continue
      const entry = metricsByTaskId.get(session.taskId) ?? { focusMinutes: 0, completedPomodoros: 0 }
      entry.focusMinutes += Math.round((session.actualDurationMs ?? 0) / 60_000)
      entry.completedPomodoros += 1
      metricsByTaskId.set(session.taskId, entry)
    }
 
    const activeItems = tasks
      .filter((task) => !task.completedAt)
      .sort((left, right) => left.sortOrder - right.sortOrder || left.createdAt.localeCompare(right.createdAt))
      .map((task) => buildTaskBoardItem(task, metricsByTaskId.get(task.id) ?? { focusMinutes: 0, completedPomodoros: 0 }))
 
    const completedItems = tasks
      .filter((task) => Boolean(task.completedAt))
      .sort((left, right) => (right.completedAt ?? '').localeCompare(left.completedAt ?? ''))
      .map((task) => buildTaskBoardItem(task, metricsByTaskId.get(task.id) ?? { focusMinutes: 0, completedPomodoros: 0 }))
 
    return {
      counts: {
        all: tasks.length,
        active: activeItems.length,
        completed: completedItems.length
      },
      activeItems,
      completedItems
    }
  }
}