Skip to content

Commit 9b1245e

Browse files
author
Livia Zaharia
committed
UI fixes
1 parent d654f6f commit 9b1245e

File tree

11 files changed

+876
-39
lines changed

11 files changed

+876
-39
lines changed

assets/flags/de.svg

Lines changed: 6 additions & 0 deletions
Loading

assets/flags/gb.svg

Lines changed: 21 additions & 0 deletions
Loading

assets/flags/ua.svg

Lines changed: 5 additions & 0 deletions
Loading

assets/lang.css

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
.lang-picker {
2+
display: flex;
3+
gap: 8px;
4+
justify-content: flex-end;
5+
margin-bottom: 12px;
6+
align-items: flex-start;
7+
}
8+
9+
.lang-btn {
10+
display: inline-flex;
11+
flex-direction: column;
12+
align-items: center;
13+
justify-content: flex-start;
14+
gap: 4px;
15+
width: 42px;
16+
padding: 4px 4px 6px 4px;
17+
border-radius: 12px;
18+
border: 1px solid rgba(15, 23, 42, 0.16);
19+
background: transparent;
20+
cursor: pointer;
21+
box-shadow: none;
22+
}
23+
24+
.lang-btn.active {
25+
border: 1px solid rgba(29, 78, 216, 0.85);
26+
box-shadow: 0 4px 10px rgba(29, 78, 216, 0.20);
27+
}
28+
29+
.lang-flag {
30+
width: 30px;
31+
height: 20px;
32+
object-fit: cover;
33+
display: block;
34+
border-radius: 8px;
35+
border: 1px solid rgba(15, 23, 42, 0.12);
36+
background: #ffffff;
37+
}
38+
39+
.lang-label {
40+
font-size: 10px;
41+
font-weight: 800;
42+
letter-spacing: 0.08em;
43+
color: #0f172a;
44+
line-height: 1;
45+
opacity: 0;
46+
transform: translateY(-2px);
47+
transition: opacity 120ms ease-in-out, transform 120ms ease-in-out;
48+
pointer-events: none;
49+
}
50+
51+
.lang-btn:hover .lang-label,
52+
.lang-btn.active .lang-label {
53+
opacity: 1;
54+
transform: translateY(0);
55+
}
56+

logs/sugar_sugar.json

Lines changed: 724 additions & 0 deletions
Large diffs are not rendered by default.

