From 23f132c5c1b90e2495d68e86596ae82259664da3 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Tue, 28 Jan 2025 15:11:43 -0600 Subject: [PATCH] adding more mission trip info and making the contact form work again --- content/_index.md | 3 +- content/contact.md | 6 +- content/ministries/mission-trip/_index.md | 2 +- layouts/shortcodes/contact-form.html | 2 +- src/api/contact.rs | 169 ++++++++++++++++++++++ src/api/mod.rs | 1 + 6 files changed, 177 insertions(+), 6 deletions(-) create mode 100644 src/api/contact.rs diff --git a/content/_index.md b/content/_index.md index 534a486..6019d52 100644 --- a/content/_index.md +++ b/content/_index.md @@ -31,7 +31,6 @@ Teens For Christ Connection (TFC) is a rural ministry reaching out to the missio -
@@ -54,6 +53,8 @@ Fill out now! > If you need to fill out a health form, please do so [here](/health-form). Also here you can fill out the [parent](/mt-parent-form), [teacher](/mt-teacher-form), [church-related](/mt-church-form) reference forms. +{{< pt src="https://videos.tfcconnection.org/videos/embed/aa14bf70-adc8-4efd-b15b-37c59b31f418" >}} + ## Our Vision Our vision is to change the world from the heart of America by providing disciple making opportunities that serve communities where student ministries are limited. diff --git a/content/contact.md b/content/contact.md index 90263e1..6e85650 100644 --- a/content/contact.md +++ b/content/contact.md @@ -9,8 +9,8 @@ sharingLinks: false --- -Right now our contact form is broken, you can email any of the staff by using their first name followed by @tfcconnection.org. Sorry for the inconvenience. + - +We would love to get into contact with you! Just put in your name, a message and your email address and we will get right back to you! You can also email a specific staff member here if you'd like to make sure the message gets directly to them! If you don't know who to email, just leave it blank! - +{{< contact-form >}} diff --git a/content/ministries/mission-trip/_index.md b/content/ministries/mission-trip/_index.md index 05c3fce..90b3d02 100644 --- a/content/ministries/mission-trip/_index.md +++ b/content/ministries/mission-trip/_index.md @@ -20,6 +20,6 @@ Our desire to see teenagers develop a heart for missions was the main force behi ## -{{< pt src="https://videos.tfcconnection.org/videos/embed/c92fc5dd-ebfd-4d13-b486-d08d281868f2" >}} +{{< pt src="https://videos.tfcconnection.org/videos/embed/aa14bf70-adc8-4efd-b15b-37c59b31f418" >}} {{< spacing >}} diff --git a/layouts/shortcodes/contact-form.html b/layouts/shortcodes/contact-form.html index fab3fde..6b8c0b0 100644 --- a/layouts/shortcodes/contact-form.html +++ b/layouts/shortcodes/contact-form.html @@ -25,7 +25,7 @@ } }; - xhr.open("POST", "https://n8n.tfcconnection.org/webhook/contact-form"); + xhr.open("POST", "/contact"); xhr.send(data); console.log(data); } diff --git a/src/api/contact.rs b/src/api/contact.rs new file mode 100644 index 0000000..17e6bd0 --- /dev/null +++ b/src/api/contact.rs @@ -0,0 +1,169 @@ +use std::{ + collections::{BTreeMap, HashMap}, + fs, +}; + +use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm}; +use actix_web::{post, web, HttpResponse}; +use color_eyre::{eyre::eyre, Result}; +use lettre::{ + message::{header::ContentType, Attachment, MultiPart, SinglePart}, + Message, +}; +use maud::{html, Markup, PreEscaped, DOCTYPE}; +use reqwest::Client; +use serde_json::json; +use sqlx::SqliteConnection; +use tracing::{error, info}; + +#[derive(Debug, MultipartForm)] +struct ContactForm { + name: Text, + email: Text, + staff: Text, + message: Text, +} + +impl From<&ContactForm> for HashMap { + fn from(form: &ContactForm) -> Self { + let mut map = HashMap::new(); + map.insert(169, form.name.0.clone()); + map.insert(169, form.email.0.clone()); + map.insert(169, form.staff.0.clone()); + map.insert(169, form.message.0.clone()); + map + } +} + +impl ContactForm { + async fn build_email(&self) -> Markup { + html! { + (DOCTYPE) + meta charset="utf-8"; + html { + head { + title { (self.name.0) " filled out a contact form!" } + style { + "table { border-collapse: collapse; width: 100% }" + "td, th { padding: 8px }" + "td { text-align: left; width: 70%; word-wrap: break-word }" + "th { text-align: right; border-right: 1px solid #ddd }" + "tr { border-bottom: 1px solid #ddd }" + "h1 { text-align: center }" + } + } + body { + h1 { "Contact form for " (self.name.0) "!" } + hr; + p { "Email: " (self.email.0) } + p { "To: " (self.staff.0) } + hr; + p { (self.message.0) } + } + } + } + } + + async fn store_form(&self) -> Result<()> { + let client = Client::new(); + let map = HashMap::from(self); + let mut json = HashMap::new(); + json.insert("data", map); + + let link = r#"https://staff.tfcconnection.org/apps/tables/#/table/14/row/757"#; + let res = client + .post("https://staff.tfcconnection.org/ocs/v2.php/apps/tables/api/2/tables/14/rows") + .basic_auth("chris", Some("2VHeGxeC^Zf9KqFK^G@Pt!zu2q^6@b")) + .header("OCS-APIRequest", "true") + .header("Content-Type", "application/json") + .json(&json) + .send() + .await?; + if res.status().is_success() { + let res = res.text().await.unwrap(); + Ok(()) + } else { + Err(eyre!( + "Problem in storing data: {:?}", + res.error_for_status() + )) + } + } + + async fn send_email(&mut self) -> Result<()> { + let name = self.name.clone(); + let email_subject = format!("Contact form for {}!", name); + info!("{name} contact form!"); + let email = self.build_email().await; + let email = SinglePart::html(email.into_string()); + + if let Ok(m) = Message::builder() + .from( + "TFC ADMIN " + .parse() + .unwrap(), + ) + .to("Chris Cochrun ".parse().unwrap()) + .to("Ethan Rose ".parse().unwrap()) + .subject(email_subject) + .singlepart(email) + { + crate::email::send_email(m).await + } else { + Err(eyre!("Email incorrect")) + } + } +} + +#[post("/api/mt-parent-form")] +pub async fn mt_parent_form(MultipartForm(mut form): MultipartForm) -> HttpResponse { + match form.store_form().await { + Ok(_) => info!("Successfully sent form to nextcloud!"), + Err(e) => error!("There was an erroring sending form to nextcloud: {e}"), + } + match form.send_email().await { + Ok(_) => info!("Successfully sent email"), + Err(e) => error!("There was an error sending the email: {e}"), + } + HttpResponse::Ok().body("thankyou") +} + +#[cfg(test)] +mod test { + use actix_web::test; + use pretty_assertions::assert_eq; + use sqlx::Connection; + use tracing::debug; + + use super::*; + + fn form() -> ContactForm { + ContactForm { + name: Text(String::from("Bilbo Braggins")), + email: Text(String::from("biblo@hobbits.us")), + staff: Text(String::from("Uncle")), + message: Text(String::from("Very")), + } + } + + #[test] + async fn test_nc_post() { + let form = form(); + assert!(!form.name.is_empty()); + let res = form.store_form().await; + match res { + Ok(_) => assert!(true, "passed storing test"), + Err(e) => assert!(false, "Failed storing test: {e}"), + } + } + + #[test] + async fn test_email() { + let mut form = form(); + assert!(!form.name.is_empty()); + match form.send_email().await { + Ok(_) => assert!(true, "passed emailing test"), + Err(e) => assert!(false, "Failed emailing test: {e}"), + } + } +} diff --git a/src/api/mod.rs b/src/api/mod.rs index dbb4844..0c01222 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,5 +1,6 @@ pub mod camp_form; // pub mod errors; +pub mod contact; pub mod health_form; pub mod local_trip_form; pub mod mt_church_form;