feat: make toasts available on all routes

This commit is contained in:
alphafetus committed 2026-01-12 15:52:17 -05:00
1 parent 865410b6f2
commit de7b8633ff
4 files changed
+121 -96

No files matched your search

+20 -17
View File
@@ -3,6 +3,7 @@ use leptos::prelude::*;
use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context}; use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context};
use leptos_oidc::{Auth, AuthParameters, AuthSignal, Challenge}; use leptos_oidc::{Auth, AuthParameters, AuthSignal, Challenge};
use leptos_router::{components::{Route, Router, Routes, ParentRoute}, path}; use leptos_router::{components::{Route, Router, Routes, ParentRoute}, path};
use crate::components::ToastList;
pub fn shell(options: LeptosOptions) -> impl IntoView { pub fn shell(options: LeptosOptions) -> impl IntoView {
view! { view! {
@@ -94,23 +95,25 @@ pub fn AppWithRoutes() -> impl IntoView {
<Title text="R15 Scholarship App DEV" /> <Title text="R15 Scholarship App DEV" />
<main> <main>
// TODO Create a 404 page <ToastList>
<Routes fallback=|| "Page not found.".into_view()> // TODO Create a 404 page
<Route path=path!("") view=HomePage/> <Routes fallback=|| "Page not found.".into_view()>
<Route path=path!("/about") view=AboutPage/> <Route path=path!("") view=HomePage/>
<Route path=path!("/test_page") view=TestPage/> <Route path=path!("/about") view=AboutPage/>
<Route path=path!("/comparison") view=ComparisonTestPage /> <Route path=path!("/test_page") view=TestPage/>
<Route path=path!("/providers") view=ProviderPortal/> <Route path=path!("/comparison") view=ComparisonTestPage />
<Route path=path!("/providers/profile") view=ProviderContactPage /> <Route path=path!("/providers") view=ProviderPortal/>
<ParentRoute path=path!("/providers/scholarships") view=ScholarshipInfoPage> <Route path=path!("/providers/profile") view=ProviderContactPage />
<Route path=path!(":id") view=ScholarshipInfoPage/> <ParentRoute path=path!("/providers/scholarships") view=ScholarshipInfoPage>
<Route path=path!("") view=ScholarshipInfoPage/> <Route path=path!(":id") view=ScholarshipInfoPage/>
</ParentRoute> <Route path=path!("") view=ScholarshipInfoPage/>
<ParentRoute path=path!("loaners") view=LoanerPage> </ParentRoute>
<Route path=path!("") view=LoanerPage /> <ParentRoute path=path!("loaners") view=LoanerPage>
<Route path=path!(":form_name") view=LoanerPage /> <Route path=path!("") view=LoanerPage />
</ParentRoute> <Route path=path!(":form_name") view=LoanerPage />
</Routes> </ParentRoute>
</Routes>
</ToastList>
</main> </main>
} }
} }
+9 -2
View File
@@ -4,6 +4,7 @@ use crate::components::toasts::toast::Toast;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Toast { pub struct Toast {
id: String, id: String,
header: String,
message: String, message: String,
} }
@@ -11,10 +12,16 @@ impl Toast {
pub fn new() -> Self { pub fn new() -> Self {
Toast { Toast {
id: "".to_owned(), id: "".to_owned(),
header: "".to_owned(),
message: "".to_owned(), message: "".to_owned(),
} }
} }
pub fn header(mut self, header: impl Into<String>) -> Self {
self.header = header.into();
self
}
pub fn msg(mut self, msg: impl Into<String>) -> Self { pub fn msg(mut self, msg: impl Into<String>) -> Self {
self.message = msg.into(); self.message = msg.into();
self self
@@ -61,11 +68,11 @@ pub fn ToastList(
<For <For
each=move || context.messages.get() each=move || context.messages.get()
key=|toast| toast.id.clone() key=|toast| toast.id.clone()
let(Toast { id, message }) let(Toast { id, header, message })
> >
<Toast <Toast
message=message message=message
title="Testing Toast" title=header
on_close=move || { on_close=move || {
context.messages.update(|list| context.messages.update(|list|
list.retain(|v| v.id != id) list.retain(|v| v.id != id)
+1 -1
View File
@@ -149,7 +149,7 @@ pub fn ValidatedForm(
} }
button_type="submit" button_type="submit"
> >
"Submit form (but actually)" "Submit"
</ActionButton> </ActionButton>
</form> </form>
} }
+91 -76
View File
@@ -3,7 +3,7 @@ use leptos::logging::log;
use leptos::prelude::*; use leptos::prelude::*;
use leptos_oidc::{AuthLoaded, Authenticated}; use leptos_oidc::{AuthLoaded, Authenticated};
use crate::common::ValueType; use crate::common::ValueType;
use crate::components::{Banner, Loading, OutlinedTextField, Panel, Row, TextFieldType, ValidatedForm}; use crate::components::{Banner, Loading, OutlinedTextField, Panel, Row, TextFieldType, Toast, ToastContext, ToastList, ValidatedForm};
use crate::pages::UnauthenticatedPage; use crate::pages::UnauthenticatedPage;
use crate::pages::utils::get_user_claims; use crate::pages::utils::get_user_claims;
@@ -120,86 +120,101 @@ pub fn ProviderContactPage() -> impl IntoView {
submit_action.pending().get() submit_action.pending().get()
}); });
let mut toasts_context = expect_context::<ToastContext>();
Effect::new(move || {
submit_action.value().get().is_some()
.then(|| {
toasts_context.toast(
Toast::new()
.id(uuid::Uuid::new_v4())
.header("Submission Successful")
.msg("You can go back or continue editing your responses.")
);
});
});
// Display contact form. // Display contact form.
view! { view! {
<Banner <Banner title="R15 Scholarships" logo="/PHS_Stacked_Acronym.png" path="/" />
title="R15 Scholarships"
logo="/PHS_Stacked_Acronym.png"
path="/"
/>
<AuthLoaded fallback=Loading> <AuthLoaded fallback=Loading>
<Authenticated unauthenticated=UnauthenticatedPage> <Authenticated unauthenticated=UnauthenticatedPage>
<Suspense fallback=Loading> <Suspense fallback=Loading>
<Panel> <div class="flex flex-row">
<ValidatedForm on_submit=on_submit> <div class="flex flex-col flex-1" />
{move || contact_resource.get() <Panel>
.map(|_| { <ValidatedForm on_submit=on_submit>
view! { {move || {
<Row> contact_resource
<OutlinedTextField .get()
label="First Name:" .map(|_| {
placeholder="John" view! {
disabled=elements_disabled <Row>
data_member="first_name" <OutlinedTextField
data_map=contact_info label="First Name:"
required=true placeholder="John"
/> disabled=elements_disabled
<OutlinedTextField data_member="first_name"
label="Last Name:" data_map=contact_info
placeholder="Smith" required=true
disabled=elements_disabled />
data_member="last_name" <OutlinedTextField
data_map=contact_info label="Last Name:"
required=true placeholder="Smith"
/> disabled=elements_disabled
</Row> data_member="last_name"
<Row> data_map=contact_info
<OutlinedTextField required=true
label="Contact Email:" />
placeholder="student@region15.org" </Row>
disabled=elements_disabled <Row>
data_member="contact_email" <OutlinedTextField
data_map=contact_info label="Contact Email:"
input_type=TextFieldType::Email placeholder="student@region15.org"
required=true disabled=elements_disabled
/> data_member="contact_email"
</Row> data_map=contact_info
<Row> input_type=TextFieldType::Email
<OutlinedTextField required=true
label="Phone Number:" />
placeholder="123-456-7890" </Row>
disabled=elements_disabled <Row>
data_member="phone_number" <OutlinedTextField
data_map=contact_info label="Phone Number:"
required=true placeholder="123-456-7890"
/> disabled=elements_disabled
</Row> data_member="phone_number"
<Row> data_map=contact_info
<OutlinedTextField required=true
label="Street Address:" />
placeholder="123 Fake Street" </Row>
disabled=elements_disabled <Row>
data_member="address" <OutlinedTextField
data_map=contact_info label="Street Address:"
required=true placeholder="123 Fake Street"
/> disabled=elements_disabled
</Row> data_member="address"
<Row> data_map=contact_info
<OutlinedTextField required=true
label="Testing Number" />
placeholder="Just put a number" </Row>
disabled=elements_disabled <Row>
data_member="testing_number" <OutlinedTextField
data_map=contact_info label="Testing Number"
input_type=TextFieldType::Number placeholder="Just put a number"
required=true disabled=elements_disabled
/> data_member="testing_number"
</Row> data_map=contact_info
} input_type=TextFieldType::Number
}) required=true
} />
</ValidatedForm> </Row>
</Panel> }
})
}}
</ValidatedForm>
</Panel>
<div class="flex flex-col flex-1" />
</div>
</Suspense> </Suspense>
</Authenticated> </Authenticated>
</AuthLoaded> </AuthLoaded>