step for pin code login
This commit is contained in:
parent
e6851255dc
commit
0024687621
4 changed files with 118 additions and 46 deletions
|
|
@ -1,11 +1,13 @@
|
||||||
|
import gleam/int
|
||||||
import gleam/json
|
import gleam/json
|
||||||
import gleam/list
|
import gleam/list
|
||||||
import gleam/result
|
import gleam/result
|
||||||
import lustre
|
import lustre
|
||||||
import lustre/attribute
|
import lustre/attribute.{class}
|
||||||
import lustre/effect.{type Effect}
|
import lustre/effect.{type Effect}
|
||||||
import lustre/element.{type Element}
|
import lustre/element.{type Element}
|
||||||
import lustre/element/html
|
import lustre/element/html
|
||||||
|
import lustre/event
|
||||||
import plinth/browser/document
|
import plinth/browser/document
|
||||||
import plinth/browser/element as plinth_element
|
import plinth/browser/element as plinth_element
|
||||||
import shared
|
import shared
|
||||||
|
|
@ -27,10 +29,10 @@ pub fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Model {
|
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: "")
|
let model = Model(rooms: items, name: "")
|
||||||
|
|
||||||
#(model, effect.none())
|
#(model, effect.none())
|
||||||
|
|
@ -43,41 +45,85 @@ type Msg {
|
||||||
|
|
||||||
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
||||||
case msg {
|
case msg {
|
||||||
UserAddedItem -> {
|
UserAddedItem ->
|
||||||
case model.name {
|
case model.name {
|
||||||
"" -> #(model, effect.none())
|
_ -> #(model, effect.none())
|
||||||
name -> {
|
|
||||||
let updated_items = [name, ..model.rooms]
|
|
||||||
|
|
||||||
#(Model(rooms: updated_items, name: ""), 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) {
|
fn view(model: Model) -> Element(Msg) {
|
||||||
let styles = [
|
echo "NAME " <> model.name
|
||||||
#("max-width", "30ch"),
|
case model.name {
|
||||||
#("margin", "0 auto"),
|
"" ->
|
||||||
#("display", "flex"),
|
html.div([], [
|
||||||
#("flex-direction", "column"),
|
html.div([class("terminal-header")], [
|
||||||
#("gap", "1em"),
|
html.div([class("terminal-status")], [
|
||||||
]
|
html.span([class("status-blink")], [html.text("●")]),
|
||||||
|
html.text(" SYSTEM READY"),
|
||||||
html.div([attribute.styles(styles)], [
|
html.span([class("ml-8")], [
|
||||||
html.h1([], [html.text("Select your QuizRoom")]),
|
html.text("<< Please Log On to use QuizTerm. >>"),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
view_room_list(model.rooms),
|
view_room_list(model.rooms),
|
||||||
])
|
])
|
||||||
|
_ -> {
|
||||||
|
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(String)) -> Element(Msg) {
|
fn view_room_list(items: List(shared.Room)) -> Element(Msg) {
|
||||||
case items {
|
html.div([attribute.class("terminal-section")], [
|
||||||
[] -> html.p([], [html.text("No items in your list yet.")])
|
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.")]
|
||||||
_ -> {
|
_ -> {
|
||||||
html.ul([], list.map(items, fn(item) { html.li([], [html.text(item)]) }))
|
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),
|
||||||
|
]),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
import gleam/dynamic/decode
|
import gleam/dynamic/decode
|
||||||
import gleam/json
|
|
||||||
|
|
||||||
pub type GroceryItem {
|
pub type Room {
|
||||||
GroceryItem(name: String, quantity: Int)
|
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 {
|
pub fn grocery_list_decoder() -> decode.Decoder(List(Room)) {
|
||||||
let GroceryItem(name:, quantity:) = grocery_item
|
let room_decoder = {
|
||||||
json.object([#("name", json.string(name)), #("quantity", json.int(quantity))])
|
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)
|
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +121,12 @@ body {
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.participant-login {
|
||||||
|
border: 2px dashed #005500;
|
||||||
|
padding: 1rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
.participant-hidden {
|
.participant-hidden {
|
||||||
border: 0px dashed #005500;
|
border: 0px dashed #005500;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
|
|
@ -139,6 +145,12 @@ body {
|
||||||
box-shadow: 0 0 20px rgba(0, 255, 0, 0.3);
|
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 {
|
.participant-name {
|
||||||
color: #00ff00;
|
color: #00ff00;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,26 @@
|
||||||
<script src="/client.js" type="module"></script>
|
<script src="/client.js" type="module"></script>
|
||||||
<script id="model" type="application/json">
|
<script id="model" type="application/json">
|
||||||
[
|
[
|
||||||
"a",
|
{
|
||||||
"b",
|
"id": "abt",
|
||||||
"c"
|
"name": "Billettering",
|
||||||
|
"key": "T5X6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "slg",
|
||||||
|
"name": "Salg",
|
||||||
|
"key": "6B4T"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "prs",
|
||||||
|
"name": "Personalisering",
|
||||||
|
"key": "P2Q5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "srp",
|
||||||
|
"name": "Support",
|
||||||
|
"key": "P2Q5"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
<link href="/static/layout.css" rel="stylesheet" type="text/css">
|
<link href="/static/layout.css" rel="stylesheet" type="text/css">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue