Skip to content

Commit f08c6ac

Browse files
authored
React email template for starlight (#809)
* Revert "Availabilities CRUD (#735)" This reverts commit 01457e4. * feat: hardcoded emails for starlight demo * chore: react email dependencies * feat: make backend work with react email (theoretically) * feat: starlight email hardcode
1 parent a884010 commit f08c6ac

18 files changed

Lines changed: 554 additions & 517 deletions

File tree

backend/server/src/handler/availabilities.rs

Lines changed: 0 additions & 149 deletions
This file was deleted.

backend/server/src/handler/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
pub mod answer;
2121
pub mod application;
2222
pub mod auth;
23-
pub mod availabilities;
2423
pub mod campaign;
2524
pub mod comment;
2625
pub mod email_template;

backend/server/src/handler/offer.rs

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,9 @@ impl OfferHandler {
191191

192192
let count = body.emails.len();
193193
for item in body.emails {
194+
// Create an offer record for acceptances (audit / accept-decline flow).
194195
if matches!(item.email_type, EmailType::Accept) {
195-
let offer_id = Offer::create(
196+
Offer::create(
196197
campaign_id,
197198
item.application_id,
198199
item.email_template_id,
@@ -202,31 +203,23 @@ impl OfferHandler {
202203
&mut state.snowflake_generator,
203204
)
204205
.await?;
205-
if state.is_dev_env {
206-
let email = item.email;
207-
println!("need to call offers here, but sent to: {email}");
208-
} else {
209-
Offer::send_offer(
210-
offer_id,
211-
&mut transaction.tx,
212-
state.email_credentials.clone(),
213-
)
214-
.await?;
215-
}
206+
}
207+
208+
// Queue the frontend-rendered subject/body for all outcome types.
209+
// Accept emails are HTML (React Email); rejects remain plaintext for now.
210+
if state.is_dev_env {
211+
let email = item.email;
212+
let email_type = format!("{:?}", item.email_type);
213+
println!("Queuing {email_type} email to {email}");
216214
} else {
217-
if state.is_dev_env {
218-
let email = item.email;
219-
println!("Sending reject email to {email}");
220-
} else {
221-
EmailQueue::add_to_queue(
222-
Some(item.name),
223-
item.email,
224-
item.subject,
225-
item.body,
226-
&mut transaction.tx,
227-
)
228-
.await?;
229-
}
215+
EmailQueue::add_to_queue(
216+
Some(item.name),
217+
item.email,
218+
item.subject,
219+
item.body,
220+
&mut transaction.tx,
221+
)
222+
.await?;
230223
}
231224
}
232225

backend/server/src/models/app.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use crate::handler::answer::AnswerHandler;
22
use crate::handler::application::ApplicationHandler;
33
use crate::handler::auth::{google_auth_init, google_callback, logout, DevLoginHandler};
4-
use crate::handler::availabilities::AvailabilitiesHandler;
54
use crate::handler::campaign::CampaignHandler;
65
use crate::handler::comment::CommentHandler;
76
use crate::handler::email_template::EmailTemplateHandler;
@@ -13,7 +12,6 @@ use crate::handler::rating::RatingHandler;
1312
use crate::handler::role::RoleHandler;
1413
use crate::handler::role_status::RoleStatusHandler;
1514
use crate::handler::user::UserHandler;
16-
use crate::models::availabilities::Availability;
1715
use crate::models::email::{ChaosEmail, EmailCredentials};
1816
use crate::models::error::ChaosError;
1917
use crate::models::storage::Storage;
@@ -180,11 +178,6 @@ pub async fn init_app_state() -> AppState {
180178
}
181179
}
182180

183-
#[derive(Serialize)]
184-
pub struct AvailabilitiesMessage {
185-
pub availabilities: Vec<Availability>,
186-
}
187-
188181
pub async fn app() -> Result<(Router, AppState), ChaosError> {
189182
let state = init_app_state().await;
190183
let state_clone = state.clone();
@@ -567,10 +560,6 @@ pub async fn app() -> Result<(Router, AppState), ChaosError> {
567560
"/api/v1/invite/:code",
568561
get(InviteHandler::get).post(InviteHandler::use_invite),
569562
)
570-
.route(
571-
"/api/v1/availabilities/:user_id/:campaign_id",
572-
get(AvailabilitiesHandler::get).patch(AvailabilitiesHandler::update),
573-
)
574563
.layer(cors)
575564
.with_state(state);
576565

backend/server/src/models/email.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! the Lettre email library.
66
77
use crate::models::error::ChaosError;
8+
use lettre::message::header::ContentType;
89
use lettre::transport::smtp::authentication::Credentials;
910
use lettre::{AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor};
1011
use serde::{Deserialize, Serialize};
@@ -146,6 +147,14 @@ impl ChaosEmail {
146147
None => recipient_email_address,
147148
};
148149

150+
// Detect HTML so React Email bodies render correctly in clients.
151+
// Plaintext reject bodies still work as text/plain.
152+
let content_type = if body.trim_start().starts_with('<') {
153+
ContentType::TEXT_HTML
154+
} else {
155+
ContentType::TEXT_PLAIN
156+
};
157+
149158
let message = Message::builder()
150159
.from(
151160
format!(
@@ -157,6 +166,7 @@ impl ChaosEmail {
157166
.reply_to("chaos@devsoc.app".parse()?)
158167
.to(to.parse()?)
159168
.subject(subject)
169+
.header(content_type)
160170
.body(body)?;
161171

162172
let mailer = Self::new_connection(credentials)?;

backend/server/src/models/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ pub mod answer;
1111
pub mod app;
1212
pub mod application;
1313
pub mod auth;
14-
pub mod availabilities;
1514
pub mod campaign;
1615
pub mod comment_last_read;
1716
pub mod comment;

0 commit comments

Comments
 (0)