diff --git a/src/app.rs b/src/app.rs index b3b1aa6..c7cc1ae 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,4 +1,4 @@ -use crate::pages::{AboutPage, HomePage, LoanerPage, ProviderPortal, ComparisonTestPage, ScholarshipInfoPage, TestPage}; +use crate::pages::{AboutPage, HomePage, LoanerPage, ProviderPortal, ComparisonTestPage, ScholarshipInfoPage, TestPage, ProviderContactPage}; use leptos::leptos_dom::log; use leptos::prelude::*; use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context}; @@ -105,6 +105,7 @@ pub fn AppWithRoutes() -> impl IntoView { + diff --git a/src/pages/mod.rs b/src/pages/mod.rs index b3d9f41..4da8c68 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -8,8 +8,9 @@ mod scholarship_info; mod test_page; mod unauthenticated_page; mod utils; +mod provider_contact; pub use self::{ about_page::*, comparison_test::*, home_page::*, loaner_page::*, provider_portal::*, - test_page::*, unauthenticated_page::*, scholarship_info::* + test_page::*, unauthenticated_page::*, scholarship_info::*, provider_contact::* }; diff --git a/src/pages/provider_contact.rs b/src/pages/provider_contact.rs new file mode 100644 index 0000000..775d3c3 --- /dev/null +++ b/src/pages/provider_contact.rs @@ -0,0 +1,207 @@ +use std::collections::HashMap; +use leptos::logging::log; +use leptos::prelude::*; +use leptos_oidc::{AuthLoaded, Authenticated}; +use crate::common::ValueType; +use crate::components::{Banner, Loading, OutlinedTextField, Panel, Row, TextFieldType, ValidatedForm}; +use crate::pages::UnauthenticatedPage; +use crate::pages::utils::get_user_claims; + +#[cfg(feature = "ssr")] +use crate::pages::utils::server_utils::create_dynamo_client; + +#[cfg(feature = "ssr")] +fn into_attr_map(map: HashMap) -> HashMap { + map.into_iter().map(|(k, v)| (k, v.into())).collect() +} + +#[server] +async fn get_provider_contact(id: String) -> Result, ServerFnError> { + use aws_sdk_dynamodb::types::AttributeValue; + use aws_sdk_dynamodb::error::ProvideErrorMetadata; + + let client = create_dynamo_client().await; + + log!("Getting contact info for provider {}", id); + + match client + .get_item() + .table_name("leptos-provider-contacts") + .key("subject", AttributeValue::S(id)) + .send() + .await + { + Ok(output) => { + let Some(item) = output.item else { + return Ok(HashMap::new()); + }; + + let map = item.iter().map(|(key, val)| { + let val_type = ValueType::from(val); + + (key.clone(), val_type) + }).collect::>(); + + Ok(map) + } + Err(err) => { + let msg = err.message().unwrap_or("An unknown error occurred."); + Err(ServerFnError::new(msg)) + } + } +} + +#[server] +async fn put_provider_contact(id: String, contact_info: HashMap) -> Result<(), ServerFnError> { + use aws_sdk_dynamodb::error::ProvideErrorMetadata; + + let client = create_dynamo_client().await; + + let mut item = into_attr_map(contact_info); + item.insert("subject".to_owned(), aws_sdk_dynamodb::types::AttributeValue::S(id)); + + match client + .put_item() + .table_name("leptos-provider-contacts") + .set_item(Some(item)) + .send() + .await + { + Ok(_) => Ok(()), + Err(err) => { + let msg = err.message().unwrap_or("An unknown error occurred."); + Err(ServerFnError::new(msg)) + } + } +} + +#[component] +pub fn ProviderContactPage() -> impl IntoView { + // Get user claims + let user_claims = get_user_claims(); + let user_id = Memo::new(move |_| { + user_claims.get() + .map(|info| info.claims.subject.clone()) + }); + + // Get contact information + let contact_info = RwSignal::new(HashMap::new()); + let contact_resource = Resource::new( + move || user_id.get(), + async move |id| { + let Some(id) = id else { + return Ok(HashMap::new()); + }; + + get_provider_contact(id).await + } + ); + + Effect::new(move || { + match contact_resource.get() { + Some(Ok(map)) => contact_info.set(map), + Some(Err(e)) => log!("Error getting contact info: {}", e), + None => log!("Contact info resource is not ready yet."), + } + }); + + // Set up submit action + let submit_action = ServerAction::::new(); + + let on_submit = move || { + // Submit the form by reading the contact_info. + submit_action.dispatch(PutProviderContact { + id: user_id.get().unwrap_or_default(), + contact_info: contact_info.get() + }); + }; + + let elements_disabled = Signal::derive(move || { + submit_action.pending().get() + }); + + // Display contact form. + view! { + + + + + + + {move || contact_resource.get() + .map(|_| { + view! { + + + + + + + + + + + + + + + + + } + }) + } + + + + + + } +} \ No newline at end of file