Thuta Learning
ProjectsProgrammingbeginner

Practice Project: Task Manager - Part 1

Relax. We'll talk through this in plain words — no textbook voice.

What you'll walk away with

  • Apply Practice Project: Task Manager - Part 1 in a hands-on project
  • Write and run the code yourself
  • Build a complete project step by step

Let's think about it this way

In this project, we'll build a simple Task Manager that runs in the terminal, split across 3 parts. In Part 1, we'll create a data class called Task and define priority levels with an enum class. We use a data class to store each task's id, title, priority, and isDone properties as structured data. We'll use a MutableList to keep the task list in memory and add an add function so new tasks can be inserted. Kotlin's null safety feature comes into play right away when validating the task title.

Let's build it

Instead of a separate Task.kt file, write a Priority enum class (LOW, MEDIUM, HIGH) inside a single main.kt. Then create a Task data class with the fields id: Int, title: String, priority: Priority, isDone: Boolean = false. Inside a TaskManager class, keep a private mutableListOf<Task>() as a property, and write an addTask(title: String, priority: Priority) function — if the title is blank, print an error message with println and return without adding the task. Auto-generate task ids using list.size + 1. Finally, create a TaskManager instance inside main() and try adding about 3 tasks.

Code Example

kotlin
enum class Priority { LOW, MEDIUM, HIGH }

data class Task(
    val id: Int,
    val title: String,
    val priority: Priority,
    var isDone: Boolean = false
)

class TaskManager {
    private val tasks = mutableListOf<Task>()

    fun addTask(title: String, priority: Priority) {
        if (title.isBlank()) {
            println("Task title empty ဖြစ်လို့ add လုပ်လို့မရပါ")
            return
        }
        val newTask = Task(id = tasks.size + 1, title = title, priority = priority)
        tasks.add(newTask)
        println("Task added: ${newTask.title} [${newTask.priority}]")
    }

    fun printAll() {
        tasks.forEach { println("#${it.id} - ${it.title} (${it.priority}) done=${it.isDone}") }
    }
}

fun main() {
    val manager = TaskManager()
    manager.addTask("Kotlin syntax ပြန်ကြည့်ရန်", Priority.HIGH)
    manager.addTask("Data class ကျင့်ရန်", Priority.MEDIUM)
    manager.addTask("", Priority.LOW)
    manager.printAll()
}
You should see
Two tasks are added successfully, while the task with an empty title shows an error message and gets skipped.

5-Minute Challenge

Add a new URGENT value to the Priority enum, then modify the function signature so that when addTask is called without a priority, it automatically defaults to MEDIUM.

A Quick Warning

Using list.size + 1 for auto-increment logic on things like id in data classes can cause duplicate ids if a task is deleted and a new one added afterward — for production apps, use a UUID or a database sequence instead.

Easy traps

  • Declaring a data class property with var instead of val, letting id be changed at runtime — fields that shouldn't change, like id, should be val
  • Confusing isBlank() with isEmpty() — isEmpty() won't catch a title that's just whitespace

Now Try It Yourself

Add a new URGENT value to the Priority enum, then modify the function signature so that when addTask is called without a priority, it automatically defaults to MEDIUM.

You'll know it worked when: Two tasks are added successfully, while the task with an empty title shows an error message and gets skipped.