feat: implement basic structure of provider applicants page

This commit is contained in:
alphafetus committed 2026-04-08 13:55:07 -04:00
1 parent 3baee8cac7
commit 469f192feb
5 files changed
+508 -26

No files matched your search

+82 -3
View File
@@ -1,10 +1,12 @@
use leptos::prelude::*;
use leptos::server_fn::codec::Json;
use std::collections::HashMap;
#[cfg(feature = "ssr")]
mod imports {
pub use super::super::MAIN_TABLE_NAME;
pub use crate::common::ValueType;
pub use crate::pages::api::tokens::validate_and_get_token_info;
pub use crate::utils::server::*;
pub use aws_sdk_dynamodb::error::ProvideErrorMetadata;
pub use aws_sdk_dynamodb::types::AttributeValue;
@@ -16,7 +18,7 @@ mod imports {
pub async fn put_student_data(
subject: String,
data_type: String,
data_map: std::collections::HashMap<String, crate::common::ValueType>,
data_map: HashMap<String, crate::common::ValueType>,
) -> Result<(), ServerFnError> {
use imports::*;
@@ -52,7 +54,7 @@ pub async fn put_student_data(
pub async fn get_student_data(
subject: String,
data_type: String,
) -> Result<std::collections::HashMap<String, crate::common::ValueType>, ServerFnError> {
) -> Result<HashMap<String, crate::common::ValueType>, ServerFnError> {
use imports::*;
let client = create_dynamo_client().await;
@@ -99,7 +101,7 @@ pub async fn get_student_data(
#[server]
pub async fn get_all_student_data(
subject: String,
) -> Result<std::collections::HashMap<String, crate::common::ValueType>, ServerFnError> {
) -> Result<HashMap<String, crate::common::ValueType>, ServerFnError> {
use imports::*;
let client = create_dynamo_client().await;
@@ -131,3 +133,80 @@ pub async fn get_all_student_data(
ServerFnError::new(msg)
})
}
#[server]
pub async fn get_completed_students(
access_token: String,
) -> Result<HashMap<String, HashMap<String, crate::common::ValueType>>, ServerFnError> {
use imports::*;
// We want to get all student information. The requirements are that the students have completed
// the demographics form - everything else may bed from this.
// The easiest way is to get all the information and filter on this side, instead of bookkeeping
// on the database's side.
// We want to verify the access token first, and make sure that the user has the correct access.
let claims = validate_and_get_token_info(access_token).await?;
if !claims.groups.contains(&"ScholarshipProviders".to_string()) {
return Err(ServerFnError::new(
"User is not in the ScholarshipProviders group",
));
}
let client = create_dynamo_client().await;
let response = client
.scan()
.table_name(MAIN_TABLE_NAME)
.send()
.await
.map_err(|err| {
let msg = err.message().unwrap_or("Unknown error occurred");
error!("{}", msg);
ServerFnError::new(msg)
})?;
let Some(items) = response.items else {
return Ok(HashMap::new());
};
let mut output = HashMap::<String, HashMap<String, ValueType>>::new();
items.into_iter().for_each(|mut form_info| {
let student_id_full = form_info
.get("HK")
.map(|v| v.as_s().cloned().unwrap_or_default())
.unwrap_or_default()
.to_owned();
let student_id = student_id_full.split("STUDENT#").collect::<String>();
form_info.remove("HK");
form_info.remove("SK");
let form_info_convert = form_info
.into_iter()
.map(|(k, v)| (k, ValueType::from(&v)))
.collect::<HashMap<String, ValueType>>();
// We want to insert all the remaining information into the output map
output
.entry(student_id)
.and_modify(|v| {
v.extend(form_info_convert.clone());
})
.or_insert(form_info_convert);
});
// Don't love this, but it does verify that the student has completed the demographics form
let output = output
.into_iter()
.filter_map(|(k, student_info)| {
student_info
.get("first_name")
.and_then(|_| Some((k, student_info.clone())))
})
.collect();
Ok(output)
}