<ContentPage eyebrow="Tutorial" title="Track task status" description="Model tasks with structs and format them with a function.">

<TutorialNavigation slug="tutorial-task-model" />

Start with chapter 2's numbered list. A title alone can't tell us whether a task is complete. We'll give each task a title and a boolean status, then move its display logic into a function.

## Describe a task

Add this definition at the top of `tasks.tea`:

```tea
struct Task {
  title: String
  done: Bool
}
```

A `struct` groups named fields into a type. Fields have explicit types: `title` is a `String`, and `done` is a `Bool` (`true` or `false`). Struct definitions use braces; function and loop bodies use `end`.

Replace your string list with the `Task(...)` values in the complete checkpoint below. Named arguments make it clear which field each value supplies. The list's inferred type is now `List[Task]`.

## Give formatting a name

Add this function after the struct:

```tea
def format_task(task: Task, number: Int) -> String
  const marker = if(task.done) "[x]" else "[ ]"
  `${number}. ${marker} ${task.title}`
end
```

`def` introduces a function. Parameters have explicit types, and `-> String` declares the return type. Tea uses the final expression as the return value; you can also write `return` explicitly.

The `if(...) ... else ...` expression chooses one of two strings. Access a field with a dot, such as `task.done` or `task.title`. Both branches produce a `String`, so Tea can infer the type of `marker`.

Replace the loop's output statement with `@println(format_task(task, number))`, and rename its loop binding from `title` to `task`.

## Run the program

```bash
tea tasks.tea
```

```text
1. [ ] Learn Tea
2. [ ] Build a CLI
3. [x] Take a break
```

## Complete checkpoint

**`tasks.tea`**

```tea checkpoint="examples/tutorial/tasks/03-task-model/tasks.tea"
struct Task {
  title: String
  done: Bool
}

def format_task(task: Task, number: Int) -> String
  const marker = if(task.done) "[x]" else "[ ]"
  `${number}. ${marker} ${task.title}`
end

const tasks = [
  Task(title: "Learn Tea", done: false),
  Task(title: "Build a CLI", done: false),
  Task(title: "Take a break", done: true)
]
var number = 1

for task in tasks
  @println(format_task(task, number))
  number = number + 1
end
```

## Try it yourself

Count completed tasks and print the count after the loop. Use a mutable counter and an `if` statement inside the loop.

<details>
<summary>Hint</summary>

Initialize `var completed = 0` before the loop. Inside it, add:

```tea
if task.done
  completed = completed + 1
end
```

After the loop, print `completed`. Unlike the expression that chooses `marker`, this `if` performs an action and ends with `end`.

</details>

The task data and its presentation now have names. Next, we'll let the person running the program decide which tasks to see.

Read more: [structs](/docs/structs), [functions and return values](/docs/functions).

<TutorialNavigation slug="tutorial-task-model" position="bottom" />

</ContentPage>