sugar_sugar/app.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ def get_random_data_window(full_df: pl.DataFrame, points: int) -> Tuple[pl.DataF
128128

129129
app = dash.Dash(__name__,
130130
external_stylesheets=external_stylesheets,
131+
assets_folder=str(project_root / 'assets'),
131132
suppress_callback_exceptions=True
132133
)
133134
app.title = "Sugar Sugar - Glucose Prediction Game"
@@ -441,6 +442,22 @@ def create_ending_layout(
441442
if len(prediction_table_data) >= 2: # Need at least actual and predicted rows
442443
stored_metrics = metrics_component_ending._calculate_metrics_from_table_data(prediction_table_data)
443444

445+
def _translate_metric_label(metric: str) -> str:
446+
mapping: dict[str, str] = {
447+
"Actual Glucose": t("ui.table.actual_glucose", locale=locale),
448+
"Predicted": t("ui.table.predicted", locale=locale),
449+
"Absolute Error": t("ui.table.absolute_error", locale=locale),
450+
"Relative Error (%)": t("ui.table.relative_error_pct", locale=locale, pct="%"),
451+
}
452+
return mapping.get(metric, metric)
453+
454+
prediction_table_data_display: list[dict[str, str]] = []
455+
for row in prediction_table_data:
456+
metric_val = str(row.get("metric", ""))
457+
new_row = dict(row)
458+
new_row["metric"] = _translate_metric_label(metric_val)
459+
prediction_table_data_display.append(new_row)
460+
444461
# Create metrics display directly
445462
metrics_display = MetricsComponent.create_ending_metrics_display(stored_metrics, locale=locale) if stored_metrics else [
446463
html.H3(t("ui.metrics.title_accuracy_metrics", locale=locale), style={'textAlign': 'center'}),
@@ -516,8 +533,8 @@ def create_ending_layout(
516533
}),
517534
# Create prediction table directly from stored data
518535
dash_table.DataTable(
519-
data=prediction_table_data,
520-
columns=[{'name': 'Metric', 'id': 'metric'}] + [
536+
data=prediction_table_data_display,
537+
columns=[{'name': t("ui.table.metric_header", locale=locale), 'id': 'metric'}] + [
521538
{'name': f'T{i}', 'id': f't{i}', 'type': 'text'}
522539
for i in range(len(prediction_table_data[0]) - 1) if prediction_table_data
523540
],

sugar_sugar/components/landing.py

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,51 +38,37 @@ def __init__(self, *, locale: str = "en") -> None:
3838
language_picker = html.Div(
3939
[
4040
html.Button(
41-
"🇬🇧",
41+
[
42+
html.Img(src="/assets/flags/gb.svg", className="lang-flag"),
43+
html.Span("EN", className="lang-label"),
44+
],
4245
id="lang-en",
43-
title=t("ui.language.en", locale=locale),
44-
style={
45-
"border": "1px solid rgba(15, 23, 42, 0.20)",
46-
"background": "white",
47-
"borderRadius": "10px",
48-
"padding": "6px 10px",
49-
"fontSize": "18px",
50-
"cursor": "pointer",
51-
},
46+
title="EN",
47+
**{"aria-label": "EN"},
48+
className="lang-btn" + (" active" if locale == "en" else ""),
5249
),
5350
html.Button(
54-
"🇩🇪",
51+
[
52+
html.Img(src="/assets/flags/de.svg", className="lang-flag"),
53+
html.Span("DE", className="lang-label"),
54+
],
5555
id="lang-de",
56-
title=t("ui.language.de", locale=locale),
57-
style={
58-
"border": "1px solid rgba(15, 23, 42, 0.20)",
59-
"background": "white",
60-
"borderRadius": "10px",
61-
"padding": "6px 10px",
62-
"fontSize": "18px",
63-
"cursor": "pointer",
64-
},
56+
title="DE",
57+
**{"aria-label": "DE"},
58+
className="lang-btn" + (" active" if locale == "de" else ""),
6559
),
6660
html.Button(
67-
"🇺🇦",
61+
[
62+
html.Img(src="/assets/flags/ua.svg", className="lang-flag"),
63+
html.Span("UA", className="lang-label"),
64+
],
6865
id="lang-uk",
69-
title=t("ui.language.uk", locale=locale),
70-
style={
71-
"border": "1px solid rgba(15, 23, 42, 0.20)",
72-
"background": "white",
73-
"borderRadius": "10px",
74-
"padding": "6px 10px",
75-
"fontSize": "18px",
76-
"cursor": "pointer",
77-
},
66+
title="UA",
67+
**{"aria-label": "UA"},
68+
className="lang-btn" + (" active" if locale == "uk" else ""),
7869
),
7970
],
80-
style={
81-
"display": "flex",
82-
"gap": "8px",
83-
"justifyContent": "flex-end",
84-
"marginBottom": "12px",
85-
},
71+
className="lang-picker",
8672
)
8773

8874
hero = dbc.Row(

sugar_sugar/i18n.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ def setup_i18n(*, extra_load_paths: Optional[Iterable[Path]] = None) -> None:
4040
i18n.load_path.append(sp)
4141

4242
# Load and cache all translations upfront.
43-
i18n.load_everything()
43+
# Using reload ensures changes to translation files are picked up on process start.
44+
i18n.reload_everything()
4445

4546

4647
def t(key: str, *, locale: Optional[str] = None, **kwargs: object) -> str:

sugar_sugar/translations/ui.de.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ de:
120120
rmse: "Ähnlich wie MAE, bestraft große Fehler stärker"
121121
mape: "Durchschnittliche prozentuale Abweichung vom Messwert"
122122

123+
table:
124+
metric_header: "Metrik"
125+
actual_glucose: "Gemessene Glukose"
126+
predicted: "Vorhersage"
127+
absolute_error: "Absoluter Fehler"
128+
relative_error_pct: "Relativer Fehler (%{pct})"
129+
123130
session_expired:
124131
title: "Sitzung abgelaufen"
125132
text: "Bitte von vorne beginnen."

sugar_sugar/translations/ui.en.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ en:
120120
rmse: "Similar to MAE but penalizes large errors more"
121121
mape: "Average percentage difference from actual values"
122122

123+
table:
124+
metric_header: "Metric"
125+
actual_glucose: "Actual Glucose"
126+
predicted: "Predicted"
127+
absolute_error: "Absolute Error"
128+
relative_error_pct: "Relative Error (%{pct})"
129+
123130
session_expired:
124131
title: "Session Expired"
125132
text: "Please start over from the beginning."

0 commit comments

Comments
 (0)