Fix the todo toggle that rebuilds the list

Review the AI's codeEasy10 min

Your task

A todo checkbox never re-rendered: the handler flipped done on the existing item and passed the same array back to setTodos, so React saw no change. The replacement builds a new list, with a new value for the row that changed.

An assistant wrote toggle_todo_done(todo_lines, target_id). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • todo_lines: the todos in order, one string each: "<id>:<state>", such as "t1:open".
  • target_id: the id of the todo the user clicked.
  • Return a new list of rows, in the same order and the same length.

Rules the tests check:

  • Split a row at its first :. A row is well formed when it has a colon, a non-empty id before it, and a state after it that is exactly "done" or "open".
  • Ids are not unique. Only the first well formed row whose id equals target_id flips: "done" becomes "open" and "open" becomes "done". Later rows with the same id stay as they are.
  • Every other row is copied unchanged, malformed rows included.
  • The id match is exact and case sensitive. An empty target_id flips nothing, because a row with an empty id is malformed.
  • When no row matches, return the rows unchanged. No rows returns an empty list.

Examples

toggle_todo_done(todo_lines: list[str], target_id: str) -> list[str]
Example 1
Inputtoggle_todo_done(["t1:open", "t2:done"], "t1")
Output["t1:done", "t2:done"]
Example 2
Inputtoggle_todo_done(["t1:open", "t2:done"], "t2")
Output["t1:open", "t2:open"]
Example 3
Inputtoggle_todo_done(["t1:open"], "zz")
Output["t1:open"]