feature: converts timers from local to API based#65
Draft
marlonmarcello wants to merge 1 commit into
Draft
Conversation
🦋 Changeset detectedLatest commit: df2e895 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refactors Teamwork timer functionality from a local-cache (“local timers”) implementation to Teamwork’s native (server-side) timer API, updating both the TUI and CLI flows accordingly.
Changes:
- Replaced local timer persistence + submission workflows with Teamwork native timer list/start/stop/delete operations.
- Updated TUI task tabs and the dedicated timers tab to display and control server-side timers.
- Updated CLI
teamwork timersubcommands to align with the new API-backed timer model and removed local-only commands.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tui/pages/teamwork/timers-tab.tsx | Switches timers tab to API-backed timers and updates keybindings/actions. |
| src/tui/pages/teamwork/project-tab.tsx | Updates task tab timer props/refresh to use API-backed timers. |
| src/tui/pages/teamwork/my-work-tab.tsx | Updates task tab timer props/refresh to use API-backed timers. |
| src/tui/hooks/use-task-timer.tsx | Refactors shared timer hook to call Teamwork timer API (start/stop/list). |
| src/tui/hooks/use-branch-workflow.tsx | Starts API-backed timer when creating branches (was local). |
| src/tui/components/teamwork/task-list.tsx | Uses API timer types + elapsed calculation for task timer badges. |
| src/cli/commands/timers.ts | Refactors CLI timer operations to use API-backed timers and updates formatting/output. |
| src/cli/commands/teamwork-command.ts | Updates CLI subcommands for timers (notably delete replacing prior commands). |
| src/cli/commands/task-workflow.ts | Starts API-backed timer from CLI workflow (was local). |
| src/api/teamwork/timers/local.ts | Deletes the local timer storage/submission implementation. |
| src/api/teamwork/timers/api.ts | Adds Teamwork native timer API client + elapsed/duration formatting helpers. |
| src/api/teamwork/timers.ts | Removes the prior Teamwork timers/time-entry submission API module. |
| src/api/cache/consts.ts | Removes cache key/descriptor for the local timers file. |
| plans/PLAN.md | Updates roadmap note to reflect the new API-backed timer approach. |
| .changeset/smooth-doors-rest.md | Adds a changeset for the timers refactor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /** Stops a running timer by ID. */ | ||
| export async function stopTimer(timerId: number): Promise<TeamworkTimer> { | ||
| try { | ||
| const data = (await fetchTeamworkApiJson(`/timers/${timerId}.json`, { |
Comment on lines
+119
to
+123
| export function getTimerElapsedMs(timer: TeamworkTimer, now: Date): number { | ||
| if (!timer.lastStartedAt) return 0; | ||
| const start = new Date(timer.lastStartedAt).getTime(); | ||
| return Math.max(0, now.getTime() - start); | ||
| } |
Comment on lines
+61
to
+66
| const body: Record<string, unknown> = { | ||
| timer: { taskId }, | ||
| }; | ||
| if (description) { | ||
| (body.timer as Record<string, unknown>).description = description; | ||
| } |
| ): number | null { | ||
| if (!timers.length) return null; | ||
|
|
||
| const currentIndex = currentId ? timers.findIndex((timer) => timer.id === currentId) : -1; |
| {(timer) => ( | ||
| <ListItem | ||
| title={timer.taskName} | ||
| title={timer.taskName ?? `Task #${timer.taskId}`} |
Comment on lines
65
to
69
| const stopSelectedTimer = async () => { | ||
| const timer = selectedTimer(); | ||
| if (!timer) { | ||
| setMessage("No local timer selected."); | ||
| setMessage("No timer selected."); | ||
| return; |
Comment on lines
+82
to
87
| const deleteSelectedTimer = () => { | ||
| const timer = selectedTimer(); | ||
| if (!timer) { | ||
| setMessage("No local timer selected."); | ||
| setMessage("No timer selected."); | ||
| return; | ||
| } |
Comment on lines
49
to
51
| const refreshTimers = async () => { | ||
| setLocalTimers(await loadLocalTimers()); | ||
| setTwTimers(await getMyTimers()); | ||
| }; |
Comment on lines
+22
to
24
| const refreshTimers = async () => { | ||
| setTimers(await getMyTimers()); | ||
| }; |
Comment on lines
+43
to
+46
| const qs = searchParams.toString(); | ||
| const path = qs ? `/me/timers.json?${qs}` : "/me/timers.json"; | ||
| const data = (await fetchTeamworkApiJson(path)) as { timers: TeamworkTimer[] }; | ||
| return data.timers ?? []; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refactors teamwork timers from local to API based.
Type of Change
Local Verification
bun run fmtbun run lintbun run checkbun run buildRelease Impact
.changeset/