Skip to content

Create task screen — core fields #121

Closed

Description

@MessiasLima

Description

Add a "Create Task" screen where users can create a new task with a title (required) and description (optional). This is the foundational task creation flow that subsequent tickets will extend with due date, priority, URL, and location fields.

The current app has no create-task navigation or screen. The Today screen is a placeholder with centered text and does not expose an add action. This ticket introduces the screen composable, ViewModel, navigation route, and a plus button in the Today screen top bar to navigate to it.

Scope

In scope: CreateTaskScreen composable with title (required) and description (optional) fields, form validation (title must not be blank), CreateTaskViewModel with Orbit MVI pattern, CreateTaskNavigation route, plus button in the Today/home top bar that navigates to the create screen, string resources for all UI text, and unit tests for the ViewModel.

Out of scope: due date, priority, URL, and location fields (covered by separate tickets). Edit task flow. Upcoming screen quick-add behavior.

Acceptance criteria

  • GIVEN the user is on the Today screen
    WHEN they tap the plus button in the top bar
    THEN they navigate to the Create Task screen
  • GIVEN the Create Task screen is displayed
    WHEN the user leaves the title blank and taps save
    THEN a validation error is shown and the task is not created
  • GIVEN the Create Task screen is displayed
    WHEN the user enters a title and taps save
    THEN a new task is persisted with creationDate set to now, and the user navigates back
  • GIVEN the Create Task screen is displayed
    WHEN the user enters a title and an optional description
    THEN both fields are saved on the task
  • GIVEN the user is on the Create Task screen
    WHEN they press the system back button or the back arrow
    THEN they navigate back without creating a task
  • GIVEN a task is successfully created
    WHEN the user returns to the Today screen
    THEN the new task appears in the list once the Today task list is implemented

