defmodule Todo.List do defstruct entries: %{}, next_id: 1 def new(entries \\ []) do Enum.reduce(entries, %__MODULE__{}, &add(&2, &1)) end def add( %__MODULE__{entries: entries, next_id: next_id} = todo_list, %{date: _, title: _} = entry ) do new_entry = Map.put(entry, :id, next_id) new_entries = Map.put(entries, next_id, new_entry) %__MODULE__{todo_list | entries: new_entries, next_id: next_id + 1} end def entries(%__MODULE__{} = todo_list, date) do todo_list.entries |> Map.filter(fn {_, entry} -> entry.date == date end) |> Map.values() end def update(%__MODULE__{entries: entries} = todo_list, id, update_fun) when is_function(update_fun, 1) do case Map.fetch(entries, id) do :error -> todo_list {:ok, entry} -> new_entry = update_fun.(entry) new_entries = Map.put(entries, id, new_entry) %__MODULE__{todo_list | entries: new_entries} end end def delete(%__MODULE__{entries: entries} = todo_list, id) when is_number(id) do new_entries = Map.delete(entries, id) %__MODULE__{todo_list | entries: new_entries} end end