Start|Stop Timer for Item (Task)
- Dominant language
- Dart
- Stars
- 152
- Forks
- 22
- PR merge metrics
- No merged PRs in 30d
Description
# Story
As a `person` wanting to _maximise_ my personal effectiveness,
I want be able to associate (`start|stop`) a timer with a task (_todo list item_)
_So that_ I can keep track of how much time I have spent on a given task.
## Context
> _Most_ people listed "_**tracking time** on a **task**_" as highly desirable feature in #262 ❤️
It has _always_ been one of our _core_ objectives to [track time](https://github.com/dwyl/app/blob/4d8af4ca2b723bdd6df7fe42ad663180854e871c/README.md) against tasks.
One of the _most_ frustrating things about _most_ task/todo apps is that they _don't_ have this feature!
_Not_ being able to track the time spent on a task leads to people being distracted/unfocussed.
It's _incredibly_ frustrating to work in a team where it's impossible to see what other teammates are working on or **how _long_** they has spent on a given task. This is a _systematic_ problem of all "ticketing" systems like JIRA, Trello or Asana. It means _everything_ takes longer than it _needs_ to. Let's _fix_ it.
Given that it's a "_core_" feature, we already have the Schema in place for attaching `timers` to `items`.
It's a **`one-to-many`** relationship which means an `item` can have _multiple_ timers.

This means you can `start|stop` _several_ `timers` for a given `item` and _accumulate_ a _total_ amount of time spent on a task over one or more sessions.
# Todo
+ [x] ***Edit*** the `lib/app_web/templates/item/show.html.eex` template to
+ [x] ***Display*** the `item` _inline_ instead of in a `
- ` similar to the [TodoMVC UI](https://github.com/dwyl/javascript-todo-list-tutorial#toggle-a-todo-item-to-donetrue)
+ [x] ***Create*** the UI `` to **`start`** & **`stop`** a timer for a task.
+ [x] ***Create*** a `` to display the timer for the task.
+ [x] A timer should appear in the `` when **`start`** button is clicked.
+ [x] ***Create*** a new `test` in `test/app_web/controllers/timer_controller_test.exs`
+ [x] That tests for the insertion of a new `timer` record in the `timers` table.
+ [x] The new timer should be linked to an `item_id`
+ [x] The test should _fail_ before the `function` is written (_because this is new functionality_) ...
+ [x] ***Create*** a new `timer` entry for the `item_id` when the **`start`** button is pressed.
> In case you are _wondering_ why the `timers` table has both a `start` and `inserted_at` column, it's so that the **`client`** can define the **`start`** (_the time when the timer was started_),
> but they **cannot** define/change the **`inserted_at`** (_which is controlled by Phoenix/Postgres_)
> This is to mitigate "time travelling" (_people always "starting" timers in the **past**_) ...
> The client can still define a `start` in the past, that's "OK" for people who _forget_ to start a timer.
> But the server will still "_know_" when the `timer` was actually _inserted_ into the DB.
> So someone waiting till the _end_ of the day to retrospectively start/stop a bunch of timers to make it _look_ like they have been _super_ busy and used their time well will be informed otherwise.
> People who don't use the app to improve their personal effectiveness by starting timers before they start working on a task, but rather _invent_ a bunch of timers for a time-sheet will be flagged.
> Don't mistake this for "big brother" _watching_ you, it's "_coach_" making you a _better **teammate**_!
+ [x] ***Write*** the (`Elixir`) `start_timer/1` `function` to be invoked to make the test pass.
+ [x] ***Invoke*** `start_timer/1` when the **`start`** button is clicked/tapped.
+ [x] ***Write*** `JavaScript` code in that _enhances_ the server-rendered page to:
+ [x] ***Render*** a **Clock** in the form `HH:MM:SS` in the `` created above.
+ [x] Only display _relevant_ timer information to keep the UI clean i.e:
+ [x] When only a few seconds have passed show `SS` e.g: `7`, `8`, `9`, etc.
+ [x] When more than 9 seconds have passed show `10`, `11`, `12`, etc.
+ [x] After a _minute_ has passed, show `1:01`, `1:02` etc. where the `0` is now significant.
+ [x] At `9:59` (_nine min and fifty-nine sec_) add the next digit: `10:00`, `10:01`, `10:02`, etc.
+ [x] Once `59:59` has passed add the first _hour_ digit: `1:00:00`
+ [x] Finally if the timer reaches `9:59:59`, add the final digit of significance `10:00:00`
> **Note**: this format for displaying the time is subject to discussion/change.
> We just need _something_ for now so that we can _ship_ this feature!
> For now we do not foresee a timer lasting more than **24 hours**. (_to be tested!_)
> But if [Goggins](https://youtu.be/TLKxdTmk-zc) starts using our app to time his [runs](https://en.wikipedia.org/wiki/Ultramarathon) we'll craft a UI just for him!
+ [x] ***Update*** the clock each second.
+ [x] ***Create*** a test for the `stop_timer/1` function
+ [x] ***Write*** the `stop_timer/1` function to pass the test
+ [x] `stop_timer/1` should ***Update*** the `timer` record with an `end` value
+ [x] ***Invoke*** `stop_timer/1` when the **`stop`** button is clicked in the UI.## Proposed MVP UI/UX
This _proposed_ UI/UX is just to create the MVP functionality.
It _will_ change over time as we _use_ the App and collect _feedback_.

https://www.figma.com/file/WrpkKGJNYZbeCzMRDVtvQLbC/dwyl-app?node-id=0%3A1### _Walkthrough_ of UI/UX Screens:
1. In this UI we can see a `list` with 5 `items` in this case the `list.title` is "Todo List".
+ A **`start`** button is displayed on the _right_ of each `item`
2. When the **`start`** for a given `item` is clicked:
+ **`start`** button for that `item` is hidden
+ a **`stop`** button appears
+ Hide the **`start`** buttons for all other `items` (_to avoid multiple concurrent timers_)
+ the **`timer`** is displayed above the **`stop`** button.
+ the **`timer`** is updated once per second to show the passing of time.
3. When the **`stop`** button for a timer that is _running_ is clicked:
+ Hide the **`stop`** button
+ Stop the **`timer`** from counting. (`clearInterval(timer)`)
+ Show the **`start`** timer
4. If the person clicks/taps the "box" on the left of the `item.text` to signal that the `item` is done:
+ Update the "box" to the "done" arrow version
+ Strikethrough the `item.text` to show that it is complete (_feedback welcome on this UX_)
+ Hide the **`start`** button for this `item` as it's no longer relevant
+ Display the **total** time taken for the `item`Feedback on this issue/spec very much welcome. 🙏
I'm not "precious" about any of it, if you think we can do better UI/UX/functionality, comment!! 💬
I intend to start _building_ it today. Once it's ready for review I will _assign_ the PR. 📦
Contributor guide
Research direction
Review the checked requirements against lib/app_web/templates/item/show.html.eex and test/app_web/controllers/timer_controller_test.exs, then inspect the existing start_timer/1 and stop_timer/1 entry points. Confirm whether the UI, timer persistence, and tests already satisfy the issue; done is determining the remaining gap, if any, rather than starting the feature from this stale specification.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elixir, javascript, postgresql
- Domain
- backend, databases, frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100