84 lines
1.9 KiB
Gleam
84 lines
1.9 KiB
Gleam
|
|
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)]) }))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|