More massive workstuff for completion :P

This commit is contained in:
Lett Osprey 2026-04-10 19:36:28 +02:00
parent 7a8acf27a7
commit 3385118b14
20 changed files with 325 additions and 354 deletions

View file

@ -1,27 +1,30 @@
import gleam/dynamic/decode
import gleam/json
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/result
import gleam/string
import lustre
import lustre/effect.{type Effect}
import model.{
type Model, type Msg, AwaitPlayers, Empty, EnterPin, Initialize, KeyPin, Model,
PickPlayer, Players, SelectedGamestyle, SelectedPlayer, SelectedRoom,
type Model, type Msg, type Room, Empty, EnterPin, Initialize, KeyPin, Model,
Room, SelectedGamestyle, SelectedRoom,
}
import plinth/browser/document
import plinth/browser/element as plinth_element
import rsvp
import shared.{type Room}
import view.{view}
pub fn main() {
let room_decoder = {
use name <- decode.field("name", decode.string)
use id <- decode.field("id", decode.string)
use pin <- decode.field("key", decode.string)
decode.success(Room(id:, name:, pin:))
}
let initial_items =
document.query_selector("#model")
|> result.map(plinth_element.inner_text)
|> result.try(fn(json) {
json.parse(json, shared.grocery_list_decoder())
json.parse(json, decode.list(room_decoder))
|> result.replace_error(Nil)
})
|> result.unwrap([])
@ -47,14 +50,6 @@ fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
effect.none(),
)
KeyPin(pin) -> {
//let _decode_answer = {
// use id <- decode.field("id", decode.string)
// use text <- decode.field("text", decode.string)
// decode.success(id)
// }
// let decode_list = {
// decode.list(decode.string)
// }
case model.state {
EnterPin(room, _) -> #(
Model(..model, state: case string.length(pin) < 4 {
@ -72,97 +67,21 @@ fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
}
SelectedGamestyle(style) -> {
case model.state {
model.SelectGamestyle(room:, pin:) -> #(
Model(..model, state: case style {
"Single Game" ->
PickPlayer(room:, pin:, players: [
"Player a",
"Player b",
"Player c",
"Player d",
"Player e",
"Player f",
])
_ -> model.JoinLive(room:, pin:)
}),
effect.none(),
)
model.SelectGamestyle(room:, pin:) -> {
#(
Model(..model, state: case style {
"Single Game" -> model.JoinSingle(room:, pin:)
_ -> model.JoinLive(room:, pin:)
}),
effect.none(),
)
}
_ ->
init(#(
model.rooms,
Some("(fail: selectgamestyle) Invalid state, starting over"),
))
}
// Model(..model, state: AwaitPlayers(room:, pin:)),
// rsvp.post(
// "http://localhost:1234/api/room/players",
// json.object([#("id", json.string("1234"))]),
// rsvp.expect_json(decode_answer, Players),
// ),
// )
}
Players(Ok(players)) -> {
echo "got players"
case model.state {
AwaitPlayers(room:, pin:) -> #(
Model(..model, state: PickPlayer(room:, pin:, players: [players])),
effect.none(),
)
_ ->
init(#(
model.rooms,
Some("(fail: awaitplayers) Invalid state, starting over"),
))
}
}
Players(Error(x)) ->
init(#(
model.rooms,
Some("Error fetching players " <> decode_rsvp_error(x)),
))
SelectedPlayer(player) ->
case model.state {
PickPlayer(room:, pin:, players: _) -> #(
Model(..model, state: model.JoinSingle(room:, pin:, player:)),
effect.none(),
)
_ ->
init(#(
model.rooms,
Some("(fail: pickplayer) Invalid state, starting over"),
))
}
}
}
fn decode_rsvp_error(rsvp_error: rsvp.Error) {
case rsvp_error {
rsvp.BadBody -> "Bad body"
rsvp.BadUrl(_x) -> "Bad url"
rsvp.HttpError(_x) -> "Http error"
rsvp.JsonError(x) -> "Json error" <> decode_decode_error(x)
rsvp.NetworkError -> "Network error"
rsvp.UnhandledResponse(_) -> "Unhandled response"
}
}
fn decode_decode_error(json_error: json.DecodeError) -> String {
case json_error {
json.UnableToDecode(x) ->
"[unable to decode"
<> string.concat(
list.map(x, fn(x) { "(" <> decode_ddecode_error(x) <> ")" }),
)
<> "]"
json.UnexpectedSequence(s) -> "[unexpected sequence " <> s <> "]"
json.UnexpectedByte(x) -> "[unexpected byte " <> x <> "]"
json.UnexpectedEndOfInput -> "[unexpected end of input]"
}
}
fn decode_ddecode_error(decode_error: decode.DecodeError) -> String {
case decode_error {
decode.DecodeError(expected:, found:, path:) ->
"(e: " <> expected <> ", f: " <> found <> ", p: " <> string.concat(path)
}
}