Content
View differences
Updated by Marc Alcobé 1 day ago
### **Original feedback**
_When recording time, there is no keyword search for "Activity". You can only scroll through the list. This is unmanageable when there are a large number of activities, as is the case with us._
### User Story **Acceptance criteria**
As a mobile app user
I want to select an activity for time logging using search and a recent list
so that I can find the right activity faster with fewer taps
### Acceptance Criteria
* The time logging flow includes an **Activity** selector that triggers a bottom sheet modal
<br>
**Technical notes**
* The Activity bottom sheet shows a **tabs** with two options: **All** <br>
**Permissions and **Recent**
visibility considerations**
* The **All** tab _To whom is selected by default when the bottom sheet opens
* In the **All** tab, the list displays all activities available to the user for the selected work package (or for the time entry context currently being logged)
* In the **Recent** tab, the list displays only the most recently used activities by the user, ordered by most recent first
* The bottom sheet includes a **search input** at the top that can be focused immediately and accepts text input
* When the search query is non-empty, the list shows only matching activities within the currently selected tab (All or Recent)
* When the user types in the search input, the activity list is filtered in real time based on a case-insensitive “contains” match against the activity name
* If there are **no matches**, the list shows an explicit empty state message (use the existing blank slate for results: “**No matching results** - No results match your search term”) and shows no selectable rows
* Clearing the search input restores the unfiltered list for the selected tab
* Selecting an activity in either tab sets the activity on the time entry draft and closes the bottom sheet this feature visible?_
* After an activity _When is selected (and the time entry is saved or confirmed according to current app behavior), that activity becomes the most recent activity for the user and appears at the top of the Recent tab
* The Recent tab does it not contain duplicates. If an activity is selected again, it moves to the top of the Recent list
* The Recent list has a fixed maximum size (assumption: 15 items). When exceeded, the oldest item is removed
* If the user has no recent activities, the Recent tab is hidden
* The Activity list supports scrolling, and the search input and tab control remain visible while scrolling (sticky header behavior)
* If activities cannot be loaded due to connectivity or API errors, the UI shows a failure state, without crashing or blocking the entire time logging flow visible?_
### 3\. Technical Notes **Translation considerations**
* **Assumptions**
* “Activities” correspond to OpenProject time entry activities configured per project (or globally), _Key terms and are selectable when creating/editing a time entry.
* The mobile app already fetches the available activity list for the time logging screen.
* **Data model (local)**
* Store a per-user “recent activities” list locally on-device.
* Data fields to store per recent item:
* Activity identifier (immutable ID)
* Activity name (cached for display)
* Last used timestamp
* Storage approach:
* iOS: UserDefaults or local persistence layer used by the app
* Android: SharedPreferences or local persistence layer used by the app
* **API dependencies / contracts**
* Use existing API calls for fetching available activities (no new server API required for recents if stored locally).
* Search is client-side filtering of the already fetched activity list (avoid new “search activities” endpoint).
* If the activity list is context-dependent (project/work package), the All tab must reflect that same scope.
* **Frontend vs backend responsibilities**
* Frontend:
* Render bottom sheet, tabs, search input, list, empty states
* Apply filtering and ordering
* Persist and update recent activities locally after selection
* Backend:
* No change required unless activities are not currently available phrases in the mobile time logging API
* **Performance and state**
* We could store the activities as cache already to have them available fast
* Handle activity lists up to a reasonable size (assumption: up to a few hundred) with performant list virtualization
* Ensure state is preserved during quick open/close cycles key languages_
**Out of the bottom sheet and device rotation (where applicable)
### Permissions and Visibility Considerations scope**
* Only authenticated users can access time logging and the Activity selector
* The All tab only lists activities the user is permitted <br>
_Set the_ **To be informed/consulted teams** _field to use for time entries in the current context (project/work package)
* If the user lacks permission include all teams necessary to log time, the Activity selector is not accessible (or the time logging UI is disabled) following existing app behavior
* The Recent list must never show activities that are no longer available in the All list for the current context
* If a recent activity is not currently available, it is hidden in Recent
### Translation Considerations
* Localize:
* Tab labels “All” and “Recent”
* Retry and error messages
### 6\. Out be informed of Scope
* Server-side synchronization of recent activities across devices
* Favorites or pinned activities (separate from recents)
* Changes to the underlying set of activities available in OpenProject (configuration remains as-is) changes._
_When recording time, there is no keyword search for "Activity". You can only scroll through the list. This is unmanageable when there are a large number of activities, as is the case with us._
### User Story
As a mobile app user
I want to select an activity for time logging using search and a recent list
so that I can find the right activity faster with fewer taps
### Acceptance Criteria
* The time logging flow includes an **Activity** selector that triggers a bottom sheet modal
**Technical notes**
**Permissions
* In the **All** tab, the list displays all activities available to the user for the selected work package (or for the time entry context currently being logged)
* In the **Recent** tab, the list displays only the most recently used activities by the user, ordered by most recent first
* The bottom sheet includes a **search input** at the top that can be focused immediately and accepts text input
* When the search query is non-empty, the list shows only matching activities within the currently selected tab (All or Recent)
* When the user types in the search input, the activity list is filtered in real time based on a case-insensitive “contains” match against the activity name
* If there are **no matches**, the list shows an explicit empty state message (use the existing blank slate for results: “**No matching results** - No results match your search term”) and shows no selectable rows
* Clearing the search input restores the unfiltered list for the selected tab
* Selecting an activity in either tab sets the activity on the time entry draft and closes the bottom sheet
* After an activity
* The Recent tab does
* The Recent list has a fixed maximum size (assumption: 15 items). When exceeded, the oldest item is removed
* If the user has no recent activities, the Recent tab is hidden
* The Activity list supports scrolling, and the search input and tab control remain visible while scrolling (sticky header behavior)
* If activities cannot be loaded due to connectivity or API errors, the UI shows a failure state, without crashing or blocking the entire time logging flow
### 3\. Technical Notes
* **Assumptions**
* “Activities” correspond to OpenProject time entry activities configured per project (or globally),
* The mobile app already fetches the available activity list for the time logging screen.
* **Data model (local)**
* Store a per-user “recent activities” list locally on-device.
* Data fields to store per recent item:
* Activity identifier (immutable ID)
* Activity name (cached for display)
* Last used timestamp
* Storage approach:
* iOS: UserDefaults or local persistence layer used by the app
* Android: SharedPreferences or local persistence layer used by the app
* **API dependencies / contracts**
* Use existing API calls for fetching available activities (no new server API required for recents if stored locally).
* Search is client-side filtering of the already fetched activity list (avoid new “search activities” endpoint).
* If the activity list is context-dependent (project/work package), the All tab must reflect that same scope.
* **Frontend vs backend responsibilities**
* Frontend:
* Render bottom sheet, tabs, search input, list, empty states
* Apply filtering and ordering
* Persist and update recent activities locally after selection
* Backend:
* No change required unless activities are not currently available
* **Performance and state**
* We could store the activities as cache already to have them available fast
* Handle activity lists up to a reasonable size (assumption: up to a few hundred) with performant list virtualization
* Ensure state is preserved during quick open/close cycles
**Out
### Permissions and Visibility Considerations
* Only authenticated users can access time logging and the Activity selector
* The All tab only lists activities the user is permitted
_Set the_ **To be informed/consulted teams** _field
* If the user lacks permission
* The Recent list must never show activities that are no longer available in the All list for the current context
* If a recent activity is not currently available, it is hidden in Recent
### Translation Considerations
* Localize:
* Tab labels “All” and “Recent”
* Retry and error messages
### 6\. Out
* Server-side synchronization of recent activities across devices
* Favorites or pinned activities (separate from recents)
* Changes to the underlying set of activities available in OpenProject (configuration remains as-is)