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()
|
Redirect::to("/").into_response()
|
||||||
} else {
|
} else {
|
||||||
View::Signup {
|
View::Signup {
|
||||||
|
username: None,
|
||||||
username_available: true,
|
username_available: true,
|
||||||
passwords_match: true,
|
passwords_match: true,
|
||||||
}
|
}
|
||||||
|
@ -207,10 +208,13 @@ async fn get_signup(State(ctx): State<Context>, headers: HeaderMap, jar: CookieJ
|
||||||
async fn post_signup(
|
async fn post_signup(
|
||||||
State(ctx): State<Context>,
|
State(ctx): State<Context>,
|
||||||
jar: CookieJar,
|
jar: CookieJar,
|
||||||
|
headers: HeaderMap,
|
||||||
user_agent: Option<TypedHeader<UserAgent>>,
|
user_agent: Option<TypedHeader<UserAgent>>,
|
||||||
Form(signup): Form<SignupForm>,
|
Form(signup): Form<SignupForm>,
|
||||||
) -> AppResult<Response> {
|
) -> AppResult<Response> {
|
||||||
if signup.validate(&ctx)?.valid() {
|
let validation = signup.validate(&ctx)?;
|
||||||
|
|
||||||
|
if validation.valid() {
|
||||||
// Create the user and log them in
|
// Create the user and log them in
|
||||||
match tokio::task::spawn_blocking(move || {
|
match tokio::task::spawn_blocking(move || {
|
||||||
let user = ctx.store.create_user(&signup.username, &signup.password)?;
|
let user = ctx.store.create_user(&signup.username, &signup.password)?;
|
||||||
|
@ -238,6 +242,13 @@ async fn post_signup(
|
||||||
Err(err) => Err(AppError::from(err)),
|
Err(err) => Err(AppError::from(err)),
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
View::Signup {
|
||||||
|
username: None,
|
||||||
username_available: true,
|
username_available: true,
|
||||||
passwords_match: true,
|
passwords_match: true,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,34 @@
|
||||||
<article>
|
<article>
|
||||||
<form hx-post hx-target="#inner">
|
<form hx-post hx-target="#inner">
|
||||||
<label for="username">Username:</label>
|
<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>
|
<label for="password">Password:</label>
|
||||||
<input type="password" id="password" name="password">
|
<input type="password" id="password" name="password">
|
||||||
<label for="password_confirm">Confirm password:</label>
|
<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">
|
<input type="submit" value="Sign Up">
|
||||||
</form>
|
</form>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub enum View {
|
||||||
Sessions(Vec<gpodder::Session>, i64, Option<Query>),
|
Sessions(Vec<gpodder::Session>, i64, Option<Query>),
|
||||||
Users(Vec<gpodder::User>, i64, Option<Query>),
|
Users(Vec<gpodder::User>, i64, Option<Query>),
|
||||||
Signup {
|
Signup {
|
||||||
|
username: Option<String>,
|
||||||
username_available: bool,
|
username_available: bool,
|
||||||
passwords_match: bool,
|
passwords_match: bool,
|
||||||
},
|
},
|
||||||
|
@ -67,9 +68,11 @@ impl Template for View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Signup {
|
Self::Signup {
|
||||||
|
username,
|
||||||
username_available,
|
username_available,
|
||||||
passwords_match,
|
passwords_match,
|
||||||
} => {
|
} => {
|
||||||
|
ctx.insert("username", &username);
|
||||||
ctx.insert("username_available", &username_available);
|
ctx.insert("username_available", &username_available);
|
||||||
ctx.insert("passwords_match", &passwords_match);
|
ctx.insert("passwords_match", &passwords_match);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue