540871a8cdc2c7df89bd3c0f5eb39387359db062 / frogue / src / views / accounts.rs
Raw
// SPDX-FileCopyrightText: 2026 Ololduck <ololduck@vit.am> and contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
use actix_web::HttpResponse;
use maud::{Markup, Render, html};
use super::components::{Complaint, PasswordField, TextField};
use super::{Page, ViewCtx};
/// What the registration form shows when it is (re)rendered: the values to
/// put back in the fields, and any complaint about the last attempt.
pub struct RegisterForm {
pub name: Option<String>,
pub email: Option<String>,
pub invite: Option<String>,
pub error: Option<String>,
}
pub(super) struct RegisterBody<'a> {
form: &'a RegisterForm,
}
impl Render for RegisterBody<'_> {
fn render(&self) -> Markup {
html! {
h2 { "Register" }
(Complaint(self.form.error.as_deref()))
form method="post" action="/register" {
@if let Some(invite) = &self.form.invite {
input type="hidden" name="invite" value=(invite) {}
}
(TextField {
label: Some("Name"),
name: "name",
input_type: "text",
value: self.form.name.as_deref(),
required: true,
maxlength: u32::MAX,
})
(TextField {
label: Some("Email"),
name: "email",
input_type: "email",
value: self.form.email.as_deref(),
required: true,
maxlength: u32::MAX,
})
(PasswordField {
label: "Password",
name: "password",
required: true,
})
button type="submit" { "Register" }
}
}
}
}
/// A complaint shown in place of the registration form.
pub(super) struct RegisterClosedBody<'a> {
message: &'a str,
}
impl Render for RegisterClosedBody<'_> {
fn render(&self) -> Markup {
html! {
h2 { "Register" }
(Complaint(Some(self.message)))
}
}
}
/// What the login form shows when it is (re)rendered.
pub struct LoginForm {
pub name: Option<String>,
pub error: Option<String>,
}
pub(super) struct LoginBody<'a> {
form: &'a LoginForm,
}
impl Render for LoginBody<'_> {
fn render(&self) -> Markup {
html! {
h2 { "Log in" }
(Complaint(self.form.error.as_deref()))
form method="post" action="/login" {
(TextField {
label: Some("Name"),
name: "name",
input_type: "text",
value: self.form.name.as_deref(),
required: true,
maxlength: u32::MAX,
})
(PasswordField {
label: "Password",
name: "password",
required: true,
})
button type="submit" { "Log in" }
}
}
}
}
/// The registration page, showing `form`'s values and complaint.
pub fn register(viewer: Option<&str>, form: &RegisterForm) -> HttpResponse {
Page {
title: "Frogue - Register".to_string(),
ctx: ViewCtx::from_viewer(viewer),
extra_head: None,
body: RegisterBody { form },
}
.into_response()
}
/// The login page, showing `form`'s values and complaint.
pub fn login(viewer: Option<&str>, form: &LoginForm) -> HttpResponse {
Page {
title: "Frogue - Log in".to_string(),
ctx: ViewCtx::from_viewer(viewer),
extra_head: None,
body: LoginBody { form },
}
.into_response()
}
/// The registration page, showing `message` instead of the form (for closed
/// mode).
pub fn register_closed(viewer: Option<&str>, message: &str) -> HttpResponse {
Page {
title: "Frogue - Register".to_string(),
ctx: ViewCtx::from_viewer(viewer),
extra_head: None,
body: RegisterClosedBody { message },
}
.into_response()
}