Redirection back without clearing form

This commit is contained in:
Mo 2022-10-27 18:44:40 +02:00
parent e619cea3ee
commit f8c0f42370
4 changed files with 68 additions and 24 deletions

View file

@ -6,7 +6,10 @@ use rocket_dyn_templates::Template;
#[rocket::launch] #[rocket::launch]
fn rocket() -> _ { fn rocket() -> _ {
rocket::build() rocket::build()
.mount("/", rocket::routes![routes::index, routes::submit]) .mount(
"/contact-form",
rocket::routes![routes::index, routes::submit, routes::success],
)
.manage(states::SharedCaptchaSolutions::new()) .manage(states::SharedCaptchaSolutions::new())
.attach(Template::fairing()) .attach(Template::fairing())
} }

View file

@ -1,19 +1,29 @@
use rocket::form::{Form, FromForm, Strict}; use rocket::form::{Form, FromForm, Strict};
use rocket::response::status::BadRequest; use rocket::response::status::BadRequest;
use rocket::{get, post, State}; use rocket::response::Redirect;
use rocket::{get, post, uri, State};
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use serde::Serialize; use serde::Serialize;
use std::mem;
use crate::states; use crate::states;
#[derive(Serialize)] #[derive(Serialize)]
struct FormContext { struct FormContext {
id: u16, id: u16,
name: Option<String>,
email: Option<String>,
telefon: Option<String>,
message: Option<String>,
captcha: String, captcha: String,
} }
#[get("/")] #[get("/?<name>&<email>&<telefon>&<message>")]
pub fn index( pub fn index(
name: Option<String>,
email: Option<String>,
telefon: Option<String>,
message: Option<String>,
captcha_solutions: &State<states::SharedCaptchaSolutions>, captcha_solutions: &State<states::SharedCaptchaSolutions>,
) -> Result<Template, BadRequest<()>> { ) -> Result<Template, BadRequest<()>> {
let captcha = captcha::by_name(captcha::Difficulty::Easy, captcha::CaptchaName::Lucy); let captcha = captcha::by_name(captcha::Difficulty::Easy, captcha::CaptchaName::Lucy);
@ -26,6 +36,10 @@ pub fn index(
let form_context = FormContext { let form_context = FormContext {
id, id,
name,
email,
telefon,
message,
captcha: captcha_base64, captcha: captcha_base64,
}; };
@ -44,13 +58,27 @@ pub struct ContactForm {
#[post("/submit", data = "<form>")] #[post("/submit", data = "<form>")]
pub fn submit( pub fn submit(
form: Form<Strict<ContactForm>>, mut form: Form<Strict<ContactForm>>,
captcha_solutions: &State<states::SharedCaptchaSolutions>, captcha_solutions: &State<states::SharedCaptchaSolutions>,
) -> Result<String, BadRequest<String>> { ) -> Redirect {
println!( let path_prefix = uri!("/contact-form");
"{}",
captcha_solutions.check_answer(form.id, &form.captcha_answer)
);
Ok("Ihre Anfrage wurde übermittelt. Wir melden uns bald bei Ihnen zurück.".to_string()) if !captcha_solutions.check_answer(form.id, &form.captcha_answer) {
return Redirect::to(uri!(
path_prefix,
index(
Some(mem::take(&mut form.name)),
Some(mem::take(&mut form.email)),
Some(mem::take(&mut form.telefon)),
Some(mem::take(&mut form.message)),
)
));
}
Redirect::to(uri!(path_prefix, success()))
}
#[get("/success")]
pub fn success() -> &'static str {
"Ihre Anfrage wurde übermittelt! Wir melden uns bald bei Ihnen zurück."
} }

View file

@ -35,13 +35,15 @@ impl SharedCaptchaSolutions {
} }
pub fn check_answer(&self, id: u16, answer: &str) -> bool { pub fn check_answer(&self, id: u16, answer: &str) -> bool {
let mut captcha_solutions = self.arc.lock().unwrap(); {
let mut captcha_solutions = self.arc.lock().unwrap();
let id = id as usize; let id = id as usize;
if captcha_solutions.solutions[id] == Some(answer.trim().to_string()) { if captcha_solutions.solutions[id] == Some(answer.trim().to_string()) {
captcha_solutions.solutions[id] = None; captcha_solutions.solutions[id] = None;
return true; return true;
}
} }
false false

View file

@ -4,37 +4,48 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contact form</title> <title>Contact form</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head> </head>
<body> <body>
<p>
Alternativ können Sie im unteren Formular Ihre E-Mail-Adresse (und optional Telefon-Nummer) mit einer Nachricht mit Ihrem Anliegen hinterlassen. Wir versuchen dann, Sie so früh wie möglich zu kontaktieren.
</p>
<h2>Kontakt-Formular</h2> <h2>Kontakt-Formular</h2>
<form action="/submit" method="post"> <form action="/contact-form/submit" method="post">
<input type="hidden" name="id" value="{{ id }}" required> <input type="hidden" name="id" value="{{ id }}" required>
<div class="mb-3"> <div class="mb-3">
<label for="name" class="form-label">Name</label> <label for="name" class="form-label">Name</label>
<input type="text" name="name" class="form-control" id="exampleInputEmail1" required> <input type="text" name="name" value="{{ name }}" class="form-control" id="exampleInputEmail1" required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="email" class="form-label">E-Mail</label> <label for="email" class="form-label">E-Mail</label>
<input type="email" name="email" class="form-control" id="email" required> <input type="email" name="email" value="{{ email }}" class="form-control" id="email" required>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="telefon" class="form-label">Telefon</label> <label for="telefon" class="form-label">Telefon</label>
<input type="number" name="telefon" class="form-control" id="telefon"> <input type="text" name="telefon" value="{{ telefon }}" class="form-control" id="telefon">
</div> </div>
<div class="mb-3"> <div class="mb-5">
<label for="message" class="form-label">Nachricht</label> <label for="message" class="form-label">Nachricht</label>
<input type="text" name="message" class="form-control" id="message" required> <textarea name="message" rows="5" class="form-control" id="message" style="resize: none;" required>{{ message }}</textarea>
</div>
<div class="mb-3">
<img src="data:image/png;base64,{{ captcha }}">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label for="captcha_answer" class="form-label">Code vom Bild daneben eingeben</label> <label for="captcha_answer" class="form-label">Code vom oberen Bild eingeben</label>
<input type="text" name="captcha_answer" class="form-control" id="captcha_answer" required> <input type="text" name="captcha_answer" class="form-control" id="captcha_answer" required>
</div> </div>
<button type="submit" class="btn btn-primary">Abschicken</button> <div class="d-grid">
<button type="submit" class="btn btn-primary">Abschicken</button>
</div>
</form> </form>
<img src="data:image/png;base64,{{ captcha }}"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</body> </body>
</html> </html>