cards/client/src/components/browser.rs
2024-12-03 17:52:45 -05:00

173 lines
8.3 KiB
Rust

use crate::components::websocket::WebSocketContext;
use leptos::prelude::*;
use leptos_use::core::ConnectionReadyState;
use lib::*;
use serde_json::to_string;
use thaw::*;
pub mod create_game;
#[component]
pub fn Browser() -> impl IntoView {
// Websocket stuff
let websocket = expect_context::<WebSocketContext>();
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
let tx = websocket.clone();
let (websocket_send, set_websocket_send) = signal("".to_string());
Effect::new(move |_| {
if websocket_send() != "".to_string() {
tx.send(&websocket_send());
}
});
// Browser stuff
let game_browser_context = expect_context::<ReadSignal<Vec<GameBrowserMeta>>>();
let join_id = RwSignal::new("".to_string());
let delete_id = RwSignal::new("".to_string());
let nav_context = expect_context::<RwSignal<String>>();
Effect::new(move |_| {
if join_id() != "" {
set_websocket_send(to_string(&GameJoinRequest { id: join_id() }).unwrap());
nav_context.set("game".to_string());
join_id.set("".to_string());
}
});
Effect::new(move |_| {
if delete_id() != "" {
set_websocket_send(
to_string(&GameDeleteRequest {
delete_game_id: delete_id(),
})
.unwrap(),
);
delete_id.set("".to_string());
}
});
let show_create_game = RwSignal::new(false);
provide_context(show_create_game);
view! {
<div class="my-2">
<div class="flex flex-wrap justify-between">
<Popover
trigger_type=PopoverTriggerType::Click
position=PopoverPosition::BottomStart
>
<PopoverTrigger slot>
<Button
icon=icondata::TbHelp
appearance=ButtonAppearance::Transparent
size=ButtonSize::Small
/>
</PopoverTrigger>
<p>"Yes, the delete button works. Please don't abuse it."</p>
</Popover>
<Button
icon=icondata::AiPlusOutlined
appearance=ButtonAppearance::Primary
size=ButtonSize::Small
on_click=move |_| nav_context.set("create".to_string())
>
"Create Game"
</Button>
</div>
<Show when=move || { connected() } fallback=|| view! { <p>"Disconnected."</p> }>
<Show
when=move || { game_browser_context().len() > 0 }
fallback=|| {
view! { <p>"No games to show right now.. Maybe you should create one!"</p> }
}
>
<div>
<Table>
<TableHeader>
<TableRow>
<TableHeaderCell class="justify-center">
<p>Name</p>
</TableHeaderCell>
<TableHeaderCell class="justify-center">
<p>Host</p>
</TableHeaderCell>
<TableHeaderCell class="justify-center">
<p>Players</p>
</TableHeaderCell>
<TableHeaderCell class="justify-center">
<p>Card Packs</p>
</TableHeaderCell>
<TableHeaderCell></TableHeaderCell>
</TableRow>
</TableHeader>
// This rebuilds the entire browser each time it runs but using <For /> won't update the children if the id doesn't change
{move || {
game_browser_context()
.iter()
.cloned()
.map(|game| {
view! {
<TableBody>
<TableRow>
<TableCell>
<TableCellLayout class="justify-center">
<p>{game.name}</p>
</TableCellLayout>
</TableCell>
<TableCell>
<TableCellLayout class="justify-center">
{game.host}
</TableCellLayout>
</TableCell>
<TableCell>
<TableCellLayout class="justify-center">
{game.players}
</TableCellLayout>
</TableCell>
<TableCell>
<TableCellLayout class="justify-center">
{game.packs.len()}
</TableCellLayout>
</TableCell>
<TableCell>
<TableCellLayout class="flex flex-wrap justify-center">
<Button
appearance=ButtonAppearance::Primary
size=ButtonSize::Small
on_click={
let game_id = game.uuid.clone();
move |_| {
join_id.set(game_id.clone());
}
}
>
"Join"
</Button>
<Button
appearance=ButtonAppearance::Secondary
size=ButtonSize::Small
icon=icondata::TiDeleteOutline
on_click=move |_| {
delete_id.set(game.uuid.clone());
}
>
"Delete"
</Button>
</TableCellLayout>
</TableCell>
</TableRow>
</TableBody>
}
})
.collect_view()
}}
</Table>
</div>
</Show>
</Show>
</div>
}
}