Activity

  1. added this to the next milestone on Jul 15, 2026
  2. MessiasLima commented on Jul 21, 2026

    @MessiasLima
    OwnerAuthor

    /oc

    Issue #121 Plan: Create Task Screen - Core Fields

    Goal

    Implement the foundational create-task flow so a user can open a Create Task screen from Today, enter a required title and optional description, save the task, and return to the previous screen.

    Scope

    In scope:

    • New Create Task screen
    • New Create Task ViewModel using Orbit MVI
    • New navigation route for Create Task
    • Plus button in the Today top bar
    • Validation for required title
    • Persisting a new task with creationDate = now
    • String resources for all UI text
    • ViewModel unit tests

    Out of scope:

    • Due date
    • Priority
    • URL
    • Location
    • Edit task flow
    • Today task list implementation
    • Any change to Today task query behavior

    Current State

    • TodayScreen is currently a placeholder and has no top bar action.
    • TodayViewModel currently has no events or side effects.
    • Navigation is route-based with NavKey plus Navigation<T> implementations.
    • TaskDao already supports writes through save(vararg task: Task).
    • TaskRepository does not yet expose a create/save method.
    • Task already has the fields needed for this ticket.

    Files Likely To Change

    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/data/task/TaskRepository.kt
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/data/task/TaskRepositoryImpl.kt
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/today/TodayViewModel.kt
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/today/TodayScreen.kt
    • foliary/src/commonMain/composeResources/values/strings.xml

    Files To Add

    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/createtask/CreateTaskViewModel.kt
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/createtask/CreateTaskScreen.kt
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/feature/createtask/CreateTaskNavigation.kt
    • foliary/src/commonTest/kotlin/dev/appoutlet/foliary/feature/createtask/CreateTaskViewModelTest.kt

    Implementation Plan

    1. Extend the task repository

    Add a minimal create API to TaskRepository.

    Proposed shape:

    • suspend fun save(task: Task)

    Implementation:

    • Delegate to the existing taskDao.save(task) in TaskRepositoryImpl.

    Reason:

    • This is the smallest change that keeps task creation behind the repository boundary already used by the app.

    2. Create the new feature package

    Add a new feature/createtask/ package following the existing screen pattern.

    Files:

    • CreateTaskViewModel.kt
    • CreateTaskScreen.kt
    • CreateTaskNavigation.kt

    This matches the structure already used by signin, profile, and the project’s create-screen guidance.

    3. Add navigation for Create Task

    Create:

    • @Serializable data object CreateTaskNavKey : NavKey
    • @Single class CreateTaskNavigation : Navigation<CreateTaskNavKey>

    Behavior:

    • Register CreateTaskScreen() in setupRoute
    • Register CreateTaskNavKey in setupPolymorphism

    Reason:

    • Navigation entries are already auto-aggregated via Koin and NavigationAggregator, so this should integrate without central manual route wiring.

    4. Update Today to expose the create flow

    Update TodayViewModel to handle a plus-button event.

    Suggested contracts:

    • TodayEvent.OnAddTaskClick
    • TodayAction.NavigateToCreateTask

    Behavior:

    • When the plus button is tapped, emit NavigateToCreateTask

    Update TodayScreen:

    • Add a Material 3 top app bar
    • Add a plus icon button in the top bar
    • Dispatch TodayEvent.OnAddTaskClick
    • Handle TodayAction.NavigateToCreateTask by navigating to CreateTaskNavKey

    Reason:

    • Keeps Today aligned with Orbit MVI instead of navigating directly from the composable.

    5. Implement CreateTaskViewModel

    Keep form state in the ViewModel so validation and save behavior are fully testable.

    Suggested state:

    • title: String
    • description: String
    • showTitleError: Boolean
    • isSaving: Boolean

    Suggested events:

    • OnTitleChanged(String)
    • OnDescriptionChanged(String)
    • OnSaveClick
    • OnBackClick

    Suggested side effects:

    • NavigateBack

    Dependencies:

    • TaskRepository
    • TimeProvider

    Behavior:

    • OnTitleChanged updates title and clears the error once the title is no longer blank
    • OnDescriptionChanged updates description
    • OnBackClick emits NavigateBack
    • OnSaveClick:
      • validate title.isBlank()
      • if blank, set showTitleError = true and stop
      • if valid, create a Task
      • save through repository
      • emit NavigateBack

    Task construction:

    • id = Uuid.random()
    • title = title.trim()
    • description = description.trim().ifBlank { null }
    • creationDate = timeProvider.now()
    • dueDate = null
    • completionDate = null
    • priority = null
    • url = null
    • location = null

    Reason:

    • This exactly matches the ticket scope and avoids prematurely modeling future fields.

    6. Implement CreateTaskScreen

    Build the screen using the project’s existing Screen(...) wrapper and a Scaffold.

    UI elements:

    • Top app bar with back arrow
    • Screen title
    • Required title input
    • Optional description input
    • Save button

    Behavior:

    • Back arrow triggers OnBackClick
    • System/back navigation is satisfied by normal navigator back-stack behavior
    • Save button triggers OnSaveClick
    • Title field shows validation error when showTitleError is true

    Layout:

    • Use a scrollable column
    • Constrain width similarly to other form screens like SignInScreen
    • Keep desktop and mobile layout simple and consistent

    Notes:

    • There is no existing shared app bar pattern in the app, so this ticket will establish the first simple back/app-bar pattern.
    • There is no shared text field wrapper, so use Material 3 text fields directly and match existing style where possible.

    7. Add string resources

    Add all UI strings to strings.xml.

    Expected additions:

    • Create Task screen title
    • Title label or placeholder
    • Description label or placeholder
    • Save action text
    • Title required validation text
    • Add task action content description
    • Back action content description if needed
    • Any Today top bar action label if surfaced

    Rule:

    • No hardcoded user-facing strings in UI code.

    Testing Plan

    1. CreateTaskViewModel tests

    Add CreateTaskViewModelTest covering:

    • initial state is empty and not saving
    • blank title on save shows validation error
    • blank title on save does not call repository
    • entering a valid title clears the title error
    • valid title saves a task
    • valid title plus description saves both values
    • blank description is saved as null
    • successful save emits NavigateBack
    • back event emits NavigateBack without saving

    Recommended assertions:

    • verify repository interaction
    • verify saved Task fields
    • verify side effects through Orbit test helpers

    2. Optional TodayViewModel test

    Add a small TodayViewModelTest if needed to cover:

    • OnAddTaskClick emits NavigateToCreateTask

    This is optional but low cost.

    3. Repository test update

    Extend TaskRepositoryImplTest with one save-delegation test if repository behavior is modified.

    Verification

    Run only targeted JVM tests:

    • ./gradlew foliary:jvmTest --tests "dev.appoutlet.foliary.feature.createtask.CreateTaskViewModelTest"
    • ./gradlew foliary:jvmTest --tests "dev.appoutlet.foliary.data.task.TaskRepositoryImplTest"

    If a TodayViewModelTest is added:

    • ./gradlew foliary:jvmTest --tests "dev.appoutlet.foliary.feature.today.TodayViewModelTest"

    Risks

    • There is no existing top app bar pattern in the app, so this ticket introduces one. Keep it minimal and local to avoid over-design.
    • The Today screen still does not render tasks. This ticket should not try to solve that.
    • Newly created tasks will have dueDate = null, and current Today query behavior only returns due/overdue tasks. That is acceptable because showing the created task in Today is explicitly outside this ticket’s scope.

    Definition Of Done

    • User can tap a plus button from Today and reach Create Task
    • Create Task screen shows title and description inputs
    • Saving with a blank title shows a validation error and does not save
    • Saving with a valid title persists a task with creationDate = now
    • Optional description is persisted when provided
    • Successful save navigates back
    • Back arrow navigates back without saving
    • All new UI strings are in strings.xml
    • ViewModel unit tests pass
  3. opencode-agent commented on Jul 21, 2026

    @opencode-agent
    Contributor

    Created PR #194

    New%20session%20-%202026-07-21T14%3A48%3A48.525Z
    opencode session  |  github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions