sidebar part 1: character image, name, class, level, xp, hp

This commit is contained in:
YK committed 2025-09-12 11:44:55 +03:00
1 parent 9c211d46de
commit 37f2232af1
4 files changed
+300 -14

No files matched your search

+100 -3
View File
@@ -1,12 +1,109 @@
use crate::prelude::*;
use leptos::prelude::*;
use crate::{entities::{DashboardStoreFields, NameStoreFields, PlayerDataStoreFields}, prelude::*};
use leptos::{attr::Target, ev::{Event, Targeted}, html, logging, prelude::*};
use leptos::web_sys::HtmlInputElement;
#[component]
pub fn Sidebar () -> impl IntoView {
let state = expect_context::<Context>();
let player = state.player();
let name = player.name();
let first = name.first();
let last = name.last();
let alias = name.alias();
let name_input_class = "header-input header-input-3";
let class = player.class();
let level = player.level();
let xp = player.xp();
let hp = player.hp();
let max_hp = player.max_hp();
let temp_hp = player.temp_hp();
let image = player.image();
let adjust_level = move |adjustment: i8| level.update(|l| {
if let Some(new) = l.checked_add_signed(adjustment) {
*l = new;
}
});
let adjust_xp = move |ev: Targeted<Event, HtmlInputElement>| {
utils::adjust_checked(ev, xp);
};
let adjust_hp = move |ev: Targeted<Event, HtmlInputElement>| {
utils::adjust_checked(ev, hp);
};
let adjust_max_hp = move |ev: Targeted<Event, HtmlInputElement>| {
utils::adjust_checked(ev, max_hp);
};
let adjust_temp_hp = move |ev: Targeted<Event, HtmlInputElement>| {
utils::adjust_checked(ev, temp_hp);
};
let pc_hp = move |a: u16, b: u16| {
format!("width: {}%", utils::filled_pc(a, b).min(100.))
};
view! {
<aside>
sidebar
<Show when=move || !image.get().is_empty() >
<div class="character-image">
<img src=image.get() />
</div>
</Show>
<div class="names">
<input id="first-name" type="text" class=name_input_class bind:value=first />
<div class="alias-field">
"«"
<input id="alias" type="text" class=name_input_class bind:value=alias/>
"»"
</div>
<input id="last-name" type="text" class=name_input_class bind:value=last />
</div>
<div class="about">
<div class="class">
<input id="class" type="text" class="header-input" bind:value=class/>
</div>
<div class="level">
{move || level.get()}
<span> уровня</span>
</div>
<div class="level-adjust">
<button title="Уменьшить уровень" on:click=move |_| adjust_level(-1)>-</button>
<button title="Увеличить уровень" on:click=move |_| adjust_level( 1)>+</button>
</div>
<div class="xp">
<input id="xp" type="number" class="header-input" on:input:target=move |e| adjust_xp(e) prop:value=move || xp.get() />
<span> XP</span>
</div>
</div>
<h6>hp/оз:</h6>
<div class="hp">
<div class="perm">
<div style=move || pc_hp(hp.get(), max_hp.get()) class="bar"></div>
<div class="val">
<input title="Текущее количество хитпойнтов" id="current_hp" type="number" class="header-input" on:input:target=move |e| adjust_hp(e) prop:value=move || hp.get() />
"/"
<input title="Максимальное количество хитпойнтов" id="max_hp" type="number" class="header-input" on:input:target=move |e| adjust_max_hp(e) prop:value=move || max_hp.get() />
</div>
</div>
<div class="temp">
<div style=move || pc_hp(temp_hp.get(), 10) class="bar"></div>
<div class="val">
<input title="Временные хитпойнты" id="temp_hp" type="number" class="header-input" on:input:target=move |e| adjust_temp_hp(e) prop:value=move || temp_hp.get() />
</div>
</div>
</div>
</aside>
}
}
+25
View File
@@ -1,4 +1,8 @@
use crate::prelude::*;
use std::str::FromStr;
use leptos::ev::{ Event, Targeted };
use leptos::web_sys::HtmlInputElement;
use leptos::reactive::traits::{ Get, Set };
pub fn read_items (contents: &str, map: &mut HashMap<String, Item>) -> usize {
@@ -19,3 +23,24 @@ pub fn read_items (contents: &str, map: &mut HashMap<String, Item>) -> usize {
map.len() - start
}
pub fn adjust_checked <T, U> (ev: Targeted<Event, HtmlInputElement>, store: U) -> ()
where
U: Set<Value = T> + Get<Value = T>,
T: FromStr + ToString
{
let target = ev.target();
let val = target.value();
if let Ok(val) = val.parse::<T>() {
store.set(val);
} else {
target.set_value(&store.get().to_string());
}
}
pub fn filled_pc <T> (cur: T, max: T) -> f32 where T: Into<f32> {
let cur: f32 = cur.into();
let max: f32 = max.into();
cur / max * 100.
}