1.5 KiB · text History 25c4237
use axum::http::StatusCode;
use axum::response::Html;
use tracing::error;

use crate::AppState;

pub mod areas;
pub mod auth;
pub mod lunch;
pub mod places;
pub mod restaurants;

pub use auth::{
    handle_create_invite, handle_login, handle_logout, handle_register, show_invites, show_login,
    show_profile, show_register,
};

/// Render a named template with the given context, mapping failures to a 500
/// plus a log line. Templates are data rather than code, so a typo in one only
/// surfaces here at render time — hence the logging rather than a bare `?`.
pub(crate) fn render(
    state: &AppState,
    name: &str,
    ctx: minijinja::Value,
) -> Result<Html<String>, StatusCode> {
    let template = state.env.get_template(name).map_err(|e| {
        error!(template = name, error = %e, "load template failed");
        StatusCode::INTERNAL_SERVER_ERROR
    })?;
    let body = template.render(ctx).map_err(|e| {
        error!(template = name, error = %e, "render template failed");
        StatusCode::INTERNAL_SERVER_ERROR
    })?;
    Ok(Html(body))
}

/// Log a database (or other backend) error and turn it into a 500.
pub(crate) fn internal(what: &'static str) -> impl FnOnce(sea_orm::DbErr) -> StatusCode {
    move |e| {
        error!(error = %e, "{what}");
        StatusCode::INTERNAL_SERVER_ERROR
    }
}

/// Trim a form field, treating blank as absent.
pub(crate) fn non_empty(s: Option<String>) -> Option<String> {
    s.map(|s| s.trim().to_string()).filter(|s| !s.is_empty())
}