feat: begin implementation of student data
This commit is contained in:
1 parent
d7c4c6b707
commit
5a064bdd69
7 files changed
+201
-14
No files matched your search
@@ -3,6 +3,7 @@ mod scholarships;
|
|||||||
mod dates;
|
mod dates;
|
||||||
mod admin;
|
mod admin;
|
||||||
mod providers;
|
mod providers;
|
||||||
|
pub mod students;
|
||||||
|
|
||||||
pub use comparisons::*;
|
pub use comparisons::*;
|
||||||
pub use scholarships::*;
|
pub use scholarships::*;
|
||||||
@@ -21,3 +22,6 @@ pub static SCHOLARSHIPS_TABLE: &str = "leptos-scholarships";
|
|||||||
|
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
pub static PROVIDER_CONTACT_TABLE: &str = "leptos-provider-contacts";
|
pub static PROVIDER_CONTACT_TABLE: &str = "leptos-provider-contacts";
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
pub static MAIN_TABLE_NAME: &str = "scholarships-main";
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
use leptos::prelude::*;
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn put_student_data(
|
||||||
|
subject: String,
|
||||||
|
data_type: String,
|
||||||
|
data_map: std::collections::HashMap<String, crate::common::ValueType>
|
||||||
|
) -> Result<(), ServerFnError> {
|
||||||
|
use leptos::logging::log;
|
||||||
|
use crate::utils::server::{create_dynamo_client, into_attr_map};
|
||||||
|
use aws_sdk_dynamodb::types::AttributeValue;
|
||||||
|
use super::MAIN_TABLE_NAME;
|
||||||
|
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
|
||||||
|
let mut data_map_attr = into_attr_map(data_map);
|
||||||
|
data_map_attr.insert(
|
||||||
|
"HK".into(),
|
||||||
|
AttributeValue::S(format!("STUDENT#{}", subject))
|
||||||
|
);
|
||||||
|
data_map_attr.insert(
|
||||||
|
"SK".into(),
|
||||||
|
AttributeValue::S(data_type.to_uppercase())
|
||||||
|
);
|
||||||
|
|
||||||
|
log!("Inserting this item: {:?}", data_map_attr);
|
||||||
|
|
||||||
|
client
|
||||||
|
.put_item()
|
||||||
|
.table_name(MAIN_TABLE_NAME)
|
||||||
|
.set_item(Some(data_map_attr))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map(|_| ())
|
||||||
|
.map_err(ServerFnError::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn get_student_data(
|
||||||
|
subject: String,
|
||||||
|
data_type: String,
|
||||||
|
) -> Result<std::collections::HashMap<String, crate::common::ValueType>, ServerFnError> {
|
||||||
|
use crate::utils::server::create_dynamo_client;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use crate::common::ValueType;
|
||||||
|
use aws_sdk_dynamodb::types::AttributeValue;
|
||||||
|
use super::MAIN_TABLE_NAME;
|
||||||
|
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
|
||||||
|
client
|
||||||
|
.query()
|
||||||
|
.table_name(MAIN_TABLE_NAME)
|
||||||
|
.key_condition_expression("HK = :hk AND SK = :sk")
|
||||||
|
.expression_attribute_values(":hk", AttributeValue::S(format!("STUDENT#{}", subject)))
|
||||||
|
.expression_attribute_values(":sk", AttributeValue::S(data_type.to_uppercase()))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map(|output| {
|
||||||
|
// Map the output to a HashMap<String, ValueType>
|
||||||
|
let Some(list) = output.items else {
|
||||||
|
return HashMap::new();
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
|
||||||
|
let _ = list
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.for_each(|(k, v)| {
|
||||||
|
map.insert(k, ValueType::from(&v));
|
||||||
|
});
|
||||||
|
|
||||||
|
map
|
||||||
|
})
|
||||||
|
.map_err(ServerFnError::from)
|
||||||
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
use std::collections::HashMap;
|
use leptos::prelude::*;
|
||||||
use leptos::prelude::*;
|
|
||||||
use crate::components::{OutlinedTextField, TextFieldType, ValidatedForm};
|
use crate::components::{OutlinedTextField, TextFieldType, ValidatedForm};
|
||||||
|
use crate::pages::student::form_setup::use_student_form;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn StudentAcademicsPage() -> impl IntoView {
|
pub fn StudentAcademicsPage() -> impl IntoView {
|
||||||
let data_map = RwSignal::new(HashMap::new());
|
let controller = use_student_form("academics");
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="flex flex-1" />
|
<div class="flex flex-1" />
|
||||||
<div class="flex flex-col flex-2 mt-6">
|
<div class="flex flex-col flex-2 mt-6">
|
||||||
<ValidatedForm title="Academic Information" on_submit=move || {}>
|
<ValidatedForm title="Academic Information" on_submit=controller.submit_action>
|
||||||
<OutlinedTextField
|
<OutlinedTextField
|
||||||
label="Unweighted GPA:"
|
label="Unweighted GPA:"
|
||||||
data_map=data_map
|
data_map=controller.data_map
|
||||||
data_member="unweighted_gpa"
|
data_member="unweighted_gpa"
|
||||||
placeholder="4.0"
|
placeholder="4.0"
|
||||||
required=true
|
required=true
|
||||||
@@ -20,7 +20,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
|||||||
/>
|
/>
|
||||||
<OutlinedTextField
|
<OutlinedTextField
|
||||||
label="Weighted GPA:"
|
label="Weighted GPA:"
|
||||||
data_map=data_map
|
data_map=controller.data_map
|
||||||
data_member="weighted_gpa"
|
data_member="weighted_gpa"
|
||||||
placeholder="4.5"
|
placeholder="4.5"
|
||||||
required=true
|
required=true
|
||||||
@@ -28,7 +28,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
|||||||
/>
|
/>
|
||||||
<OutlinedTextField
|
<OutlinedTextField
|
||||||
label="Highest SAT Score:"
|
label="Highest SAT Score:"
|
||||||
data_map=data_map
|
data_map=controller.data_map
|
||||||
data_member="sat_score"
|
data_member="sat_score"
|
||||||
placeholder="1600"
|
placeholder="1600"
|
||||||
required=false
|
required=false
|
||||||
@@ -36,7 +36,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
|||||||
/>
|
/>
|
||||||
<OutlinedTextField
|
<OutlinedTextField
|
||||||
label="Highest ACT Score:"
|
label="Highest ACT Score:"
|
||||||
data_map=data_map
|
data_map=controller.data_map
|
||||||
data_member="act_score"
|
data_member="act_score"
|
||||||
placeholder="36"
|
placeholder="36"
|
||||||
required=false
|
required=false
|
||||||
@@ -44,7 +44,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
|||||||
/>
|
/>
|
||||||
<OutlinedTextField
|
<OutlinedTextField
|
||||||
label="Academic Honors:"
|
label="Academic Honors:"
|
||||||
data_map=data_map
|
data_map=controller.data_map
|
||||||
data_member="academic_honors"
|
data_member="academic_honors"
|
||||||
placeholder="TBD"
|
placeholder="TBD"
|
||||||
required=false
|
required=false
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
use std::collections::HashMap;
|
use leptos::prelude::*;
|
||||||
use leptos::prelude::*;
|
|
||||||
use crate::components::{MultiEntry, ValidatedForm};
|
use crate::components::{MultiEntry, ValidatedForm};
|
||||||
use crate::input;
|
use crate::input;
|
||||||
|
use crate::pages::student::form_setup::use_student_form;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn StudentAthleticsPage() -> impl IntoView {
|
pub fn StudentAthleticsPage() -> impl IntoView {
|
||||||
let data_map = RwSignal::new(HashMap::new());
|
let controller = use_student_form("athletics");
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="flex flex-1" />
|
<div class="flex flex-1" />
|
||||||
<div class="flex flex-col flex-2 mt-6">
|
<div class="flex flex-col flex-2 mt-6">
|
||||||
<ValidatedForm title="Athletics Information" on_submit=move || {}>
|
<ValidatedForm title="Athletics Information" on_submit=controller.submit_action>
|
||||||
<MultiEntry
|
<MultiEntry
|
||||||
label="Athletics Activities:"
|
label="Athletics Activities:"
|
||||||
description="Leave blank if not applicable."
|
description="Leave blank if not applicable."
|
||||||
data_map=data_map
|
data_map=controller.data_map
|
||||||
data_member="athletic_participation"
|
data_member="athletic_participation"
|
||||||
schema=vec![
|
schema=vec![
|
||||||
input!(
|
input!(
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use leptos::prelude::*;
|
||||||
|
use crate::common::ValueType;
|
||||||
|
use crate::pages::api::students::{get_student_data, PutStudentData};
|
||||||
|
use crate::utils::get_user_claims;
|
||||||
|
|
||||||
|
pub struct StudentFormInfo {
|
||||||
|
pub data_map: RwSignal<HashMap<String, ValueType>>,
|
||||||
|
pub user_id: Memo<Option<String>>,
|
||||||
|
pub submit_action: Callback<()>,
|
||||||
|
pub refresh_trigger: Trigger,
|
||||||
|
pub data_resource: Resource<Result<HashMap<String, ValueType>, ServerFnError>>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn use_student_form(
|
||||||
|
form_type: impl Into<Signal<String>>
|
||||||
|
) -> StudentFormInfo {
|
||||||
|
let form_type = form_type.into();
|
||||||
|
|
||||||
|
let user_claims = get_user_claims();
|
||||||
|
let user_id = Memo::new(move |_| {
|
||||||
|
user_claims.get()
|
||||||
|
.map(|info| info.claims.subject.clone())
|
||||||
|
});
|
||||||
|
|
||||||
|
let data_map = RwSignal::new(HashMap::new());
|
||||||
|
|
||||||
|
let refresh_trigger = Trigger::new();
|
||||||
|
let data_resource = Resource::new(
|
||||||
|
move || (user_id.get().unwrap_or_default(), form_type.get(), refresh_trigger.track()),
|
||||||
|
async move |(id, form_type, _)| get_student_data(
|
||||||
|
id,
|
||||||
|
form_type,
|
||||||
|
).await
|
||||||
|
);
|
||||||
|
|
||||||
|
Effect::new(move || {
|
||||||
|
data_resource.with(|map_opt| {
|
||||||
|
let Some(Ok(map)) = map_opt else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
data_map.set(map.to_owned());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let submit_action = ServerAction::<PutStudentData>::new();
|
||||||
|
let on_submit = move || {
|
||||||
|
submit_action.dispatch(PutStudentData {
|
||||||
|
subject: user_id.get().unwrap_or_default(),
|
||||||
|
data_type: form_type.get(),
|
||||||
|
data_map: data_map.get()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
StudentFormInfo {
|
||||||
|
data_map,
|
||||||
|
refresh_trigger,
|
||||||
|
data_resource,
|
||||||
|
user_id,
|
||||||
|
submit_action: on_submit.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,55 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use leptos::logging::log;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
|
use crate::common::ValueType;
|
||||||
|
use crate::components::ActionButton;
|
||||||
|
use crate::pages::api::students::{GetStudentData, PutStudentData};
|
||||||
|
use crate::utils::get_user_claims;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn StudentHomePage() -> impl IntoView {
|
pub fn StudentHomePage() -> impl IntoView {
|
||||||
|
let user_claims = get_user_claims();
|
||||||
|
let user_id = Memo::new(move |_| {
|
||||||
|
user_claims.get()
|
||||||
|
.map(|info| info.claims.subject.clone())
|
||||||
|
});
|
||||||
|
|
||||||
|
let create_student_data = ServerAction::<PutStudentData>::new();
|
||||||
|
let get_student_data = ServerAction::<GetStudentData>::new();
|
||||||
|
|
||||||
|
let on_click_student_test = move |_| {
|
||||||
|
create_student_data.dispatch(PutStudentData {
|
||||||
|
subject: user_id.get().unwrap_or_default(),
|
||||||
|
data_type: "TESTING".into(),
|
||||||
|
data_map: HashMap::from([
|
||||||
|
("testing_info".into(), ValueType::String(Some("hello!".to_string())))
|
||||||
|
]),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let on_click_get_student = move |_| {
|
||||||
|
get_student_data.dispatch(GetStudentData {
|
||||||
|
subject: user_id.get().unwrap_or_default(),
|
||||||
|
data_type: "TESTING".into()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Effect::new(move || {
|
||||||
|
let Some(value) = get_student_data.value().get() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
log!("{:?}", value);
|
||||||
|
});
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<div class="flex flex-1 flex-col gap-4 items-center m-4">
|
<div class="flex flex-1 flex-col gap-4 items-center m-4">
|
||||||
<div class="font-bold text-3xl">"Student Home Page"</div>
|
<div class="font-bold text-3xl">"Student Home Page"</div>
|
||||||
<div class="text-lg">
|
<div class="text-lg">
|
||||||
"This is just a placeholder for now. We'll show some redirect buttons."
|
"This is just a placeholder for now. We'll show some redirect buttons."
|
||||||
</div>
|
</div>
|
||||||
|
<ActionButton on:click=on_click_student_test>"Test Put Student Function"</ActionButton>
|
||||||
|
<ActionButton on:click=on_click_get_student>"Test Get Student Function"</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ mod extracurriculars_page;
|
|||||||
mod work_experience_page;
|
mod work_experience_page;
|
||||||
mod university_page;
|
mod university_page;
|
||||||
mod family_info_page;
|
mod family_info_page;
|
||||||
|
mod form_setup;
|
||||||
|
|
||||||
pub use shell::*;
|
pub use shell::*;
|
||||||
pub use home_page::*;
|
pub use home_page::*;
|
||||||
|
|||||||
Reference in new issue
Block a user