feat(server): add error feedback to signup form
parent
4902f4d1fe
commit
5017bfb710
|
@ -195,6 +195,7 @@ async fn get_signup(State(ctx): State<Context>, headers: HeaderMap, jar: CookieJ
|
|||
Redirect::to("/").into_response()
|
||||
} else {
|
||||
View::Signup {
|
||||
username: None,
|
||||
username_available: true,
|
||||
passwords_match: true,
|
||||
}
|
||||
|
@ -207,10 +208,13 @@ async fn get_signup(State(ctx): State<Context>, headers: HeaderMap, jar: CookieJ
|
|||
async fn post_signup(
|
||||
State(ctx): State<Context>,
|
||||
jar: CookieJar,
|
||||
headers: HeaderMap,
|
||||
user_agent: Option<TypedHeader<UserAgent>>,
|
||||
Form(signup): Form<SignupForm>,
|
||||
) -> AppResult<Response> {
|
||||
if signup.validate(&ctx)?.valid() {
|
||||
let validation = signup.validate(&ctx)?;
|
||||
|
||||
if validation.valid() {
|
||||
// Create the user and log them in
|
||||
match tokio::task::spawn_blocking(move || {
|
||||
let user = ctx.store.create_user(&signup.username, &signup.password)?;
|
||||
|
@ -238,6 +242,13 @@ async fn post_signup(
|
|||
Err(err) => Err(AppError::from(err)),
|
||||
}
|
||||
} else {
|
||||
todo!("return form with error messages")
|
||||
Ok(View::Signup {
|
||||
username: Some(signup.username),
|
||||
username_available: validation.username_available,
|
||||
passwords_match: validation.passwords_match,
|
||||
}
|
||||
.page(&headers)
|
||||
.response(&ctx.tera)
|
||||
.into_response())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ pub fn initialize_tera() -> tera::Result<tera::Tera> {
|
|||
),
|
||||
(
|
||||
View::Signup {
|
||||
username: None,
|
||||
username_available: true,
|
||||
passwords_match: true,
|
||||
}
|
||||
|
|
|
@ -1,11 +1,34 @@
|
|||
<article>
|
||||
<form hx-post hx-target="#inner">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username">
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
value="{{ username }}"
|
||||
{% if not username_available %}
|
||||
aria-invalid="true"
|
||||
aria-describedby="username-helper"
|
||||
{% endif %}
|
||||
>
|
||||
{% if not username_available %}
|
||||
<small id="username-helper">Username not available</small>
|
||||
{% endif %}
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password">
|
||||
<label for="password_confirm">Confirm password:</label>
|
||||
<input type="password" id="password_confirm" name="password_confirm">
|
||||
<input
|
||||
type="password"
|
||||
id="password_confirm"
|
||||
name="password_confirm"
|
||||
{% if not passwords_match %}
|
||||
aria-invalid="true"
|
||||
aria-describedby="password-helper"
|
||||
{% endif %}
|
||||
>
|
||||
{% if not passwords_match %}
|
||||
<small id="password-helper">Passwords don't match</small>
|
||||
{% endif %}
|
||||
<input type="submit" value="Sign Up">
|
||||
</form>
|
||||
</article>
|
||||
|
|
|
@ -9,6 +9,7 @@ pub enum View {
|
|||
Sessions(Vec<gpodder::Session>, i64, Option<Query>),
|
||||
Users(Vec<gpodder::User>, i64, Option<Query>),
|
||||
Signup {
|
||||
username: Option<String>,
|
||||
username_available: bool,
|
||||
passwords_match: bool,
|
||||
},
|
||||
|
@ -67,9 +68,11 @@ impl Template for View {
|
|||
}
|
||||
}
|
||||
Self::Signup {
|
||||
username,
|
||||
username_available,
|
||||
passwords_match,
|
||||
} => {
|
||||
ctx.insert("username", &username);
|
||||
ctx.insert("username_available", &username_available);
|
||||
ctx.insert("passwords_match", &passwords_match);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue