diff options
author | Vincent Ambo <mail@tazj.in> | 2023-06-02T20·43+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2023-06-06T11·43+0000 |
commit | 6fa6f3a7f4a72a74ce495609646d2dae3789cde3 (patch) | |
tree | b5a673931267da0ad6682f0d9ae05567dba5cc58 /corp/rih/src | |
parent | 20a671036586088578952f4958440f246decb06e (diff) |
feat(corp/rih): submit form data to backend r/6236
Change-Id: I0c74deea8debf9acbcf6eabf225969dbfe9cc34c Reviewed-on: https://cl.tvl.fyi/c/depot/+/8703 Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'corp/rih/src')
-rw-r--r-- | corp/rih/src/home.html | 9 | ||||
-rw-r--r-- | corp/rih/src/main.rs | 66 |
2 files changed, 72 insertions, 3 deletions
diff --git a/corp/rih/src/home.html b/corp/rih/src/home.html index df77ee1e8820..697daf5148f3 100644 --- a/corp/rih/src/home.html +++ b/corp/rih/src/home.html @@ -99,6 +99,7 @@ html! { <p>{"Let's get started with you telling us a bit about what kind of job you would like!"}</p> </div> + if !self.submitted { <div class="mx-auto col-6 border rounded-3 shadow"> <form class="m-3"> @@ -172,12 +173,18 @@ html! { <div id="captcha-container" class="smart-captcha mb-3" style="height: 100px" /> <button type="submit" class="btn btn-primary" - disabled={!(self.record.is_complete() && self.captcha_token.is_some())}> + disabled={!(self.record.is_complete() && self.captcha_token.is_some())} + onclick={link.callback(|_| Msg::Submit)}> {"Submit"} </button> <p class="pt-2"><i>{"This page is still under construction! Please reach out at contact@ if you have any questions."}</i></p> </form> </div> + } else { + <div class="mx-auto col-6 border rounded-3 shadow"> + <p>{"Thank you for submitting your data! We will reach out to confirm your email address, and further if any matches are found. You can contact us at contact@russiaishiring.com with any questions you might have."}</p> + </div> + } </div> </div> diff --git a/corp/rih/src/main.rs b/corp/rih/src/main.rs index 02cb350d1acb..9b7e38422ac2 100644 --- a/corp/rih/src/main.rs +++ b/corp/rih/src/main.rs @@ -2,7 +2,9 @@ use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::FuzzyMatcher; use gloo::console; use gloo::history::{BrowserHistory, History}; +use gloo::net::http; use gloo::storage::{LocalStorage, Storage}; +use gloo::utils::format::JsValueSerdeExt; use rand::seq::IteratorRandom; use rand::thread_rng; use serde::{Deserialize, Serialize}; @@ -24,6 +26,13 @@ const CAPTCHA_KEY: &'static str = "ysc1_K7iOi3FSmsyO8pZGu8Im2iQClCtPsVx7jSRyhyCV #[cfg(not(debug_assertions))] const CAPTCHA_KEY: &'static str = "ysc1_a3LVlaDRDMwU8CLSZ0WKENTI2exyOxz5J2c6x28P5339d410"; +// Form data is submitted to different endpoints in dev/prod. +#[cfg(debug_assertions)] +const SUBMIT_URL: &'static str = "http://localhost:9090/submit"; + +#[cfg(not(debug_assertions))] +const SUBMIT_URL: &'static str = "https://api.russiaishiring.com/submit"; + /// This code ends up being compiled for the native and for the /// webassembly architectures during the build & test process. /// However, the `rust_iso3166` crate exposes a different API (!) @@ -83,7 +92,7 @@ enum Route { /// Represents a single record as filled in by a user. This is the /// primary data structure we want to populate and persist somewhere. -#[derive(Default, Debug, Deserialize, Serialize)] +#[derive(Clone, Default, Debug, Deserialize, Serialize)] struct Record { // Personal information name: String, @@ -127,6 +136,9 @@ struct App { // Captcha callback closure which needs to be kept alive for the // lifecycle of the app. captcha_callback: Closure<dyn FnMut(String)>, + + // Has data been submitted already by this user? + submitted: bool, } #[derive(Clone, Debug)] @@ -146,7 +158,9 @@ enum Msg { SetPosition(String), SetJobDetails(String), SetWorkBackground(String), + CaptchaSolved(String), + Submit, } /// Callback handler for adding a technology. @@ -306,6 +320,42 @@ fn render_technologies(link: &Scope<App>, technologies: &BTreeSet<String>) -> Ht } } +/// Submit the collected data to the backend service. +async fn submit_data(captcha_token: &str, record: &Record) -> bool { + let response = http::Request::get(SUBMIT_URL) + .method(http::Method::POST) + .json(&serde_json::json!({ + "captcha_token": captcha_token, + "record": record, + })) + .expect("serialising a serde_json::Value can not fail") + .send() + .await + .unwrap(); + + // currently there is nothing we can actually do with the response + // here, but we should add some way to communicate back some + // server errors etc., even if the whole thing should be as + // forgiving as possible. + response.ok() +} + +/// Handle the submit event, if all data was successfully collected. +fn handle_submit(app: &App, link: Scope<App>) -> Msg { + let token = app.captcha_token.as_ref().unwrap().clone(); + let record = app.record.clone(); + + wasm_bindgen_futures::spawn_local(async move { + if !submit_data(&token, &record).await { + console::warn!("failed to submit data for some reason"); + } else { + console::log!("submitted data successfully"); + } + }); + + Msg::NoOp +} + impl Component for App { type Message = Msg; type Properties = (); @@ -323,10 +373,11 @@ impl Component for App { link.send_message(Msg::CaptchaSolved(val)); })) }, + submitted: false, } } - fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool { + fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool { console::log!("handling ", format!("{:?}", msg)); let (state_change, view_change) = match msg { Msg::NoOp => (false, false), @@ -397,6 +448,17 @@ impl Component for App { self.captcha_token = Some(token); (false, true) } + + Msg::Submit => { + if self.record.is_complete() && self.captcha_token.is_some() { + self.submitted = true; + handle_submit(self, ctx.link().clone()); + (false, true) + } else { + console::warn!("submitted data, but form or captcha was not ready"); + (false, false) + } + } }; if state_change { |