use actix_web::{HttpRequest, Result as AwResult, get, web};
use super::render_layout;
use super::session_auth::get_username_from_request;
use crate::auth::{Exercise, ExerciseLog, Goal, HodisContext};
#[allow(clippy::too_many_arguments)]
pub fn render_dashboard_content(
_user_id: &str,
exercises: &[Exercise],
goal: &Option<Goal>,
total_points: f64,
user_points: f64,
recent_logs: &[ExerciseLog],
favorite_ids: &[String],
success_msg: Option<&str>,
) -> maud::Markup {
maud::html! {
@if let Some(msg) = success_msg {
div class="ba b--green br2 pa3 bg-washed-green mb3" {
p class="f6 dark-green ma0" { (msg) }
}
}
@if let Some(g) = goal {
div class="ba b--black-20 br2 pa3 mb4" {
h2 class="f4 fw6 mb2" style="color: #e3001a;" { (g.name) }
div class="w-100 bg-light-gray br2 mb2" style="height: 16px;" {
@let pct = if g.target_points > 0.0 { (total_points / g.target_points * 100.0).min(100.0) } else { 0.0 };
div class="bg-brand br2" style=(format!("width: {:.1}%; height: 16px; transition: width 0.3s ease;", pct)) {}
}
div class="flex justify-between" {
span class="f6 black-60" { (format!("{:.1} / {:.0} Punkte", total_points, g.target_points)) }
span class="f6 fw6" { (format!("{:.1}%", pct)) }
}
}
}
div class="mb4" {
div class="flex justify-between items-center mb2" {
h2 class="f4 fw6 black-70 ma0" { "Dein Beitrag" }
span class="f6 fw6 brand" { (format!("{:.1} Pkt", user_points)) }
}
}
div class="mb4" {
h2 class="f4 fw6 mb2 black-70" { "Log" }
@if exercises.is_empty() {
div class="ba b--black-20 br2 pa3 tc" {
p class="f6 black-50" { "Noch keine Übungen verfügbar. Bitte einen Admin, welche hinzuzufügen!" }
}
} @else {
form hx-post="/log-exercise" hx-target="#dashboard-content" hx-swap="outerHTML" class="ba b--black-20 br2 pa3" {
div class="mb3" {
label class="db f6 black-70 mb1" for="exercise" { "Übung" }
select name="exercise_id" id="exercise" required class="db w-100 pa2 ba b--black-30 br1" {
@for ex in exercises {
option value=(ex.id) { (ex.name) " (" (format!("{:.1} Pkt/{}", ex.points_per_unit, ex.unit)) ")" }
}
}
}
div class="flex mb3" {
div class="flex-auto mr2" {
label class="db f6 black-70 mb1" for="amount" { "Menge" }
input type="number" name="amount" id="amount" required step="0.1" min="0.1" class="db w-100 pa2 ba b--black-30 br1" placeholder="z.B. 5";
}
}
button type="submit" class="w-100 pa2 btn-brand br1 f5 fw6" { "Log" }
}
}
}
@if !exercises.is_empty() {
div class="mb4" {
h2 class="f4 fw6 mb2 black-70" { "Schnelleingabe" }
div class="flex flex-wrap" style="gap: 0.5rem;" {
@for ex in exercises {
@let is_fav = favorite_ids.contains(&ex.id);
form hx-post="/toggle-favorite" hx-target="#dashboard-content" hx-swap="outerHTML" class="dib ma0" style="display:inline;" {
input type="hidden" name="exercise_id" value=(ex.id);
button
type="submit"
class={"pa2 br1 f6 pointer " @if is_fav { "btn-brand" } @else { "btn-outline" }}
style={"display: inline-block; margin-right: 0.25rem; margin-bottom: 0.25rem;"}
{
@if is_fav { "★ " } @else { "☆ " }
(ex.name)
}
}
}
}
}
}
@if !recent_logs.is_empty() {
div class="mb4" {
h2 class="f4 fw6 mb2 black-70" { "Letzte Aktivitäten" }
div class="ba b--black-20 br2 overflow-hidden" {
@for log in recent_logs.iter().take(10) {
div class="flex pa2 bb b--black-10 items-center" {
div class="flex-auto" {
span class="f6 fw5" { (log.amount) }
@if let Some(ex) = exercises.iter().find(|e| e.id == log.exercise_id) {
span class="f6 black-60 ml1" { (ex.unit) " " (ex.name) }
}
}
span class="f6 brand fw5 mr2" { (format!("+{:.1} Pkt", log.points_earned)) }
span class="f7 black-30" { (log.created_at.split('T').next().unwrap_or("")) }
form hx-post="/delete-log" hx-target="#dashboard-content" hx-swap="outerHTML" class="dib ma0" style="display:inline;" {
input type="hidden" name="id" value=(log.id);
button type="submit" class="f7 red bn bg-transparent pointer underline dim ml1" { "entfernen" }
}
}
}
}
}
}
}
}
#[get("/")]
pub async fn index(
req: HttpRequest,
auth_state: web::Data<HodisContext>,
) -> AwResult<maud::Markup> {
let username = get_username_from_request(&req, &auth_state).await;
if username.is_none() {
let content = maud::html! {
div class="flex flex-column items-center justify-center" style="min-height: calc(100vh - 8rem); padding: 2rem 1rem;" {
div class="w-100 mw6 tc" {
h1 class="f2 fw6 mb3" style="color: #e3001a;" { "Hodis" }
h2 class="f4 fw3 black-60 mb4" { "Preseason-Challenge" }
p class="f6 black-50 mb4" {
"Erfasse deine Fitness-Aktivitäten und trage zu einem gemeinsamen Teamziel bei."
}
div class="flex justify-center" style="gap: 1rem;" {
a href="/auth/login" class="pa2 btn-brand br1 f5 fw6 no-underline" style="display:inline-block; min-width: 100px;" { "Anmelden" }
a href="/auth/signup" class="pa2 btn-outline br1 f5 fw6 no-underline" style="display:inline-block; min-width: 100px;" { "Registrieren" }
}
}
}
};
return Ok(render_layout(&content, None, false));
}
let user = match auth_state
.db()
.get_user_by_username(username.as_ref().unwrap())
.await
{
Ok(Some(u)) => u,
_ => {
let content = maud::html! {
p class="black-50" { "Fehler beim Laden der Nutzerdaten" }
};
return Ok(render_layout(&content, username.as_deref(), false));
}
};
let exercises = auth_state
.db()
.get_all_exercises()
.await
.unwrap_or_default();
let goal = auth_state.db().get_active_goal().await.unwrap_or_default();
let total_points = auth_state.db().get_total_points().await.unwrap_or(0.0);
let user_points = auth_state
.db()
.get_points_for_user(&user.id)
.await
.unwrap_or(0.0);
let recent_logs = auth_state
.db()
.get_exercise_logs_for_user(&user.id)
.await
.unwrap_or_default();
let favorite_ids = auth_state
.db()
.get_favorite_exercise_ids(&user.id)
.await
.unwrap_or_default();
let is_admin = user.is_admin;
let dashboard = render_dashboard_content(
&user.id,
&exercises,
&goal,
total_points,
user_points,
&recent_logs,
&favorite_ids,
None,
);
if req.headers().get("HX-Request").is_some() {
Ok(maud::html! {
div id="dashboard-content" hx-target="this" hx-swap="outerHTML" {
(dashboard)
}
})
} else {
let content = maud::html! {
div id="dashboard-content" hx-target="this" hx-swap="outerHTML" {
(dashboard)
}
};
Ok(render_layout(&content, username.as_deref(), is_admin))
}
}