cards/client/src/components/browser.rs
2024-08-18 19:16:57 -04:00

232 lines
10 KiB
Rust

use crate::components::websocket::WebSocketContext;
use leptos::html::Input;
use leptos::*;
use leptos_use::core::ConnectionReadyState;
use lib::*;
use serde_json::to_string;
use std::collections::BTreeSet;
#[component]
pub fn Browser() -> impl IntoView {
let websocket = expect_context::<WebSocketContext>();
// TODO: don't do this
let tx = websocket.clone();
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
let game_browser_context = expect_context::<ReadSignal<Vec<GameBrowserMeta>>>();
let card_packs = expect_context::<ReadSignal<CardPacksMeta>>();
let new_game_name_ref = create_node_ref::<Input>();
let (selected_packs, set_selected_packs) = create_signal::<BTreeSet<u8>>(BTreeSet::new());
// create_effect(move |_| {
// logging::log!("{:#?}", selected_packs().iter().collect::<Vec<_>>());
// });
// Game stuff
let new_game = move |_| {
if let Some(input) = new_game_name_ref.get() {
if input.value() == *"" {
logging::log!("New game name is empty!");
} else if selected_packs().is_empty() {
logging::log!("New game selected packs is empty!");
} else {
tx.send(
&to_string(&NewGameRequest {
name: input.value(),
packs: selected_packs().into_iter().collect::<Vec<_>>(),
})
.unwrap(),
);
input.set_value("");
}
}
};
let (show_packs, set_show_packs) = create_signal(false);
let show_packs_button = move |_| set_show_packs(!show_packs());
let (join_id, set_join_id) = create_signal("".to_string());
create_effect(move |_| {
websocket.send(&to_string(&GameJoinRequest { id: join_id() }).unwrap());
});
view! {
<div class="p-1">
<h2 class="text-2xl">Game Browser</h2>
<table class="min-w-full border border-collapse table-auto">
<thead>
<tr>
<th class="border-b">Name</th>
<th class="border-b">Host</th>
<th class="border-b">Players</th>
<th class="border-b">Card Packs</th>
<th class="border-b"></th>
</tr>
</thead>
{move || {
game_browser_context()
.iter()
.map(|game| {
view! {
<tr>
<td class="text-center border-b">{&game.name}</td>
<td class="text-center border-b">{&game.host}</td>
<td class="text-center border-b">
{&game.players.to_string()}
</td>
<td class="text-center border-b">
{&game.packs.len().to_string()}
</td>
<td class="text-center border-b">
<button
type="button"
value=&game.uuid
on:click=move |e| {
set_join_id(event_target_value(&e));
}
>
Join
</button>
<button type="button">Delete</button>
</td>
</tr>
}
})
.collect_view()
}}
</table>
</div>
<hr />
<div class="flex p-1">
<form onsubmit="return false" on:submit=new_game>
<h2 class="text-2xl">Create Game</h2>
<input
class="w-80 h-11 font-mono rounded-sm bg-neutral-900 text-neutral-200"
placeholder="Name"
disabled=move || !connected()
node_ref=new_game_name_ref
/>
<h2 class="text-2xl">Packs</h2>
<div class="p-2">
<button type="button" class="bg-neutral-600">
<input type="checkbox" id="all" />
<label for="all">All</label>
</button>
<button type="button" class="bg-neutral-600">
<input type="checkbox" id="official" checked />
<label for="official">Official</label>
</button>
<button type="button" class="bg-neutral-600" on:click=show_packs_button>
<label>Custom</label>
</button>
TODO: finish this
</div>
<Show when=move || show_packs()>
<span class="flex">
<div>
<h2 class="text-xl">Official</h2>
{move || {
card_packs()
.official_meta
.into_iter()
.map(|n| {
view! {
<input
type="checkbox"
value=n.pack
id=n.pack
checked
on:change=move |e| {
if event_target_checked(&e) {
logging::log!("insert");
set_selected_packs
.update(|packs| {
packs.insert(n.pack);
})
} else {
logging::log!("remove");
set_selected_packs
.update(|packs| {
packs.remove(&n.pack);
})
}
}
/>
<label for=n.pack>{n.name}</label>
<br />
// hax
{set_selected_packs
.update(|packs| {
packs.insert(n.pack);
})}
}
})
.collect_view()
}}
</div>
<div>
<h2 class="text-xl">Unofficial</h2>
{move || {
card_packs()
.unofficial_meta
.into_iter()
.map(|n| {
view! {
<input
checked
type="checkbox"
value=n.pack
id=n.pack
on:change=move |e| {
if event_target_checked(&e) {
logging::log!("insert");
set_selected_packs
.update(|packs| {
packs.insert(n.pack);
})
} else {
logging::log!("remove");
set_selected_packs
.update(|packs| {
packs.remove(&n.pack);
})
}
}
/>
<label for=n.pack>{n.name}</label>
<br />
// hax
{set_selected_packs
.update(|packs| {
packs.insert(n.pack);
})}
}
})
.collect_view()
}}
</div>
</span>
</Show>
<input
class="py-2 px-4 pl-4 font-bold text-white rounded border-b-4 bg-neutral-600 border-neutral-800 hover:bg-neutral-700 hover:border-neutral-500"
type="submit"
disabled=move || !connected()
value="New Game"
/>
</form>
</div>
}
}