# Functional specification for Timer route
This document outlines the functional specifications for the Timer route in the front-end application. The Timer route is responsible for managing and displaying timer functionalities to the user.
## Timer Route Overview
The timer route allows users to create and delete timers. Each timer has an end timestamp. The page displays a list of the active timers, showing the remaining time until each timer reaches its end timestamp. The timers should be updated every 10 seconds to reflect the remaining time accurately without overloading the system with too frequent updates. When a timer reaches its end timestamp, it should emit an event indicating that the timer has completed. The "remaining time" for expired timers should be shown with a minus prefix (e.g., '-2d 3h 15m'), indicating how much time has passed since the timer ended.
The user has the option to end a timer manually using a checkbox at the start of the timer entry. When the checkbox is selected, the timer should immediately emit an event indicating that it has been ended by the user. The timer display should then be moved to a separate section for ended timers which should be collapsed by default.
The timer route assumes that UIBUILDER for Node-RED is being used, and the implementation should adhere to the conventions and best practices of UIBUILDER.
## Timer Route Functional Requirements
There must be a button to create a new timer. Clicking this button opens a dialog where the user can input the timer details, including the description/name and end timestamp.
### The Timer route should display a list of timers, each showing the following information:
- A checkbox: Marks timer as manually ended but keeps it in the list (moved to ended section).
- The timer description or name.
- The remaining time until the timer ends (or time elapsed since it ended as a negative value), updated every 10 seconds. The 10-second update interval balances UI responsiveness with performance. This can be adjusted based on performance requirements
- The end timestamp of the timer. In the format "YYYY-MM-DD HH:MM DDD".
- Clear visual distinction between active and ended timers. Suitable for both dark and light modes.
- Use background color changes, and text styles to differentiate between active and ended timers.
- Active timers should have a normal appearance with a background colour that has a slight contrast to the page background.
- Timers within 2 minutes of ending should be highlighted (e.g., with a warning background).
- Overdue timers should be highlighgted (e.g., with a error background).
- A set of action buttons:
- Delete: Permanently removes the timer from all lists.
- Copy: Copies the timer to a new timer entry in an open dialog for further editing.
- Clicking anywhere on the timer entry (except for the checkbox and action buttons) opens a dialog to edit the timer details. Also allowing both keyboard and touch interactions.
A separate list inside a collapsible section should display the ended timers, with the same information and action buttons as active timers.
A vertical LED style chart indicator should be displayed next to the add button, this should have 10 segments. The display should count down the time untile the next 10-second update, with each segment representing 1 second. The segments should light up in sequence from bottom to top as time progresses, and reset when the timer updates. Since the 10-second update can be configurable, the segment duration should be dynamically calculated based on the update interval.
### The dialog for creating and editing timers should include:
- Input fields for:
- Timer description/name. This input should be a single-line text input with a maximum length of 100 characters. It must not be empty.
- End timestamp. The input for the end timestamp should use HTML date and time inputs (on the same line if possible), the input should be preceded by a button that sets the inputs to NOW. Excepting any other overrides (e.g. editing an existing entry), the inputs should default to NOW.
- Noting that timestamps in the past are allowed.
- A Section containing Add/Subtract radio buttons and input fields for years, months, weeks, days, hours, minutes, and seconds to easily adjust the end timestamp relative to the current value.
- A Section showing the final calculated end timestamp based on the inputs above. and the remaining time until (or since) that timestamp.
- 2 action buttons:
- Save: Saves the timer details and closes the dialog.
- Cancel: Closes the dialog without saving changes.
- Upon opening, the description/name input field should be automatically focused for user convenience.
- The escape key should close the dialog without saving changes.
- The enter key should save the timer details if the dialog is open and the focus is not on a button.
- Clicking outside the dialog should close the dialog without saving changes.
- Trap focus within the dialog when it is open to enhance accessibility.
## Data Handling
Upon route initialization, the Timer route should request the current list of timers from node-red via UIBUILDER's messaging system. The timers should be stored in the front-end application state to allow for efficient rendering and updating.
When a timer is created, edited, deleted, or ended manually, the Timer route should send the appropriate message to node-red to update the backend data store accordingly. If uibuilder's comms channel is disconnected, the Timer route should queue each event and send them once the connection is re-established.
If a timer reaches its end timestamp, the Timer route should emit an event to node-red indicating that the timer has completed. If uibuilder's comms channel is disconnected, the Timer route should queue the event and send it once the connection is re-established.
Queued events should be stored in local storage to ensure they are not lost if the user refreshes the page or closes the browser. When comms becomes re-established, the Timer route should retrieve any queued events from local storage and send them to node-red in the order they were created (do not de-duplicate events). Once sent, the queued events should be removed from local storage.
Any localStorage data should be namespaced with `uib-timer-route-` to avoid conflicts with other data.
If server data conflicts with queued local changes, local changes take precedence until successfully synced.
## Timer Data Structure
Each timer should be represented by an object with the following properties:
- `id`: A unique identifier for the timer.
- `description`: A string representing the timer's description or name.
- `endTimestamp`: A timestamp indicating when the timer is set to end.
- `status`: A string indicating the timer's status, "active", "ended" or "expired".
- `endedBy`: A string indicating how the timer was ended, either "user" or "automatic" (if ended by reaching the end timestamp). Null if the timer is still active.
## UIBUILDER messages
The Timer route should handle the following UIBUILDER messages:
* `{ topic: 'timer:request' }` - Initial list request
* `{ topic: 'timer:create', payload: {...} }` - Create timer
* `{ topic: 'timer:update', payload: {...} }` - Edit timer
* `{ topic: 'timer:delete', id: string }` - Delete timer
* `{ topic: 'timer:ended', id: string, endedBy: 'user'|'auto' }` - Timer completed
## General Requirements
- The timer route should be contained in a single html fragment file in the same folder as this specification. The fragment file should be named `timers.html`. It should include all necessary HTML, CSS, and JavaScript to implement the specified functionality.
- The Timer route should be responsive and work well on various screen sizes, including mobile devices.
- The design should be consistent with the overall application theme, supporting both dark and light modes.
- Accessibility considerations should be taken into account, ensuring that all functionalities are usable via keyboard navigation and screen readers.
- Proper error handling should be implemented for invalid inputs in the timer creation/editing dialog.
- The application should maintain performance and not degrade with multiple active timers. 100 active timers should be handled smoothly.
- All timer-related events (creation, deletion, completion, manual ending) should be logged for auditing purposes.
- The Timer route should be tested thoroughly to ensure all functionalities work as expected.
- The implementation should follow best practices for code quality, maintainability, and scalability.
- The Timer route should be compatible with the latest versions of major web browsers.
- The latest standards for HTML, CSS, and JavaScript should be used in the implementation.
- CSS should prioritize:
- Use of CSS variables for theming (dark/light mode).
- Flexbox or CSS Grid for layout.
- Avoidance of deprecated or non-standard CSS properties.
- Nested styles for better organization.
- Comments to explain complex styling decisions.
- JavaScript should prioritize:
- Use of ES6+ features for cleaner and more efficient code.
- Use ES Modules as appropriate.
- Modular code structure, separating concerns appropriately.
- Clear and descriptive naming conventions for variables and functions.
- Comments to explain complex logic or decisions.
- Avoidance of global variables to prevent conflicts.
- JSDoc comments for as needed.
- HTML should prioritize:
- Semantic HTML5 elements for better accessibility and SEO.
- Proper use of ARIA attributes where necessary.
- Clear and descriptive IDs and classes for styling and scripting.
- Comments to explain the structure and purpose of different sections.
- The implementation should include unit tests and integration tests to verify the functionality of the Timer route.
- Documentation should be provided for the Timer route, including usage instructions and any relevant technical details.
## Testing requirements
- Timer expiring while page is inactive
- Multiple timers expiring simultaneously
- Editing a timer while it's expiring
- Connection loss/recovery during timer operations
Think about everything you want. Be explicit, you need to think like you are explaining what you want to a person with very limited understanding.
No, I had a quick play with the FlowFuse AI thing but really, most flows are so simple, it would probably take you longer to explain it than to just do it.