cards/client/src/components/game.rs

254 lines
9.3 KiB
Rust
Raw Normal View History

2024-08-18 18:48:37 -04:00
use crate::components::cards::*;
2024-08-17 21:55:15 -04:00
use crate::components::websocket::WebSocketContext;
2024-08-09 01:21:04 -04:00
use leptos::*;
2024-08-21 22:25:33 -04:00
use leptos_use::core::ConnectionReadyState;
2024-08-09 02:57:27 -04:00
use lib::*;
2024-08-17 21:55:15 -04:00
use serde_json::to_string;
2024-08-20 22:25:39 -04:00
use std::collections::HashMap;
2024-08-09 01:21:04 -04:00
#[component]
pub fn Game() -> impl IntoView {
2024-08-17 21:55:15 -04:00
let websocket = expect_context::<WebSocketContext>();
2024-08-21 22:25:33 -04:00
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
2024-08-14 00:16:54 -04:00
let game_meta = expect_context::<ReadSignal<Option<GameStateMeta>>>();
2024-08-20 22:25:39 -04:00
let judge_round = expect_context::<ReadSignal<Option<JudgeRound>>>();
2024-08-09 02:57:27 -04:00
2024-08-17 21:55:15 -04:00
let (game_id, set_game_id) = create_signal("".to_string());
2024-08-09 02:57:27 -04:00
let (game_name, set_game_name) = create_signal("".to_string());
let (game_host, set_game_host) = create_signal("".to_string());
2024-08-10 19:50:26 -04:00
let (game_players, set_game_players) = create_signal(vec![]);
let (game_czar, set_game_czar) = create_signal("".to_string());
2024-08-24 21:45:15 -04:00
let (game_white_count, set_game_white_count) = create_signal(0usize);
let (game_black_count, set_game_black_count) = create_signal(0usize);
let (game_white_discard_count, set_game_white_discard_count) = create_signal(0usize);
2024-08-12 17:14:27 -04:00
let (game_black, set_game_black) = create_signal(("".to_string(), 0u8));
2024-08-18 18:48:37 -04:00
let (selected_cards_ordered, set_selected_cards_ordered) = create_signal::<Vec<String>>(vec![]);
2024-08-18 19:51:45 -04:00
let (player_hand, set_player_hand) = create_signal::<Vec<String>>(vec![]);
2024-08-20 22:25:39 -04:00
let (player_white, set_player_white) =
create_signal::<HashMap<String, WhiteCardMeta>>(HashMap::new());
2024-08-18 18:48:37 -04:00
let (card_clicked, set_card_clicked) = create_signal::<String>(String::new());
provide_context::<WriteSignal<String>>(set_card_clicked);
2024-08-09 02:57:27 -04:00
2024-08-21 22:25:33 -04:00
// Clear everything on disconnect
create_effect(move |_| {
if !connected() {
set_game_id("".to_string());
set_game_name("".to_string());
set_game_host("".to_string());
set_game_players(vec![]);
set_game_czar("".to_string());
set_game_black(("".to_string(), 0u8));
set_selected_cards_ordered(vec![]);
set_player_hand(vec![]);
set_player_white.update(|hand| {
hand.clear();
});
2024-08-24 21:45:15 -04:00
set_game_white_count(0usize);
set_game_black_count(0usize);
set_game_white_discard_count(0usize);
2024-08-21 22:25:33 -04:00
}
});
2024-08-20 22:25:39 -04:00
// Handle incoming judge message
create_effect(move |_| {
judge_round.with(move |judge_round| {
set_player_hand.update(|list| {
list.clear();
});
set_player_white.update(|list| {
list.clear();
});
set_card_clicked.update(|list| {
list.clear();
});
set_selected_cards_ordered.update(|list| {
list.clear();
});
// Load hand
if let Some(judge) = judge_round {
for cards in judge.cards_to_judge.clone() {
for card in cards {
set_player_white.update(|hand| {
hand.insert(card.uuid.clone(), card.clone());
});
set_player_hand.update(|hand| {
hand.push(card.uuid.clone());
});
}
}
}
});
});
// Handle incoming state update
2024-08-09 02:57:27 -04:00
create_effect(move |_| {
if let Some(game) = game_meta() {
2024-08-18 20:19:32 -04:00
// Clear in case of (re-)joining game
set_card_clicked.update(|list| {
list.clear();
});
set_selected_cards_ordered.update(|list| {
list.clear();
});
set_player_hand.update(|list| {
list.clear();
});
set_player_white.update(|list| {
list.clear();
});
// Load meta
2024-08-17 21:55:15 -04:00
set_game_id(game.uuid.clone());
2024-08-10 19:50:26 -04:00
set_game_name(game.name.clone());
set_game_host(game.host.clone());
set_game_players(game.players.clone());
set_game_czar(game.czar.clone());
set_game_black(game.black.clone());
2024-08-24 21:45:15 -04:00
set_game_white_count(game.white_count.clone());
set_game_black_count(game.black_count.clone());
set_game_white_discard_count(game.white_discard_count.clone());
2024-08-18 19:21:12 -04:00
// Load hand
2024-08-18 18:48:37 -04:00
for card in game.white {
2024-08-18 19:51:45 -04:00
set_player_white.update(|hand| {
2024-08-18 18:48:37 -04:00
hand.insert(card.uuid.clone(), card.clone());
2024-08-18 19:51:45 -04:00
});
set_player_hand.update(|hand| {
hand.push(card.uuid.clone());
});
2024-08-18 18:48:37 -04:00
}
2024-08-09 02:57:27 -04:00
}
});
2024-08-20 22:25:39 -04:00
// Move cards back and forth between hand and selected when clicked
2024-08-17 21:55:15 -04:00
create_effect(move |_| {
2024-08-18 19:51:45 -04:00
if let Some(card_index) = player_hand()
.iter()
.position(|card| *card == card_clicked())
{
set_player_hand.update(|list| {
list.remove(card_index);
2024-08-18 18:48:37 -04:00
});
set_selected_cards_ordered.update(|list| {
list.push(card_clicked());
2024-08-18 19:51:45 -04:00
})
} else if let Some(card_index) = selected_cards_ordered()
.iter()
.position(|card| *card == card_clicked())
{
2024-08-18 18:48:37 -04:00
set_selected_cards_ordered.update(|list| {
2024-08-18 19:51:45 -04:00
list.remove(card_index);
2024-08-18 18:48:37 -04:00
});
2024-08-18 19:51:45 -04:00
set_player_hand.update(|list| {
list.push(card_clicked());
})
2024-08-18 18:48:37 -04:00
}
2024-08-17 21:55:15 -04:00
});
2024-08-20 22:25:39 -04:00
let submit_cards = move |_| {
let tx = websocket.clone();
judge_round.with(move |judge| {
let mut _message: Option<String> = None;
if judge.is_some() {
_message = Some(
to_string(&JudgeDecisionRequest {
game_id: game_id(),
winning_cards: selected_cards_ordered(),
})
.unwrap(),
);
} else {
_message = Some(
to_string(&PlayerMoveRequest {
game_id: game_id(),
card_ids: selected_cards_ordered(),
})
.unwrap(),
);
}
if let Some(msg) = _message {
tx.send(&msg);
}
})
};
2024-08-18 18:48:37 -04:00
2024-08-09 01:21:04 -04:00
view! {
<div class="p-1">
2024-08-13 18:16:31 -04:00
<div class="relative">
<h2 class="text-2xl">Game</h2>
<span>
<p>Name: {move || game_name()}</p>
<p>Host: {move || game_host()}</p>
<p>Czar: {move || game_czar()}</p>
2024-08-24 21:45:15 -04:00
<p>White Deck: {move || game_white_count().to_string()}</p>
<p>White Discard: {move || game_white_discard_count().to_string()}</p>
<p>Black Deck: {move || game_black_count().to_string()}</p>
2024-08-13 18:16:31 -04:00
</span>
<span class="absolute top-0 right-0">
<p>Players:</p>
2024-08-22 21:19:34 -04:00
<table class="min-w-full border border-collapse table-auto">
<thead>
<tr>
<th class="border-b">Name</th>
<th class="border-b">Score</th>
</tr>
</thead>
2024-08-13 18:16:31 -04:00
{move || {
game_players()
.iter()
2024-08-22 21:19:34 -04:00
.map(|player| {
view! {
<tr>
<td class="text-center border-b">{&player.name}</td>
<td class="text-center border-b">
{&player.score.to_string()}
</td>
</tr>
}
})
2024-08-13 18:16:31 -04:00
.collect_view()
}}
2024-08-22 21:19:34 -04:00
</table>
2024-08-13 18:16:31 -04:00
</span>
</div>
2024-08-19 17:12:18 -04:00
// Game cards
// TODO: offset this correctly
<div class="w-full ms-16 inline-flex flex-wrap">
2024-08-18 18:48:37 -04:00
<BlackCard card_data=game_black />
// Card selection
<For
each=move || selected_cards_ordered()
2024-08-18 19:51:45 -04:00
key=move |card| player_white().get(card).unwrap().uuid.clone()
2024-08-18 18:48:37 -04:00
children=move |card| {
2024-08-18 19:51:45 -04:00
view! { <WhiteCard card_data=player_white().get(&card).unwrap().clone() /> }
2024-08-18 18:48:37 -04:00
}
/>
2024-08-19 17:12:18 -04:00
</div>
2024-08-20 22:25:39 -04:00
<div class="w-full inline-flex flex-wrap justify-center">
<button type="button" on:click=submit_cards>
Submit
</button>
</div>
2024-08-19 17:12:18 -04:00
// Player cards
2024-08-13 18:16:31 -04:00
<div class="inline-flex flex-wrap justify-center">
2024-08-18 18:48:37 -04:00
<For
each=move || player_hand()
2024-08-18 19:51:45 -04:00
key=move |card| player_white().get(card).unwrap().uuid.clone()
2024-08-18 18:48:37 -04:00
children=move |card| {
2024-08-18 19:51:45 -04:00
view! { <WhiteCard card_data=player_white().get(&card).unwrap().clone() /> }
2024-08-18 18:48:37 -04:00
}
/>
2024-08-12 18:36:26 -04:00
</div>
2024-08-09 01:21:04 -04:00
</div>
}
}