Skip to content

Commit 69b8579

Browse files
committed
fixed load time unit mismatch
1 parent 2ffe0ed commit 69b8579

File tree

3 files changed

+79
-6
lines changed

3 files changed

+79
-6
lines changed

crates/web/src/pages/create_dosage.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,9 @@ fn dosage_editor_page(schedule_only: bool) -> impl IntoView {
451451

452452
if let Some(next_value) = converted {
453453
estrogen_dose.set(if target_iu_mode {
454-
fmt(next_value, 0)
454+
format!("{next_value:.0}")
455455
} else {
456-
fmt(next_value, 3)
456+
format!("{next_value:.3}")
457457
});
458458
estrogen_dose_in_iu.set(target_iu_mode);
459459
} else if target_iu_mode {
@@ -505,6 +505,9 @@ fn dosage_editor_page(schedule_only: bool) -> impl IntoView {
505505
if initialized.get() {
506506
return;
507507
}
508+
if store.is_loading.get() {
509+
return;
510+
}
508511
let data = store.data.get();
509512
if let Some(inj) = data.injectableEstradiol.as_ref() {
510513
estrogen_method.set("injection".to_string());

crates/web/src/store.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ impl AppStore {
4141
let is_dirty = self.is_dirty;
4242
let last_error = self.last_error;
4343
let api_base = api_base();
44+
is_loading.set(true);
45+
last_error.set(None);
4446
spawn_local(async move {
45-
is_loading.set(true);
46-
last_error.set(None);
4747
let resp = Request::get(&format!("{}/api/data", api_base)).send().await;
4848
match resp {
4949
Ok(resp) => match resp.json::<HrtData>().await {

crates/web/src/utils.rs

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,64 @@ pub fn parse_decimal(value: &str) -> Option<f64> {
4949
if trimmed.is_empty() {
5050
return None;
5151
}
52-
let normalized = trimmed.replace(',', ".");
53-
normalized.parse::<f64>().ok().filter(|v| v.is_finite())
52+
let normalized = trimmed
53+
.replace('\u{00a0}', "")
54+
.replace('\u{202f}', "")
55+
.replace('\u{2009}', "")
56+
.replace(' ', "")
57+
.replace('_', "")
58+
.replace('\'', "");
59+
if normalized.is_empty() {
60+
return None;
61+
}
62+
63+
let parse = |raw: String| raw.parse::<f64>().ok().filter(|v| v.is_finite());
64+
65+
let comma_count = normalized.matches(',').count();
66+
let dot_count = normalized.matches('.').count();
67+
68+
if comma_count > 0 && dot_count > 0 {
69+
let last_comma = normalized.rfind(',').unwrap_or(0);
70+
let last_dot = normalized.rfind('.').unwrap_or(0);
71+
if last_comma > last_dot {
72+
// 1.234,56 -> 1234.56
73+
return parse(normalized.replace('.', "").replace(',', "."));
74+
}
75+
// 1,234.56 -> 1234.56
76+
return parse(normalized.replace(',', ""));
77+
}
78+
79+
if comma_count > 0 {
80+
if comma_count > 1 {
81+
// 1,234,567 -> 1234567
82+
return parse(normalized.replace(',', ""));
83+
}
84+
let split_idx = normalized.find(',').unwrap_or(0);
85+
let int_part = &normalized[..split_idx];
86+
let frac_part = &normalized[split_idx + 1..];
87+
let int_digits = int_part.trim_start_matches(['+', '-']);
88+
let grouped_thousands = frac_part.len() == 3
89+
&& frac_part.chars().all(|ch| ch.is_ascii_digit())
90+
&& !int_digits.is_empty()
91+
&& int_digits != "0"
92+
&& !int_digits.starts_with('0')
93+
&& int_part
94+
.chars()
95+
.all(|ch| ch.is_ascii_digit() || ch == '+' || ch == '-');
96+
if grouped_thousands {
97+
// 1,000 -> 1000
98+
return parse(normalized.replace(',', ""));
99+
}
100+
// 1,25 -> 1.25
101+
return parse(normalized.replace(',', "."));
102+
}
103+
104+
if dot_count > 1 {
105+
// 1.234.567 -> 1234567
106+
return parse(normalized.replace('.', ""));
107+
}
108+
109+
parse(normalized)
54110
}
55111

56112
pub fn parse_decimal_or_nan(value: &str) -> f64 {
@@ -274,6 +330,20 @@ mod tests {
274330
assert_eq!(parse_decimal("0,2"), Some(0.2));
275331
assert_eq!(parse_decimal(" 1.25 "), Some(1.25));
276332
assert_eq!(parse_decimal(" 1,25 "), Some(1.25));
333+
assert_eq!(parse_decimal("1.000"), Some(1.0));
334+
assert_eq!(parse_decimal("0.125"), Some(0.125));
335+
assert_eq!(parse_decimal("0,125"), Some(0.125));
336+
}
337+
338+
#[test]
339+
fn parse_decimal_accepts_grouped_thousands_inputs() {
340+
assert_eq!(parse_decimal("1,000"), Some(1000.0));
341+
assert_eq!(parse_decimal("12,345"), Some(12345.0));
342+
assert_eq!(parse_decimal("1,234.5"), Some(1234.5));
343+
assert_eq!(parse_decimal("1.234,5"), Some(1234.5));
344+
assert_eq!(parse_decimal("1.234.567"), Some(1234567.0));
345+
assert_eq!(parse_decimal("1 234,5"), Some(1234.5));
346+
assert_eq!(parse_decimal("1'234,5"), Some(1234.5));
277347
}
278348

279349
#[test]

0 commit comments

Comments
 (0)