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 admin;
|
||||
mod providers;
|
||||
pub mod students;
|
||||
|
||||
pub use comparisons::*;
|
||||
pub use scholarships::*;
|
||||
@@ -21,3 +22,6 @@ pub static SCHOLARSHIPS_TABLE: &str = "leptos-scholarships";
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
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::pages::student::form_setup::use_student_form;
|
||||
|
||||
#[component]
|
||||
pub fn StudentAcademicsPage() -> impl IntoView {
|
||||
let data_map = RwSignal::new(HashMap::new());
|
||||
let controller = use_student_form("academics");
|
||||
|
||||
view! {
|
||||
<div class="flex flex-1" />
|
||||
<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
|
||||
label="Unweighted GPA:"
|
||||
data_map=data_map
|
||||
data_map=controller.data_map
|
||||
data_member="unweighted_gpa"
|
||||
placeholder="4.0"
|
||||
required=true
|
||||
@@ -20,7 +20,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
||||
/>
|
||||
<OutlinedTextField
|
||||
label="Weighted GPA:"
|
||||
data_map=data_map
|
||||
data_map=controller.data_map
|
||||
data_member="weighted_gpa"
|
||||
placeholder="4.5"
|
||||
required=true
|
||||
@@ -28,7 +28,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
||||
/>
|
||||
<OutlinedTextField
|
||||
label="Highest SAT Score:"
|
||||
data_map=data_map
|
||||
data_map=controller.data_map
|
||||
data_member="sat_score"
|
||||
placeholder="1600"
|
||||
required=false
|
||||
@@ -36,7 +36,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
||||
/>
|
||||
<OutlinedTextField
|
||||
label="Highest ACT Score:"
|
||||
data_map=data_map
|
||||
data_map=controller.data_map
|
||||
data_member="act_score"
|
||||
placeholder="36"
|
||||
required=false
|
||||
@@ -44,7 +44,7 @@ pub fn StudentAcademicsPage() -> impl IntoView {
|
||||
/>
|
||||
<OutlinedTextField
|
||||
label="Academic Honors:"
|
||||
data_map=data_map
|
||||
data_map=controller.data_map
|
||||
data_member="academic_honors"
|
||||
placeholder="TBD"
|
||||
required=false
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
use std::collections::HashMap;
|
||||
use leptos::prelude::*;
|
||||
use leptos::prelude::*;
|
||||
use crate::components::{MultiEntry, ValidatedForm};
|
||||
use crate::input;
|
||||
use crate::pages::student::form_setup::use_student_form;
|
||||
|
||||
#[component]
|
||||
pub fn StudentAthleticsPage() -> impl IntoView {
|
||||
let data_map = RwSignal::new(HashMap::new());
|
||||
let controller = use_student_form("athletics");
|
||||
|
||||
view! {
|
||||
<div class="flex flex-1" />
|
||||
<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
|
||||
label="Athletics Activities:"
|
||||
description="Leave blank if not applicable."
|
||||
data_map=data_map
|
||||
data_map=controller.data_map
|
||||
data_member="athletic_participation"
|
||||
schema=vec![
|
||||
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 crate::common::ValueType;
|
||||
use crate::components::ActionButton;
|
||||
use crate::pages::api::students::{GetStudentData, PutStudentData};
|
||||
use crate::utils::get_user_claims;
|
||||
|
||||
#[component]
|
||||
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! {
|
||||
<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="text-lg">
|
||||
"This is just a placeholder for now. We'll show some redirect buttons."
|
||||
</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>
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ mod extracurriculars_page;
|
||||
mod work_experience_page;
|
||||
mod university_page;
|
||||
mod family_info_page;
|
||||
mod form_setup;
|
||||
|
||||
pub use shell::*;
|
||||
pub use home_page::*;
|
||||
|
||||
Reference in new issue
Block a user