diff --git a/client/src/client.gleam b/client/src/client.gleam index 17d8591..1f2ecdb 100644 --- a/client/src/client.gleam +++ b/client/src/client.gleam @@ -1,11 +1,13 @@ +import gleam/int import gleam/json import gleam/list import gleam/result import lustre -import lustre/attribute +import lustre/attribute.{class} import lustre/effect.{type Effect} import lustre/element.{type Element} import lustre/element/html +import lustre/event import plinth/browser/document import plinth/browser/element as plinth_element import shared @@ -27,10 +29,10 @@ pub fn main() { } type Model { - Model(rooms: List(String), name: String) + Model(rooms: List(shared.Room), name: String) } -fn init(items: List(String)) -> #(Model, Effect(Msg)) { +fn init(items: List(shared.Room)) -> #(Model, Effect(Msg)) { let model = Model(rooms: items, name: "") #(model, effect.none()) @@ -43,41 +45,85 @@ type Msg { fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) { case msg { - UserAddedItem -> { + UserAddedItem -> case model.name { - "" -> #(model, effect.none()) - name -> { - let updated_items = [name, ..model.rooms] - - #(Model(rooms: updated_items, name: ""), effect.none()) - } + _ -> #(model, effect.none()) } + UserTypedNewItem(text) -> { + echo "CLICK " <> text <> "aa" + #(Model(..model, name: text), 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.")]) + echo "NAME " <> model.name + case model.name { + "" -> + html.div([], [ + html.div([class("terminal-header")], [ + html.div([class("terminal-status")], [ + html.span([class("status-blink")], [html.text("●")]), + html.text(" SYSTEM READY"), + html.span([class("ml-8")], [ + html.text("<< Please Log On to use QuizTerm. >>"), + ]), + ]), + ]), + view_room_list(model.rooms), + ]) _ -> { - html.ul([], list.map(items, fn(item) { html.li([], [html.text(item)]) })) + html.div([], [ + html.div([class("terminal-header")], [ + html.div([class("terminal-status")], [ + html.span([class("status-blink")], [html.text("●")]), + html.text(" SYSTEM READY"), + html.span([class("ml-8")], [ + html.text("<< Please Log On to use QuizTerm. >>"), + ]), + ]), + ]), + pin(), + ]) } } } + +fn pin() -> Element(Msg) { + html.div([attribute.class("terminal-section")], [ + html.div([attribute.class("terminal-label mb-4")], [ + html.text("Select room to play in"), + ]), + html.div([attribute.class("participants-grid")], [ + html.text("Enter PIN code for room"), + ]), + ]) +} + +fn view_room_list(items: List(shared.Room)) -> Element(Msg) { + html.div([attribute.class("terminal-section")], [ + html.div([attribute.class("terminal-label mb-4")], [ + html.text("Select room to play in"), + ]), + html.div([attribute.class("participants-grid")], case items { + [] -> [html.text("No items in your list yet.")] + _ -> { + list.index_map(items, fn(item, index) { + content_cell(index, item, UserTypedNewItem) + }) + } + }), + ]) +} + +fn content_cell( + number: Int, + room: shared.Room, + on_click: fn(String) -> Msg, +) -> Element(Msg) { + html.div([class("participant-login"), event.on_click(on_click(room.name))], [ + html.div([class("participant-name")], [ + html.text("► " <> "[#" <> int.to_string(number) <> "] Team " <> room.name), + ]), + ]) +} diff --git a/client/src/shared.gleam b/client/src/shared.gleam index f0bae3c..7f27196 100644 --- a/client/src/shared.gleam +++ b/client/src/shared.gleam @@ -1,19 +1,16 @@ import gleam/dynamic/decode -import gleam/json -pub type GroceryItem { - GroceryItem(name: String, quantity: Int) +pub type Room { + Room(id: String, name: String, pin: String) } -pub fn grocery_list_decoder() -> decode.Decoder(List(String)) { - decode.list(decode.string) -} -fn grocery_item_to_json(grocery_item: GroceryItem) -> json.Json { - let GroceryItem(name:, quantity:) = grocery_item - json.object([#("name", json.string(name)), #("quantity", json.int(quantity))]) +pub fn grocery_list_decoder() -> decode.Decoder(List(Room)) { + 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: )) + } + decode.list(room_decoder) } - -pub fn grocery_list_to_json(items: List(GroceryItem)) -> json.Json { - json.array(items, grocery_item_to_json) -} \ No newline at end of file diff --git a/server/priv/static/layout.css b/server/priv/static/layout.css index 94434d9..1baa22e 100644 --- a/server/priv/static/layout.css +++ b/server/priv/static/layout.css @@ -121,6 +121,12 @@ body { transition: all 0.2s; } +.participant-login { + border: 2px dashed #005500; + padding: 1rem; + transition: all 0.2s; +} + .participant-hidden { border: 0px dashed #005500; padding: 1rem; @@ -139,6 +145,12 @@ body { box-shadow: 0 0 20px rgba(0, 255, 0, 0.3); } +.participant-login:hover { + border: 2px solid #00ff00; + background: rgba(0, 255, 0, 0.05); + box-shadow: 0 0 20px rgba(0, 255, 0, 0.3); +} + .participant-name { color: #00ff00; font-weight: bold; diff --git a/server/priv/static/root.html b/server/priv/static/root.html index dd37914..993a821 100644 --- a/server/priv/static/root.html +++ b/server/priv/static/root.html @@ -7,9 +7,26 @@