single game fix
This commit is contained in:
parent
09bf741997
commit
f3020b7cb0
6 changed files with 195 additions and 128 deletions
|
|
@ -51,7 +51,7 @@ fn layout(header: String, ohno: option.Option(String), body: List(Element(Msg)))
|
||||||
|
|
||||||
fn view_room_list(items: List(Room)) -> Element(Msg) {
|
fn view_room_list(items: List(Room)) -> Element(Msg) {
|
||||||
layout("Select room to play in", None, case items {
|
layout("Select room to play in", None, case items {
|
||||||
[] -> [html.text("No items in your list yet.")]
|
[] -> [html.text("No rooms exist, nowhere to play! (ohno!)")]
|
||||||
_ -> {
|
_ -> {
|
||||||
list.index_map(items, fn(item, index) {
|
list.index_map(items, fn(item, index) {
|
||||||
room_cell(index, item, SelectedRoom)
|
room_cell(index, item, SelectedRoom)
|
||||||
|
|
@ -93,7 +93,6 @@ fn view_live_or_single() -> Element(Msg) {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn input_cell(
|
fn input_cell(
|
||||||
header: String,
|
header: String,
|
||||||
password: Bool,
|
password: Bool,
|
||||||
|
|
@ -101,7 +100,7 @@ fn input_cell(
|
||||||
) -> Element(Msg) {
|
) -> Element(Msg) {
|
||||||
html.div([class("participant-login")], [
|
html.div([class("participant-login")], [
|
||||||
html.div([class("participant-name")], [
|
html.div([class("participant-name")], [
|
||||||
html.text("► " <> header),
|
html.p([], [html.text("► " <> header)]),
|
||||||
html.div([], [
|
html.div([], [
|
||||||
html.input([
|
html.input([
|
||||||
attribute.type_(case password {
|
attribute.type_(case password {
|
||||||
|
|
|
||||||
|
|
@ -261,24 +261,64 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
.terminal-input-wrap {
|
||||||
background-color: #000000;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-input-wrap::before {
|
||||||
|
content: "$>";
|
||||||
color: #00ff00;
|
color: #00ff00;
|
||||||
width: 20cap;
|
font-weight: bold;
|
||||||
|
text-shadow: 0 0 5px rgba(0, 255, 0, 0.8);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
background: transparent;
|
||||||
|
color: #00ff00;
|
||||||
|
font-family: "Courier New", "Courier", monospace;
|
||||||
|
font-size: inherit;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid #00aa00;
|
||||||
|
outline: none;
|
||||||
|
caret-color: #00ff00;
|
||||||
|
width: 20ch;
|
||||||
|
padding: 0 0 2px 0;
|
||||||
|
text-shadow: 0 0 5px rgba(0, 255, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: transparent;
|
||||||
|
color: #00ff00;
|
||||||
|
font-family: "Courier New", "Courier", monospace;
|
||||||
|
font-size: inherit;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid #00aa00;
|
||||||
|
outline: none;
|
||||||
|
caret-color: #00ff00;
|
||||||
|
width: 20ch;
|
||||||
|
padding: 0 0 2px 0;
|
||||||
|
text-shadow: 0 0 5px rgba(0, 255, 0, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
input:focus {
|
input:focus {
|
||||||
background-color: #000000;
|
border-bottom-color: #00ff00;
|
||||||
width: 20cap;
|
box-shadow: 0 2px 8px rgba(0, 255, 0, 0.3);
|
||||||
border-color: #00ff00;
|
}
|
||||||
outline: none;
|
button:hover {
|
||||||
|
border-bottom-color: #00ff00;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 255, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
|
/*button {
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
color: #00ff00;
|
color: #00ff00;
|
||||||
border: 3px solid #73ad21;
|
border: 3px solid #73ad21;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
button:focus {
|
button:focus {
|
||||||
border: 3px solid #534d01;
|
border: 3px solid #534d01;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import components.{click_cell, click_cell_pair}
|
import components.{click_cell_pair}
|
||||||
import gleam/bit_array
|
import gleam/bit_array
|
||||||
import gleam/crypto
|
import gleam/crypto
|
||||||
import gleam/dynamic/decode
|
import gleam/dynamic/decode
|
||||||
|
|
@ -146,7 +146,7 @@ fn view(model: Model) -> Element(Msg) {
|
||||||
html.div([class("terminal-status")], [
|
html.div([class("terminal-status")], [
|
||||||
html.span([class("status-blink")], [html.text("●")]),
|
html.span([class("status-blink")], [html.text("●")]),
|
||||||
html.text(" SYSTEM READY"),
|
html.text(" SYSTEM READY"),
|
||||||
html.span([class("ml-8")], [
|
html.div([class("ml-8")], [
|
||||||
case model.state {
|
case model.state {
|
||||||
Initial -> html.text("STATUS: Please select player")
|
Initial -> html.text("STATUS: Please select player")
|
||||||
ReceiveName(_) -> html.text("STATUS: Please enter your name")
|
ReceiveName(_) -> html.text("STATUS: Please enter your name")
|
||||||
|
|
@ -163,19 +163,18 @@ fn view(model: Model) -> Element(Msg) {
|
||||||
html.text("[ACTIVE TRANSMISSIONS]"),
|
html.text("[ACTIVE TRANSMISSIONS]"),
|
||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
html.div([class("participants-grid")], [
|
html.div([class("participants-grid")], [
|
||||||
case model.state {
|
case model.state {
|
||||||
Initial ->
|
Initial ->
|
||||||
case model.players {
|
case model.players {
|
||||||
[] -> input_new_player()
|
[] -> shared.input_new_player(ReceiveName)
|
||||||
_ -> view_players(model.players)
|
_ -> shared.view_players(model.players, PickedPlayer)
|
||||||
}
|
}
|
||||||
PickQuestion -> view_questions(model.answers)
|
PickQuestion -> view_questions(model.answers)
|
||||||
ReceiveName(_) -> input_new_player()
|
ReceiveName(_) -> shared.input_new_player(ReceiveName)
|
||||||
AcceptPlayer(Some(player)) -> {
|
AcceptPlayer(Some(player)) -> {
|
||||||
let #(_, player_name) = player
|
let #(_, player_name) = player
|
||||||
shared.confirm_cell(
|
shared.confirm_cells(
|
||||||
Some("Join as this player: " <> player_name <> "?"),
|
Some("Join as this player: " <> player_name <> "?"),
|
||||||
player,
|
player,
|
||||||
AcceptPlayer,
|
AcceptPlayer,
|
||||||
|
|
@ -189,26 +188,6 @@ fn view(model: Model) -> Element(Msg) {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_players(players: List(#(String, String))) {
|
|
||||||
html.div([], [
|
|
||||||
html.div(
|
|
||||||
[],
|
|
||||||
list.append(
|
|
||||||
list.index_map(players, fn(item, index) {
|
|
||||||
click_cell_pair(Some(int.to_string(index)), Some(item), PickedPlayer)
|
|
||||||
}),
|
|
||||||
[click_cell_pair(Some("ENTER NEW PLAYER"), None, PickedPlayer)],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_new_player() {
|
|
||||||
html.div([class("participant-box")], [
|
|
||||||
input_cell("Enter player name:", ReceiveName),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn input_new_answer(question: #(String, String)) {
|
fn input_new_answer(question: #(String, String)) {
|
||||||
let #(question_id, question_text) = question
|
let #(question_id, question_text) = question
|
||||||
html.div([class("participant-box")], [
|
html.div([class("participant-box")], [
|
||||||
|
|
@ -220,6 +199,7 @@ fn input_new_answer(question: #(String, String)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_questions(answers: List(#(String, #(String, String)))) {
|
fn view_questions(answers: List(#(String, #(String, String)))) {
|
||||||
|
html.div([], [
|
||||||
html.div(
|
html.div(
|
||||||
[class("singles-grid")],
|
[class("singles-grid")],
|
||||||
list.map(answers, fn(content) {
|
list.map(answers, fn(content) {
|
||||||
|
|
@ -227,10 +207,17 @@ fn view_questions(answers: List(#(String, #(String, String)))) {
|
||||||
click_cell_pair(
|
click_cell_pair(
|
||||||
Some(number <> " " <> answer),
|
Some(number <> " " <> answer),
|
||||||
Some(#(number, question)),
|
Some(#(number, question)),
|
||||||
|
True,
|
||||||
PickedQuestion,
|
PickedQuestion,
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
),
|
||||||
|
html.div([], [
|
||||||
|
html.text(
|
||||||
|
"[Your answers are saved automatically, when you are done answering, simply close the window]",
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_cell(answer: #(Int, #(String, String))) -> Element(Msg) {
|
fn content_cell(answer: #(Int, #(String, String))) -> Element(Msg) {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import lustre/element/html
|
||||||
import lustre/server_component
|
import lustre/server_component
|
||||||
import shared/message.{type NotifyClient, type NotifyServer, type User, User}
|
import shared/message.{type NotifyClient, type NotifyServer, type User, User}
|
||||||
import web/components/shared.{
|
import web/components/shared.{
|
||||||
step_prompt, view_input, view_named_input, view_yes_no,
|
input_new_player, step_prompt, view_named_input, view_players,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn component() -> lustre.App(message.ClientsServer, Model, Msg) {
|
pub fn component() -> lustre.App(message.ClientsServer, Model, Msg) {
|
||||||
|
|
@ -29,6 +29,7 @@ type State {
|
||||||
pub opaque type Model {
|
pub opaque type Model {
|
||||||
Model(
|
Model(
|
||||||
state: State,
|
state: State,
|
||||||
|
players: List(#(String, String)),
|
||||||
lobby: #(String, List(User)),
|
lobby: #(String, List(User)),
|
||||||
registry: GroupRegistry(NotifyClient),
|
registry: GroupRegistry(NotifyClient),
|
||||||
handler: Started(Subject(NotifyServer)),
|
handler: Started(Subject(NotifyServer)),
|
||||||
|
|
@ -38,7 +39,14 @@ pub opaque type Model {
|
||||||
fn init(handlers: message.ClientsServer) -> #(Model, Effect(Msg)) {
|
fn init(handlers: message.ClientsServer) -> #(Model, Effect(Msg)) {
|
||||||
let #(registry, handler) = handlers
|
let #(registry, handler) = handlers
|
||||||
|
|
||||||
let model = Model(AskName, #("", []), registry, handler)
|
let model =
|
||||||
|
Model(
|
||||||
|
AskName,
|
||||||
|
actor.call(handler.data, 1000, message.FetchPlayers),
|
||||||
|
#("", []),
|
||||||
|
registry,
|
||||||
|
handler,
|
||||||
|
)
|
||||||
#(model, subscribe(registry, SharedMessage))
|
#(model, subscribe(registry, SharedMessage))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,8 +66,8 @@ fn subscribe(
|
||||||
|
|
||||||
pub opaque type Msg {
|
pub opaque type Msg {
|
||||||
SharedMessage(message: NotifyClient)
|
SharedMessage(message: NotifyClient)
|
||||||
ReceiveName(message: String)
|
ReceiveName(Option(String))
|
||||||
AcceptName(accept: Option(String))
|
AcceptName(Option(#(String, String)))
|
||||||
GiveAnswer(name: String, answer: String)
|
GiveAnswer(name: String, answer: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,9 +75,13 @@ fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
||||||
let handler = model.handler
|
let handler = model.handler
|
||||||
|
|
||||||
case msg {
|
case msg {
|
||||||
ReceiveName(name) -> #(Model(..model, state: NameOk(name)), effect.none())
|
ReceiveName(Some(name)) -> #(
|
||||||
|
Model(..model, state: NameOk(name)),
|
||||||
|
effect.none(),
|
||||||
|
)
|
||||||
AcceptName(Some(name)) -> {
|
AcceptName(Some(name)) -> {
|
||||||
actor.send(handler.data, message.GiveName(name:))
|
let #(_, name) = name
|
||||||
|
actor.send(handler.data, message.GiveName(name))
|
||||||
#(Model(..model, state: WaitForQuiz(name)), effect.none())
|
#(Model(..model, state: WaitForQuiz(name)), effect.none())
|
||||||
}
|
}
|
||||||
AcceptName(None) -> #(Model(..model, state: AskName), effect.none())
|
AcceptName(None) -> #(Model(..model, state: AskName), effect.none())
|
||||||
|
|
@ -81,13 +93,15 @@ fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
|
||||||
handle_server_message(model, shared_msg),
|
handle_server_message(model, shared_msg),
|
||||||
effect.none(),
|
effect.none(),
|
||||||
)
|
)
|
||||||
|
_ -> #(model, effect.none())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_server_message(model: Model, notify_client) {
|
fn handle_server_message(model: Model, notify_client) {
|
||||||
case notify_client {
|
case notify_client {
|
||||||
message.Lobby(question, lobby) -> Model(..model, lobby: #(question, lobby))
|
message.Lobby(question, lobby) -> Model(..model, lobby: #(question, lobby))
|
||||||
message.Exit -> Model(AskName, #("", []), model.registry, model.handler)
|
message.Exit ->
|
||||||
|
Model(AskName, model.players, #("", []), model.registry, model.handler)
|
||||||
message.Answer ->
|
message.Answer ->
|
||||||
case model.state {
|
case model.state {
|
||||||
// We are currently waiting for next quiz question, ok to switch to answer mode
|
// We are currently waiting for next quiz question, ok to switch to answer mode
|
||||||
|
|
@ -117,20 +131,21 @@ fn handle_server_message(model: Model, notify_client) {
|
||||||
|
|
||||||
fn view(model: Model) -> Element(Msg) {
|
fn view(model: Model) -> Element(Msg) {
|
||||||
let #(question, lobby) = model.lobby
|
let #(question, lobby) = model.lobby
|
||||||
|
|
||||||
element.fragment([
|
element.fragment([
|
||||||
html.div([attribute.class("terminal-prompt")], [
|
html.div([attribute.class("terminal-prompt")], [
|
||||||
case model.state {
|
case model.state {
|
||||||
AskName ->
|
AskName ->
|
||||||
step_prompt(
|
case model.players {
|
||||||
"Hello stranger. To join the quiz, I need to know your name",
|
[] -> input_new_player(ReceiveName)
|
||||||
fn() { view_input(ReceiveName) },
|
_ -> view_players(model.players, AcceptName)
|
||||||
)
|
}
|
||||||
NameOk(name) ->
|
NameOk(name) -> {
|
||||||
step_prompt(
|
shared.confirm_cells(
|
||||||
"Your name is " <> name <> "? Are you absolutely sure???",
|
Some("Join as this player: " <> name <> "?"),
|
||||||
fn() { view_yes_no(name, AcceptName) },
|
#("", name),
|
||||||
|
AcceptName,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
Answer(name) ->
|
Answer(name) ->
|
||||||
step_prompt(
|
step_prompt(
|
||||||
"The Quiz Lead will now ask the question, and you may answer.",
|
"The Quiz Lead will now ask the question, and you may answer.",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
|
import components.{click_cell_pair}
|
||||||
import gleam/dynamic/decode
|
import gleam/dynamic/decode
|
||||||
|
import gleam/int
|
||||||
|
import gleam/list
|
||||||
import gleam/option.{type Option, None, Some}
|
import gleam/option.{type Option, None, Some}
|
||||||
import lustre/attribute
|
import lustre/attribute
|
||||||
import lustre/element.{type Element}
|
import lustre/element.{type Element}
|
||||||
|
|
@ -49,35 +52,6 @@ pub fn view_input(on_submit handle_keydown: fn(String) -> msg) -> Element(msg) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_yes_no(
|
|
||||||
accepted: String,
|
|
||||||
on_submit handle_button: fn(Option(String)) -> msg,
|
|
||||||
) -> Element(msg) {
|
|
||||||
html.div([], [
|
|
||||||
html.button([event.on_click(handle_button(Some(accepted)))], [
|
|
||||||
html.text(" <Yes> "),
|
|
||||||
]),
|
|
||||||
html.text(" - "),
|
|
||||||
html.button([event.on_click(handle_button(None))], [html.text(" <No> ")]),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn key_down(
|
|
||||||
success: fn(String) -> decode.Decoder(msg),
|
|
||||||
fail: fn() -> decode.Decoder(msg),
|
|
||||||
) {
|
|
||||||
event.on("keydown", {
|
|
||||||
use key <- decode.field("key", decode.string)
|
|
||||||
use value <- decode.subfield(["target", "value"], decode.string)
|
|
||||||
|
|
||||||
case key {
|
|
||||||
"Enter" if value != "" -> success(value)
|
|
||||||
_ -> fail()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|> server_component.include(["key", "target.value"])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prompt_input(key, on_keydown) {
|
fn prompt_input(key, on_keydown) {
|
||||||
keyed.div([], [
|
keyed.div([], [
|
||||||
#(key <> "header", html.text("$>")),
|
#(key <> "header", html.text("$>")),
|
||||||
|
|
@ -103,35 +77,83 @@ pub fn step_prompt(text: String, fetch: fn() -> Element(a)) {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
//fn xiew_player_list(items: List(String)) -> Element(Msg) {
|
pub fn confirm_cells(
|
||||||
// layout("Select or enter your player", None, case items {
|
|
||||||
// [] -> [html.text("No items in your list yet.")]
|
|
||||||
// _ -> {
|
|
||||||
// list.append(
|
|
||||||
// list.index_map(items, fn(item, index) {
|
|
||||||
// click_cell(index, item, SelectedPlayer)
|
|
||||||
// }),
|
|
||||||
// [input_cell("[#NEW PLAYER]", False, KeyPin)],
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
pub fn confirm_cell(
|
|
||||||
title: Option(String),
|
title: Option(String),
|
||||||
accepted: #(String, String),
|
accepted: #(String, String),
|
||||||
on_submit handle_button: fn(Option(#(String, String))) -> msg,
|
on_submit handle_button: fn(Option(#(String, String))) -> msg,
|
||||||
) -> Element(msg) {
|
) -> Element(msg) {
|
||||||
html.div([attribute.class("participant-login")], [
|
html.div([], [
|
||||||
|
html.div([attribute.class("participant-box")], [
|
||||||
html.div([attribute.class("participant-name")], [
|
html.div([attribute.class("participant-name")], [
|
||||||
case title {
|
case title {
|
||||||
Some(title) -> html.div([], [html.text(title)])
|
Some(title) -> html.div([], [html.text(title)])
|
||||||
None -> element.none()
|
_ -> element.none()
|
||||||
},
|
},
|
||||||
html.button([event.on_click(handle_button(Some(accepted)))], [
|
|
||||||
html.text(" <Yes> "),
|
|
||||||
]),
|
]),
|
||||||
html.text(" - "),
|
]),
|
||||||
html.button([event.on_click(handle_button(None))], [html.text(" <No> ")]),
|
click_cell_pair(Some("Yes"), Some(accepted), False, handle_button),
|
||||||
|
click_cell_pair(Some("No"), None, False, handle_button),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn view_players(
|
||||||
|
players: List(#(String, String)),
|
||||||
|
handler: fn(Option(#(String, String))) -> msg,
|
||||||
|
) {
|
||||||
|
html.div([], [
|
||||||
|
html.div(
|
||||||
|
[],
|
||||||
|
list.append(
|
||||||
|
list.index_map(players, fn(item, index) {
|
||||||
|
click_cell_pair(Some(int.to_string(index)), Some(item), True, handler)
|
||||||
|
}),
|
||||||
|
[click_cell_pair(Some("ENTER NEW PLAYER"), None, True, handler)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_new_player(handler: fn(Option(String)) -> msg) {
|
||||||
|
html.div([attribute.class("participant-box")], [
|
||||||
|
input_cell("Enter player name:", handler),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_cell(
|
||||||
|
text: String,
|
||||||
|
on_submit handle_keydown: fn(Option(String)) -> msg,
|
||||||
|
) -> Element(msg) {
|
||||||
|
html.div([attribute.class("singles-grid")], [
|
||||||
|
html.div([], [html.text(text)]),
|
||||||
|
keyed.div([], [
|
||||||
|
#("inputheader", html.text("$>")),
|
||||||
|
#(
|
||||||
|
"input",
|
||||||
|
html.input([
|
||||||
|
attribute.type_("text"),
|
||||||
|
key_down(
|
||||||
|
fn(a: String) { decode.success(handle_keydown(Some(a))) },
|
||||||
|
fn() { decode.failure(handle_keydown(None), "") },
|
||||||
|
),
|
||||||
|
attribute.autofocus(True),
|
||||||
|
]),
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn key_down(
|
||||||
|
success: fn(String) -> decode.Decoder(msg),
|
||||||
|
fail: fn() -> decode.Decoder(msg),
|
||||||
|
) {
|
||||||
|
event.on("keydown", {
|
||||||
|
use key <- decode.field("key", decode.string)
|
||||||
|
use value <- decode.subfield(["target", "value"], decode.string)
|
||||||
|
|
||||||
|
case key {
|
||||||
|
"Enter" if value != "" -> success(value)
|
||||||
|
_ -> fail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|> server_component.include(["key", "target.value"])
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ pub fn click_cell(
|
||||||
pub fn click_cell_pair(
|
pub fn click_cell_pair(
|
||||||
tag: Option(String),
|
tag: Option(String),
|
||||||
pair: Option(#(String, String)),
|
pair: Option(#(String, String)),
|
||||||
|
display_value: Bool,
|
||||||
on_click: fn(Option(#(String, String))) -> msg,
|
on_click: fn(Option(#(String, String))) -> msg,
|
||||||
) -> Element(msg) {
|
) -> Element(msg) {
|
||||||
let value = case pair {
|
let value = case pair {
|
||||||
|
|
@ -47,7 +48,10 @@ pub fn click_cell_pair(
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
html.text(value),
|
case display_value {
|
||||||
|
True -> html.text(value)
|
||||||
|
False -> element.none()
|
||||||
|
},
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue