Restore the player and gm sidebars
Some checks failed
Monorepo build / test-all (push) Failing after 7s
Monorepo build / build-flake (push) Failing after 4s

This commit was merged in pull request #442.
This commit is contained in:
2026-09-05 16:18:03 -04:00
parent 46dc20d2b5
commit 9cfc3cc025
4 changed files with 117 additions and 128 deletions

View File

@@ -14,18 +14,14 @@ mod types;
pub use types::*;
use yew_autoprops::autoprops;
#[derive(Properties, PartialEq)]
pub struct GmSidebarProps {
pub pc: Candela,
}
#[autoprops]
#[function_component]
pub fn GmSidebar(GmSidebarProps { pc }: &GmSidebarProps) -> Html {
pub fn GmSidebar(sheet: Candela) -> Html {
html! {
<Panel title={Some(pc.name.clone())}>
<DiscreteRange label="Body" current={pc.body_marks} max=3 />
<DiscreteRange label="Brain" current={pc.brain_marks} max=3 />
<DiscreteRange label="Bleed" current={pc.bleed_marks} max=3 />
<Panel title={Some(sheet.name.clone())}>
<DiscreteRange label="Body" current={sheet.body_marks} max=3 />
<DiscreteRange label="Brain" current={sheet.brain_marks} max=3 />
<DiscreteRange label="Bleed" current={sheet.bleed_marks} max=3 />
</Panel>
}
}

View File

@@ -2,6 +2,7 @@ use glimmer_yew_deprecated::prelude::{DiscreteRange, Panel};
use utils::clone;
use visions_types::Character;
use yew::prelude::*;
use yew_autoprops::autoprops;
use crate::systems::candela::{
ActionElement, ActionGroupHeader, ActionName, Candela, DriveName, MarkFieldName,
@@ -15,11 +16,12 @@ pub struct SidebarProperties {
pub on_save: Callback<Character>,
}
#[autoprops]
#[function_component]
pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) -> Html {
let on_change_marks = clone!((character, on_save), move |field: MarkFieldName| {
clone!((character, on_save, field), move |value: u8| {
let mut pc = character.clone();
pub fn Sidebar(sheet: Candela, on_save: Callback<serde_json::Value>) -> Html {
let on_change_marks = clone!((sheet, on_save), move |field: MarkFieldName| {
clone!((sheet, on_save, field), move |value: u8| {
let mut pc = sheet.clone();
match field {
MarkFieldName::Body => {
pc.body_marks = value;
@@ -31,37 +33,37 @@ pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) ->
pc.brain_marks = value;
}
}
// on_save.emit(Sheet::Candela(pc));
on_save.emit(serde_json::to_value(sheet.clone()).unwrap());
})
});
let on_update_drive: Callback<(DriveName, u8)> = use_callback(
(character.clone(), on_save.clone()),
|(drive, value), (character, _on_save): &(Candela, Callback<Character>)| {
let mut character = character.clone();
(sheet.clone(), on_save.clone()),
|(drive, value), (sheet, on_save)| {
let mut sheet = sheet.clone();
match drive {
DriveName::Nerve => character.nerve_drive.value = value,
DriveName::Cunning => character.cunning_drive.value = value,
DriveName::Intuition => character.intuition_drive.value = value,
DriveName::Nerve => sheet.nerve_drive.value = value,
DriveName::Cunning => sheet.cunning_drive.value = value,
DriveName::Intuition => sheet.intuition_drive.value = value,
}
// on_save.emit(Sheet::Candela(character));
on_save.emit(serde_json::to_value(sheet).unwrap());
},
);
let on_update_resistance: Callback<(DriveName, u8)> = use_callback(
(character.clone(), on_save.clone()),
|(drive, value), (character, _on_save): &(Candela, Callback<Character>)| {
let mut character = character.clone();
(sheet.clone(), on_save.clone()),
|(drive, value), (sheet, on_save)| {
let mut sheet = sheet.clone();
match drive {
DriveName::Nerve => character.nerve_resistance = value,
DriveName::Cunning => character.cunning_resistance = value,
DriveName::Intuition => character.intuition_resistance = value,
DriveName::Nerve => sheet.nerve_resistance = value,
DriveName::Cunning => sheet.cunning_resistance = value,
DriveName::Intuition => sheet.intuition_resistance = value,
}
// on_save.emit(Sheet::Candela(character));
on_save.emit(serde_json::to_value(sheet).unwrap());
},
);
let sheet = &character;
let sheet = &sheet;
html! {
<div>
@@ -69,49 +71,49 @@ pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) ->
<div>
<ActionGroupHeader
name={DriveName::Nerve}
group={character.nerve_drive.clone()}
resistance={character.nerve_resistance}
group={sheet.nerve_drive.clone()}
resistance={sheet.nerve_resistance}
on_change={on_update_drive.clone()}
on_change_resistance={on_update_resistance.clone()} />
<ActionElement
name={ActionName::Move}
action={character.move_.clone()} />
action={sheet.move_.clone()} />
<ActionElement
name={ActionName::Strike}
action={character.strike.clone()} />
action={sheet.strike.clone()} />
<ActionElement
name={ActionName::Control}
action={character.control.clone()} />
action={sheet.control.clone()} />
<ActionGroupHeader
name={DriveName::Cunning}
group={character.cunning_drive.clone()}
resistance={character.cunning_resistance}
group={sheet.cunning_drive.clone()}
resistance={sheet.cunning_resistance}
on_change={on_update_drive.clone()}
on_change_resistance={on_update_resistance.clone()} />
<ActionElement
name={ActionName::Sway}
action={character.sway.clone()} />
action={sheet.sway.clone()} />
<ActionElement
name={ActionName::Read}
action={character.read.clone()} />
action={sheet.read.clone()} />
<ActionElement
name={ActionName::Hide}
action={character.hide.clone()} />
action={sheet.hide.clone()} />
<ActionGroupHeader
name={DriveName::Intuition}
group={character.intuition_drive.clone()}
resistance={character.intuition_resistance}
group={sheet.intuition_drive.clone()}
resistance={sheet.intuition_resistance}
on_change={on_update_drive.clone()}
on_change_resistance={on_update_resistance.clone()} />
<ActionElement
name={ActionName::Survey}
action={character.survey.clone()} />
action={sheet.survey.clone()} />
<ActionElement
name={ActionName::Focus}
action={character.focus.clone()} />
action={sheet.focus.clone()} />
<ActionElement
name={ActionName::Sense}
action={character.sense.clone()} />
action={sheet.sense.clone()} />
</div>
<hr />
<div>

View File

@@ -53,16 +53,9 @@ pub fn PoolElement(
}
}
#[derive(PartialEq, Properties)]
pub struct SidebarProperties {
pub character: Cypher,
#[prop_or(Callback::from(|_| {}))]
pub on_save: Callback<Character>,
}
#[autoprops]
#[function_component]
pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) -> Html {
pub fn Sidebar(sheet: Cypher, on_save: Callback<serde_json::Value>) -> Html {
let styles = css!(
display: flex;
flex-flow: column;
@@ -70,8 +63,8 @@ pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) ->
gap: 4px;
);
let on_pool_change = clone!((character, on_save), move |stat, value| {
let mut sheet = character.clone();
let on_pool_change = clone!((sheet, on_save), move |stat, value| {
let mut sheet = sheet.clone();
match stat {
Stat::Might => {
sheet.might.value = value;
@@ -83,7 +76,7 @@ pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) ->
sheet.intellect.value = value;
}
}
// on_save.emit(Sheet::Cypher(sheet));
on_save.emit(serde_json::to_value(sheet).unwrap());
});
let on_change_might = Callback::from(clone!(on_pool_change, move |val| on_pool_change(
@@ -100,37 +93,33 @@ pub fn Sidebar(SidebarProperties { character, on_save }: &SidebarProperties) ->
)));
html! {
<Panel title={Some(character.name.clone())}>
<Panel title={Some(sheet.name.clone())}>
<div class={styles}>
<PoolElement name="Might" value={character.might.clone()}
<PoolElement name="Might" value={sheet.might.clone()}
on_save={on_change_might} />
<PoolElement name="Speed" value={character.speed.clone()}
<PoolElement name="Speed" value={sheet.speed.clone()}
on_save={on_change_speed} />
<PoolElement name="Intellect" value={character.intellect.clone()}
<PoolElement name="Intellect" value={sheet.intellect.clone()}
on_save={on_change_intellect} />
</div>
</Panel>
}
}
#[derive(Properties, PartialEq)]
pub struct GmSidebarProps {
pub pc: Cypher,
}
#[autoprops]
#[function_component]
pub fn GmSidebar(GmSidebarProps { pc }: &GmSidebarProps) -> Html {
pub fn GmSidebar(sheet: Cypher) -> Html {
let styles = css! {
display: flex;
justify-content: space-between;
};
let might = pc.might.clone();
let speed = pc.speed.clone();
let intellect = pc.intellect.clone();
let might = sheet.might.clone();
let speed = sheet.speed.clone();
let intellect = sheet.intellect.clone();
html! {
<Panel title={Some(pc.name.clone())}>
<Panel title={Some(sheet.name.clone())}>
<div class={styles.clone()}>
<div><b>{"M "}</b> {might.value}</div>
<div><Meter current={u16::from(might.value)} max={u16::from(might.max)} /></div>

View File

@@ -86,6 +86,8 @@ trait SystemImpl {
fn decode(js: serde_json::Value) -> Option<Self::Sheet>;
fn full_sheet_view(sheet: Self::Sheet, on_save: Callback<serde_json::Value>) -> Html;
fn player_sidebar_view(sheet: Self::Sheet, on_save: Callback<serde_json::Value>) -> Html;
fn gm_sidebar_view(sheet: Self::Sheet) -> Html;
fn character_list_row(sheet: Self::Sheet) -> Html;
}
@@ -109,6 +111,18 @@ impl SystemImpl for CandelaSystem {
}
}
fn player_sidebar_view(sheet: Self::Sheet, on_save: Callback<serde_json::Value>) -> Html {
html! {
<candela::Sidebar {sheet} {on_save} />
}
}
fn gm_sidebar_view(sheet: Self::Sheet) -> Html {
html! {
<candela::GmSidebar {sheet} />
}
}
fn character_list_row(sheet: Self::Sheet) -> Html {
html! {
<candela::CharacterListRow {sheet} />
@@ -132,6 +146,18 @@ impl SystemImpl for CypherSystem {
}
}
fn player_sidebar_view(sheet: Self::Sheet, on_save: Callback<serde_json::Value>) -> Html {
html! {
<cypher::Sidebar {sheet} {on_save} />
}
}
fn gm_sidebar_view(sheet: Self::Sheet) -> Html {
html! {
<cypher::GmSidebar {sheet} />
}
}
fn character_list_row(sheet: Self::Sheet) -> Html {
html! {
<cypher::CharacterListRow {sheet} />
@@ -139,32 +165,6 @@ impl SystemImpl for CypherSystem {
}
}
// pub const SYSTEMS: [System; 3] = [System::Candela, System::Cypher];
//
/*
#[derive(Clone, PartialEq, Eq, Debug, ImplicitClone, Identify, Properties)]
pub struct Character {
pub id: CharacterId,
pub game_id: GameId,
pub user_id: UserId,
details: serde_json::Value,
}
*/
// impl Character {
// pub fn id(&self) -> CharacterId {
// self.id.clone()
// }
//
// pub fn user_id(&self) -> UserId {
// self.user_id.clone()
// }
//
// pub fn name(&self) -> &str {
// self.details.name()
// }
// }
//
#[autoprops]
#[function_component]
#[allow(unused)]
@@ -200,50 +200,52 @@ pub fn FullSheetView(character: Character, on_save: Callback<Character>) -> Html
#[function_component]
#[allow(unused)]
pub fn PlayerSidebarView(character: Character, on_save: Callback<Character>) -> Html {
/*
let on_save = use_callback(
(character.clone(), on_save),
move |details, (character, on_save)| {
let c = Character {
(character.clone(), on_save.clone()),
|details, (character, on_save)| {
on_save.emit(Character {
details,
..character.clone()
};
on_save.emit(c);
})
},
);
match character.details {
Sheet::Candela(ref candela) => {
html! { <candela::Sidebar character={candela.clone()} on_save={on_save} /> }
}
Sheet::Cypher(ref cypher) => {
html! { <cypher::Sidebar character={cypher.clone()} on_save={on_save} /> }
}
Sheet::Wildsea(ref cypher) => {
html! { <wildsea::Sidebar sheet={cypher.clone()} on_save={on_save} /> }
}
match System::decode(&character.system) {
Ok(System::Candela) => match CandelaSystem::decode(character.details.clone()) {
Some(sheet) => CandelaSystem::player_sidebar_view(sheet, on_save.clone()),
_ => {
html! { <div>{format!("sheet decode error")}</div> }
}
},
Ok(System::Cypher) => match CypherSystem::decode(character.details.clone()) {
Some(sheet) => CypherSystem::player_sidebar_view(sheet, on_save.clone()),
_ => {
html! { <div>{format!("sheet decode error")}</div> }
}
},
Err(err) => html! { <div>{"This character sheet is not supported."}</div> },
}
*/
html! {}
}
#[autoprops]
#[function_component]
#[allow(unused)]
pub fn GmSidebar(character: Character) -> Html {
/*
match character.details {
Sheet::Candela(ref pc) => {
html! { <candela::GmSidebar pc={pc.clone()} /> }
}
Sheet::Cypher(ref pc) => {
html! { <cypher::GmSidebar pc={pc.clone()} /> }
}
Sheet::Wildsea(ref sheet) => {
html! { <wildsea::GmSidebar sheet={sheet.clone()} /> }
}
match System::decode(&character.system) {
Ok(System::Candela) => match CandelaSystem::decode(character.details.clone()) {
Some(sheet) => CandelaSystem::gm_sidebar_view(sheet),
_ => {
html! { <div>{format!("sheet decode error")}</div> }
}
},
Ok(System::Cypher) => match CypherSystem::decode(character.details.clone()) {
Some(sheet) => CypherSystem::gm_sidebar_view(sheet),
_ => {
html! { <div>{format!("sheet decode error")}</div> }
}
},
Err(err) => html! { <div>{"This character sheet is not supported."}</div> },
}
*/
html! {}
}
#[autoprops]