Files
XCDesktop/api/modules/time-tracking/routes.ts
2026-03-08 01:34:54 +08:00

132 lines
4.1 KiB
TypeScript

import express, { type Request, type Response, type Router } from 'express'
import { asyncHandler } from '../../utils/asyncHandler.js'
import { successResponse } from '../../utils/response.js'
import { TimeTrackerService } from './timeService.js'
import type { TimeTrackingEvent } from '../../../shared/types.js'
export interface TimeTrackingRoutesDependencies {
timeTrackerService: TimeTrackerService
}
export const createTimeTrackingRoutes = (deps: TimeTrackingRoutesDependencies): Router => {
const router = express.Router()
const { timeTrackerService } = deps
router.get(
'/current',
asyncHandler(async (_req: Request, res: Response) => {
const state = timeTrackerService.getCurrentState()
successResponse(res, {
isRunning: state.isRunning,
isPaused: state.isPaused,
currentSession: state.currentSession ? {
id: state.currentSession.id,
startTime: state.currentSession.startTime,
duration: state.currentSession.duration,
currentTab: state.currentTabRecord ? {
tabId: state.currentTabRecord.tabId,
fileName: state.currentTabRecord.fileName,
tabType: state.currentTabRecord.tabType
} : null
} : null,
todayDuration: state.todayDuration
})
})
)
router.post(
'/event',
asyncHandler(async (req: Request, res: Response) => {
const event = req.body as TimeTrackingEvent
await timeTrackerService.handleEvent(event)
successResponse(res, null)
})
)
router.get(
'/day/:date',
asyncHandler(async (req: Request, res: Response) => {
const { date } = req.params
const [year, month, day] = date.split('-').map(Number)
const data = await timeTrackerService.getDayData(year, month, day)
const sessionsCount = data.sessions.length
const averageSessionDuration = sessionsCount > 0
? Math.floor(data.totalDuration / sessionsCount)
: 0
const longestSession = data.sessions.reduce((max, s) =>
s.duration > max ? s.duration : max, 0)
const topTabs = Object.entries(data.tabSummary)
.map(([_, summary]) => ({
fileName: summary.fileName,
duration: summary.totalDuration
}))
.sort((a, b) => b.duration - a.duration)
.slice(0, 5)
successResponse(res, {
...data,
stats: {
sessionsCount,
averageSessionDuration,
longestSession,
topTabs
}
})
})
)
router.get(
'/week/:startDate',
asyncHandler(async (req: Request, res: Response) => {
const { startDate } = req.params
const [year, month, day] = startDate.split('-').map(Number)
const start = new Date(year, month - 1, day)
const data = await timeTrackerService.getWeekData(start)
const totalDuration = data.reduce((sum, d) => sum + d.totalDuration, 0)
const activeDays = data.filter(d => d.totalDuration > 0).length
successResponse(res, {
days: data,
totalDuration,
activeDays,
averageDaily: activeDays > 0 ? Math.floor(totalDuration / activeDays) : 0
})
})
)
router.get(
'/month/:yearMonth',
asyncHandler(async (req: Request, res: Response) => {
const { yearMonth } = req.params
const [year, month] = yearMonth.split('-').map(Number)
const data = await timeTrackerService.getMonthData(year, month)
successResponse(res, data)
})
)
router.get(
'/year/:year',
asyncHandler(async (req: Request, res: Response) => {
const { year } = req.params
const data = await timeTrackerService.getYearData(parseInt(year))
successResponse(res, data)
})
)
router.get(
'/stats',
asyncHandler(async (req: Request, res: Response) => {
const year = req.query.year ? parseInt(req.query.year as string) : undefined
const month = req.query.month ? parseInt(req.query.month as string) : undefined
const stats = await timeTrackerService.getStats(year, month)
successResponse(res, stats)
})
)
return router
}