import gleam/json import gleam/list import gleam/result import lustre import lustre/attribute import lustre/effect.{type Effect} import lustre/element.{type Element} import lustre/element/html import plinth/browser/document import plinth/browser/element as plinth_element import shared pub fn main() { let initial_items = document.query_selector("#model") |> result.map(plinth_element.inner_text) |> result.try(fn(json) { json.parse(json, shared.grocery_list_decoder()) |> result.replace_error(Nil) }) |> result.unwrap([]) let app = lustre.application(init, update, view) let assert Ok(_) = lustre.start(app, "#app", initial_items) Nil } type Model { Model(rooms: List(String), name: String) } fn init(items: List(String)) -> #(Model, Effect(Msg)) { let model = Model(rooms: items, name: "") #(model, effect.none()) } type Msg { UserTypedNewItem(String) UserAddedItem } fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) { case msg { UserAddedItem -> { case model.name { "" -> #(model, effect.none()) name -> { let updated_items = [name, ..model.rooms] #(Model(rooms: updated_items, name: ""), effect.none()) } } } UserTypedNewItem(text) -> #(Model(..model, name: text), effect.none()) } } fn view(model: Model) -> Element(Msg) { let styles = [ #("max-width", "30ch"), #("margin", "0 auto"), #("display", "flex"), #("flex-direction", "column"), #("gap", "1em"), ] html.div([attribute.styles(styles)], [ html.h1([], [html.text("Select your QuizRoom")]), view_room_list(model.rooms), ]) } fn view_room_list(items: List(String)) -> Element(Msg) { case items { [] -> html.p([], [html.text("No items in your list yet.")]) _ -> { html.ul([], list.map(items, fn(item) { html.li([], [html.text(item)]) })) } } }