mirror of
https://github.com/hex248/sprint.git
synced 2026-02-08 18:33:01 +00:00
improved timer system and overlay
This commit is contained in:
@@ -2,6 +2,7 @@ import authLogin from "./auth/login";
|
||||
import authLogout from "./auth/logout";
|
||||
import authMe from "./auth/me";
|
||||
import authRegister from "./auth/register";
|
||||
import issueById from "./issue/by-id";
|
||||
import issueCreate from "./issue/create";
|
||||
import issueDelete from "./issue/delete";
|
||||
import issueUpdate from "./issue/update";
|
||||
@@ -56,6 +57,7 @@ export const routes = {
|
||||
userUploadAvatar,
|
||||
|
||||
issueCreate,
|
||||
issueById,
|
||||
issueDelete,
|
||||
issueUpdate,
|
||||
|
||||
|
||||
29
packages/backend/src/routes/issue/by-id.ts
Normal file
29
packages/backend/src/routes/issue/by-id.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { IssueByIdQuerySchema } from "@sprint/shared";
|
||||
import type { AuthedRequest } from "../../auth/middleware";
|
||||
import { getIssueOrganisationId, getIssueWithUsersById, getOrganisationMemberRole } from "../../db/queries";
|
||||
import { errorResponse, parseQueryParams } from "../../validation";
|
||||
|
||||
export default async function issueById(req: AuthedRequest) {
|
||||
const url = new URL(req.url);
|
||||
const parsed = parseQueryParams(url, IssueByIdQuerySchema);
|
||||
if ("error" in parsed) return parsed.error;
|
||||
|
||||
const { issueId } = parsed.data;
|
||||
|
||||
const organisationId = await getIssueOrganisationId(issueId);
|
||||
if (!organisationId) {
|
||||
return errorResponse(`organisation not found for issue ${issueId}`, "ORG_NOT_FOUND", 404);
|
||||
}
|
||||
|
||||
const member = await getOrganisationMemberRole(organisationId, req.userId);
|
||||
if (!member) {
|
||||
return errorResponse("forbidden", "FORBIDDEN", 403);
|
||||
}
|
||||
|
||||
const issue = await getIssueWithUsersById(issueId);
|
||||
if (!issue) {
|
||||
return errorResponse(`issue not found: ${issueId}`, "ISSUE_NOT_FOUND", 404);
|
||||
}
|
||||
|
||||
return Response.json(issue);
|
||||
}
|
||||
@@ -1,15 +1,34 @@
|
||||
import { calculateBreakTimeMs, calculateWorkTimeMs, isTimerRunning } from "@sprint/shared";
|
||||
import type { AuthedRequest } from "../auth/middleware";
|
||||
import { getUserTimedSessions } from "../db/queries";
|
||||
import { getActiveTimedSessionsWithIssue, getUserTimedSessions } from "../db/queries";
|
||||
|
||||
// GET /timers?limit=50&offset=0
|
||||
export default async function timers(req: AuthedRequest) {
|
||||
const url = new URL(req.url);
|
||||
const limitParam = url.searchParams.get("limit");
|
||||
const offsetParam = url.searchParams.get("offset");
|
||||
const activeOnlyParam = url.searchParams.get("activeOnly");
|
||||
|
||||
const limit = limitParam ? Number(limitParam) : 50;
|
||||
const offset = offsetParam ? Number(offsetParam) : 0;
|
||||
const activeOnly = activeOnlyParam === "true" || activeOnlyParam === "1";
|
||||
|
||||
if (activeOnly) {
|
||||
const sessions = await getActiveTimedSessionsWithIssue(req.userId);
|
||||
const enriched = sessions.map((session) => ({
|
||||
id: session.id,
|
||||
issueId: session.issueId,
|
||||
issueNumber: session.issueNumber,
|
||||
projectKey: session.projectKey,
|
||||
timestamps: session.timestamps,
|
||||
endedAt: session.endedAt,
|
||||
workTimeMs: calculateWorkTimeMs(session.timestamps),
|
||||
breakTimeMs: calculateBreakTimeMs(session.timestamps),
|
||||
isRunning: isTimerRunning(session.timestamps),
|
||||
}));
|
||||
|
||||
return Response.json(enriched);
|
||||
}
|
||||
|
||||
const sessions = await getUserTimedSessions(req.userId, limit, offset);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user