Implement new structure-based comparison system #20
No files matched your search
@@ -42,7 +42,8 @@ impl ComparisonData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn compare(&self, student_data: &ExpandableInfo) -> Result<bool, String> {
|
pub fn compare(&self, student_data: &ExpandableInfo) -> Result<bool, String> {
|
||||||
let value = student_data.data.get(&self.member).unwrap();
|
let value = student_data.data.get(&self.member)
|
||||||
|
.expect(format!("Couldn't find member {:?}, current student data: {:?}", self.member, student_data).as_str());
|
||||||
self.comparison.evaluate(value, &self.target_value)
|
self.comparison.evaluate(value, &self.target_value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ impl InputType {
|
|||||||
placeholder = placeholder.clone()
|
placeholder = placeholder.clone()
|
||||||
data_member = member.clone()
|
data_member = member.clone()
|
||||||
data_map = data_map
|
data_map = data_map
|
||||||
|
input_type = "number"
|
||||||
/>
|
/>
|
||||||
}),
|
}),
|
||||||
InputType::Checkbox(member, label, options) =>
|
InputType::Checkbox(member, label, options) =>
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ pub fn MultiEntry(
|
|||||||
/// component's `data_member` input.
|
/// component's `data_member` input.
|
||||||
#[prop()]
|
#[prop()]
|
||||||
data_map: RwSignal<HashMap<String, ValueType>>,
|
data_map: RwSignal<HashMap<String, ValueType>>,
|
||||||
#[prop(into)] name_member: String,
|
/// Currently unused.
|
||||||
|
#[prop(optional, into)] name_member: String,
|
||||||
/// The type and order of the inputs for each `Entry` component within this `MultiEntry` component.
|
/// The type and order of the inputs for each `Entry` component within this `MultiEntry` component.
|
||||||
#[prop(optional)]
|
#[prop(optional)]
|
||||||
schema: Vec<InputType>,
|
schema: Vec<InputType>,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ pub fn Panel(
|
|||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
<div
|
<div
|
||||||
class="flex flex-col gap-2 p-2 m-4 flex-1
|
class="flex flex-col gap-2 p-2 m-4 flex-2
|
||||||
border-1 border-gray-600/10
|
border-1 border-gray-600/10
|
||||||
rounded-md shadow-[0_0_6px_rgba(0,0,0,0.50)]"
|
rounded-md shadow-[0_0_6px_rgba(0,0,0,0.50)]"
|
||||||
class=(["hidden"], hidden) >
|
class=(["hidden"], hidden) >
|
||||||
|
|||||||
@@ -0,0 +1,349 @@
|
|||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use crate::pages::utils::server_utils::create_dynamo_client;
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use aws_sdk_dynamodb::{
|
||||||
|
error::ProvideErrorMetadata,
|
||||||
|
};
|
||||||
|
|
||||||
|
use leptos::leptos_dom::log;
|
||||||
|
use leptos::prelude::ServerFnError;
|
||||||
|
use leptos::server;
|
||||||
|
use crate::common::{ComparisonData, ComparisonType, MapListComparison, NumberComparison, NumberListComparison, TextComparison, TextListComparison, ValueType};
|
||||||
|
|
||||||
|
/// Helper function to create all sports comparisons. Only used to create initial
|
||||||
|
/// comparison data, and should be removed upon completion of a comparison editor page.
|
||||||
|
fn create_sports_comparisons() -> Vec<ComparisonData> {
|
||||||
|
vec! [
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_football",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Football".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Football"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_soccer",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Soccer".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Soccer"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_cheerleading",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Cheerleading".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Cheerleading"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_field_hockey",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Field Hockey".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Field Hockey"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_swimming",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Swimming".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Swimming"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_golf",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Golf".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Golf"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_basketball",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Basketball".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Basketball"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_track",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Track".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Track"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_gymnastics",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Gymnastics".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Gymnastics"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_ice_hockey",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Ice Hockey".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Ice Hockey"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_ski",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Ski".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Ski"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_wrestling",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Wrestling".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Wrestling"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_lacrosse",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Lacrosse".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Lacrosse"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_softball",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Softball".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Softball"
|
||||||
|
),
|
||||||
|
ComparisonData::new(
|
||||||
|
"sports_tennis",
|
||||||
|
"sports_participation",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToTextList(
|
||||||
|
"sport_name".to_string(),
|
||||||
|
Box::new(TextListComparison::Contains)
|
||||||
|
)),
|
||||||
|
ValueType::String(Some("Tennis".to_string())),
|
||||||
|
"Sports Participation",
|
||||||
|
"Tennis"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server(CreateTestComparisons, endpoint = "/comparisons/create-test")]
|
||||||
|
pub async fn create_test_comparisons() -> Result<(), ServerFnError> {
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
|
||||||
|
log!("Creating test comparisons");
|
||||||
|
|
||||||
|
let test_comp = ComparisonData::new(
|
||||||
|
"math_sat_comp",
|
||||||
|
"math_sat",
|
||||||
|
ComparisonType::Number(NumberComparison::GreaterThanOrEqual),
|
||||||
|
ValueType::Number(Some(650.to_string())),
|
||||||
|
"Academic Information",
|
||||||
|
"Math SAT Score > 650"
|
||||||
|
);
|
||||||
|
|
||||||
|
let service_hours_25 = ComparisonData::new(
|
||||||
|
"map_sum_comp",
|
||||||
|
"community_involvement",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToNumberList(
|
||||||
|
"service_hours".to_string(),
|
||||||
|
Box::new(NumberListComparison::Sum(
|
||||||
|
Box::new(NumberComparison::GreaterThanOrEqual)
|
||||||
|
))
|
||||||
|
)),
|
||||||
|
ValueType::Number(Some(25.to_string())),
|
||||||
|
"Community Involvement",
|
||||||
|
"25 service hours"
|
||||||
|
);
|
||||||
|
|
||||||
|
let service_hours_20 = ComparisonData::new(
|
||||||
|
"service_hours_20",
|
||||||
|
"community_involvement",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToNumberList(
|
||||||
|
"service_hours".to_string(),
|
||||||
|
Box::new(NumberListComparison::Sum(
|
||||||
|
Box::new(NumberComparison::GreaterThanOrEqual)
|
||||||
|
))
|
||||||
|
)),
|
||||||
|
ValueType::Number(Some(20.to_string())),
|
||||||
|
"Community Involvement",
|
||||||
|
"20 service hours"
|
||||||
|
);
|
||||||
|
|
||||||
|
let service_hours_30 = ComparisonData::new(
|
||||||
|
"service_hours_30",
|
||||||
|
"community_involvement",
|
||||||
|
ComparisonType::MapList(MapListComparison::FlattenToNumberList(
|
||||||
|
"service_hours".to_string(),
|
||||||
|
Box::new(NumberListComparison::Sum(
|
||||||
|
Box::new(NumberComparison::GreaterThanOrEqual)
|
||||||
|
))
|
||||||
|
)),
|
||||||
|
ValueType::Number(Some(30.to_string())),
|
||||||
|
"Community Involvement",
|
||||||
|
"30 service hours"
|
||||||
|
);
|
||||||
|
|
||||||
|
let residency_southbury = ComparisonData::new(
|
||||||
|
"residency_southbury",
|
||||||
|
"town",
|
||||||
|
ComparisonType::Text(TextComparison::Matches),
|
||||||
|
ValueType::String(Some("Southbury".to_string())),
|
||||||
|
"Residency",
|
||||||
|
"Southbury"
|
||||||
|
);
|
||||||
|
|
||||||
|
let residency_middlebury = ComparisonData::new(
|
||||||
|
"residency_middlebury",
|
||||||
|
"town",
|
||||||
|
ComparisonType::Text(TextComparison::Matches),
|
||||||
|
ValueType::String(Some("Middlebury".to_string())),
|
||||||
|
"Residency",
|
||||||
|
"Middlebury"
|
||||||
|
);
|
||||||
|
|
||||||
|
let attended_bas = ComparisonData::new(
|
||||||
|
"attended_bas",
|
||||||
|
"attended_bas",
|
||||||
|
ComparisonType::Text(TextComparison::Matches),
|
||||||
|
ValueType::String(Some("Yes".to_string())),
|
||||||
|
"Miscellaneous",
|
||||||
|
"Attended BAS"
|
||||||
|
);
|
||||||
|
|
||||||
|
let midd_south = ComparisonData::new(
|
||||||
|
"midd_south",
|
||||||
|
"middsouth_church",
|
||||||
|
ComparisonType::Text(TextComparison::Matches),
|
||||||
|
ValueType::String(Some("Yes".to_string())),
|
||||||
|
"Miscellaneous",
|
||||||
|
"Member of Midd-South Church"
|
||||||
|
);
|
||||||
|
|
||||||
|
let family_military = ComparisonData::new(
|
||||||
|
"family_military",
|
||||||
|
"family_military_service",
|
||||||
|
ComparisonType::Text(TextComparison::Matches),
|
||||||
|
ValueType::String(Some("Yes".to_string())),
|
||||||
|
"Miscellaneous",
|
||||||
|
"Family with Military Service"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut sports_comps = create_sports_comparisons();
|
||||||
|
let mut major_comps = Vec::<ComparisonData>::new();
|
||||||
|
|
||||||
|
let mut comp_list = vec![
|
||||||
|
test_comp,
|
||||||
|
service_hours_20,
|
||||||
|
service_hours_25,
|
||||||
|
service_hours_30,
|
||||||
|
residency_middlebury,
|
||||||
|
residency_southbury,
|
||||||
|
attended_bas,
|
||||||
|
midd_south,
|
||||||
|
family_military,
|
||||||
|
];
|
||||||
|
|
||||||
|
comp_list.append(&mut sports_comps);
|
||||||
|
comp_list.append(&mut major_comps);
|
||||||
|
|
||||||
|
for comparison in comp_list {
|
||||||
|
if let Err(err) = client
|
||||||
|
.put_item()
|
||||||
|
.table_name("leptos-comparison-test")
|
||||||
|
.set_item(Some(serde_dynamo::to_item(&comparison)?))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
let msg = err.message().unwrap_or("An unknown error occurred");
|
||||||
|
return Err(ServerFnError::new(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub async fn get_comparison_info() -> Result<Vec<ComparisonData>, ServerFnError> {
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
|
||||||
|
log!("Getting all comparisons from the database");
|
||||||
|
|
||||||
|
// Query the database for all comparisons. The client is only going to use the
|
||||||
|
// id and display text, but we'll return the whole thing.
|
||||||
|
match client
|
||||||
|
.scan()
|
||||||
|
.table_name("leptos-comparison-test")
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(output) => {
|
||||||
|
if let Some(items) = output.items {
|
||||||
|
log!("Found comparisons from API: {:?}", items);
|
||||||
|
Ok(serde_dynamo::from_items(items)?)
|
||||||
|
} else {
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
let msg = err.message().unwrap_or("An unknown error occurred");
|
||||||
|
Err(ServerFnError::new(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
mod comparisons;
|
||||||
|
mod scholarships;
|
||||||
|
|
||||||
|
pub use self::{comparisons::*, scholarships::*};
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use aws_sdk_dynamodb::{
|
||||||
|
types::AttributeValue,
|
||||||
|
error::ProvideErrorMetadata,
|
||||||
|
};
|
||||||
|
|
||||||
|
use leptos::leptos_dom::log;
|
||||||
|
use leptos::prelude::ServerFnError;
|
||||||
|
use leptos::server;
|
||||||
|
use crate::common::ExpandableInfo;
|
||||||
|
|
||||||
|
#[cfg(feature = "ssr")]
|
||||||
|
use crate::pages::utils::server_utils::create_dynamo_client;
|
||||||
|
|
||||||
|
#[server(GetScholarshipInfo, endpoint = "/scholarship/info/get")]
|
||||||
|
pub async fn get_scholarship_info(id: String) -> Result<ExpandableInfo, ServerFnError> {
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
|
||||||
|
// Perform the operation - we just want to return all data that's contained in this entry,
|
||||||
|
// or just return an empty ExpandableInfo struct.
|
||||||
|
log!("Getting scholarship info using id {:?}", id);
|
||||||
|
match client
|
||||||
|
.get_item()
|
||||||
|
.table_name("leptos-scholarship-test")
|
||||||
|
.key("subject", AttributeValue::S(id.clone()))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(output) => {
|
||||||
|
if let Some(item) = output.item {
|
||||||
|
log!("Found output from API: {:?}", item);
|
||||||
|
Ok(serde_dynamo::from_item(item)?)
|
||||||
|
} else {
|
||||||
|
log!("Couldn't find any values, returning default struct.");
|
||||||
|
Ok(ExpandableInfo::new(id.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let msg = err.message().unwrap_or("An unknown error occurred");
|
||||||
|
Err(ServerFnError::new(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server(CreateScholarshipInfo, endpoint = "/scholarship/info/create")]
|
||||||
|
pub async fn create_scholarship_info(info: ExpandableInfo) -> Result<(), ServerFnError> {
|
||||||
|
use crate::pages::utils::server_utils::create_dynamo_client;
|
||||||
|
use aws_sdk_dynamodb::error::ProvideErrorMetadata;
|
||||||
|
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
|
||||||
|
log!("Creating or updating scholarship with ID {:?}", info.subject);
|
||||||
|
|
||||||
|
match client
|
||||||
|
.put_item()
|
||||||
|
.table_name("leptos-scholarship-test")
|
||||||
|
.set_item(Some(serde_dynamo::to_item(&info)?))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
let msg = err.message().unwrap_or("An unknown error occurred");
|
||||||
|
Err(ServerFnError::new(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[server(GetAllScholarshipInfo, endpoint = "/scholarship/info/get-all")]
|
||||||
|
pub async fn get_all_scholarship_info() -> Result<Vec<ExpandableInfo>, ServerFnError> {
|
||||||
|
let client = create_dynamo_client().await;
|
||||||
|
log!("Getting all scholarship info");
|
||||||
|
match client
|
||||||
|
.scan()
|
||||||
|
.table_name("leptos-scholarship-test")
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(output) => {
|
||||||
|
if let Some(items) = output.items {
|
||||||
|
Ok(serde_dynamo::from_items(items)?)
|
||||||
|
} else {
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => {
|
||||||
|
let msg = err.message().unwrap_or("An unknown error occurred");
|
||||||
|
Err(ServerFnError::new(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+113
-39
@@ -1,12 +1,15 @@
|
|||||||
|
use leptos::either::Either;
|
||||||
use super::home_page::get_submission;
|
use super::home_page::get_submission;
|
||||||
use super::UnauthenticatedPage;
|
use super::{UnauthenticatedPage};
|
||||||
use crate::common::{
|
use crate::common::{
|
||||||
ComparisonData, ComparisonType, ExpandableInfo, NumberComparison, UserClaims, ValueType,
|
ComparisonData, ExpandableInfo, UserClaims, ValueType,
|
||||||
};
|
};
|
||||||
use crate::components::{ActionButton, Loading, Panel, Row};
|
use crate::components::{ActionButton, Loading, Panel, Row};
|
||||||
use leptos::leptos_dom::logging::console_log;
|
use leptos::leptos_dom::logging::console_log;
|
||||||
|
use leptos::logging::log;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use leptos_oidc::{Algorithm, AuthLoaded, AuthSignal, Authenticated};
|
use leptos_oidc::{Algorithm, AuthLoaded, AuthSignal, Authenticated};
|
||||||
|
use super::api::{get_comparison_info, get_all_scholarship_info};
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ComparisonTestPage() -> impl IntoView {
|
pub fn ComparisonTestPage() -> impl IntoView {
|
||||||
@@ -23,7 +26,7 @@ pub fn ComparisonTestPage() -> impl IntoView {
|
|||||||
// Note that the value passed in MUST be equatable.
|
// Note that the value passed in MUST be equatable.
|
||||||
// We get/unwrap the value repeatedly until we get a simple string value, then clone it so that
|
// We get/unwrap the value repeatedly until we get a simple string value, then clone it so that
|
||||||
// we don't lose access to it in the future, should we need it again.
|
// we don't lose access to it in the future, should we need it again.
|
||||||
let server_resource: Resource<ExpandableInfo> = Resource::new(
|
let student_resource: Resource<ExpandableInfo> = Resource::new(
|
||||||
move || user_claims.get().map(|claim| claim.claims.subject.clone()),
|
move || user_claims.get().map(|claim| claim.claims.subject.clone()),
|
||||||
async
|
async
|
||||||
| opt_username
|
| opt_username
|
||||||
@@ -36,51 +39,122 @@ pub fn ComparisonTestPage() -> impl IntoView {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let scholarship_resource: Resource<Vec<ExpandableInfo>> = Resource::new(
|
||||||
|
move || Option::<String>::None,
|
||||||
|
async |_| {
|
||||||
|
get_all_scholarship_info().await.unwrap_or_else(|e| {
|
||||||
|
log!("An error occurred: {:?}", e);
|
||||||
|
Vec::new()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let comparison_resource: Resource<Vec<ComparisonData>> = Resource::new(
|
||||||
|
move || Option::<String>::None,
|
||||||
|
async |_| {
|
||||||
|
get_comparison_info().await.unwrap_or_else(|e| {
|
||||||
|
log!("An error occurred: {:?}", e);
|
||||||
|
Vec::new()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<AuthLoaded fallback=Loading>
|
<AuthLoaded fallback=Loading>
|
||||||
<Authenticated unauthenticated=UnauthenticatedPage>
|
<Authenticated unauthenticated=UnauthenticatedPage>
|
||||||
<Suspense fallback=Loading>
|
<Suspense fallback=Loading>
|
||||||
{move || {
|
{move || {
|
||||||
server_resource
|
let student_info = student_resource.get();
|
||||||
.get()
|
let comparison_info = comparison_resource.get();
|
||||||
.map(|response| {
|
let scholarship_info = scholarship_resource.get();
|
||||||
view! {
|
|
||||||
<Panel>
|
match (student_info, comparison_info, scholarship_info) {
|
||||||
<Row>
|
(Some(student), Some(comparisons), Some(scholarships)) => Either::Right(view! {
|
||||||
<p>{result_msg}</p>
|
<Panel>
|
||||||
</Row>
|
<Row>
|
||||||
<Row>
|
<p>{result_msg}</p>
|
||||||
<ActionButton on:click=move |_| {
|
</Row>
|
||||||
let comp = ComparisonData {
|
<Row>
|
||||||
id: "".into(),
|
<ActionButton on:click=move |_| {
|
||||||
member: "math_sat".into(),
|
// Iterate over all scholarships, get the comparison IDs,
|
||||||
target_value: ValueType::Number(Some("800".into())),
|
// get ComparisonData from the IDs, then perform the
|
||||||
comparison: ComparisonType::Number(
|
// comparisons and return a boolean. Alternatively, return
|
||||||
NumberComparison::GreaterThan,
|
// a list of comparisons that complete and a list that don't.
|
||||||
),
|
let comp_member = "requirements".to_string();
|
||||||
category: "".into(),
|
let comparison_results = scholarships.iter().map(|scholarship| {
|
||||||
display_text: "".into(),
|
let list = match scholarship.data.get(&comp_member) {
|
||||||
|
Some(ValueType::List(Some(list))) => list,
|
||||||
|
_ => {
|
||||||
|
log!("Cannot find requirements, assuming none.");
|
||||||
|
return Ok(Some(scholarship)) // students will always qualify when there are no requirements
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let result = comp.compare(&response);
|
|
||||||
match result {
|
let mut final_result = Ok(true);
|
||||||
Ok(val) => {
|
|
||||||
result_msg
|
// The list should exist, and it should contain a series of strings.
|
||||||
.set(
|
for val in list {
|
||||||
format!(
|
let comp_opt = match val {
|
||||||
"member {} is greater than target value {}: {}",
|
ValueType::String(Some(comp_id)) => {
|
||||||
comp.member,
|
// Find the comparison
|
||||||
comp.target_value,
|
comparisons.iter().find(|comp| comp.id == *comp_id)
|
||||||
val,
|
}
|
||||||
),
|
_ => None
|
||||||
)
|
};
|
||||||
|
|
||||||
|
let comparison_outcome = match comp_opt {
|
||||||
|
Some(comp) => {
|
||||||
|
// Perform the comparison
|
||||||
|
comp.compare(&student)
|
||||||
|
}
|
||||||
|
_ => Err("".to_string())
|
||||||
|
};
|
||||||
|
|
||||||
|
match comparison_outcome {
|
||||||
|
Ok(true) => {},
|
||||||
|
Ok(false) => final_result = Ok(false),
|
||||||
|
Err(e) => {
|
||||||
|
final_result = Err(e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(msg) => result_msg.set(msg),
|
|
||||||
}
|
}
|
||||||
}>"Test Comparison"</ActionButton>
|
|
||||||
</Row>
|
match final_result {
|
||||||
</Panel>
|
Ok(true) => Ok(Some(scholarship)),
|
||||||
}
|
Ok(false) => Ok(None),
|
||||||
|
Err(e) => Err(e)
|
||||||
|
}
|
||||||
|
}).collect::<Vec<Result<Option<&ExpandableInfo>, String>>>();
|
||||||
|
|
||||||
|
// Build a display string
|
||||||
|
let mut strings = Vec::new();
|
||||||
|
strings.push("Scholarship results: \n".to_string());
|
||||||
|
for result in comparison_results {
|
||||||
|
match result {
|
||||||
|
Ok(Some(scholarship_info)) => {
|
||||||
|
// Get the scholarship name.
|
||||||
|
let name_member = "name".to_string();
|
||||||
|
let scl_name = scholarship_info.data.get(&name_member).unwrap()
|
||||||
|
.as_string().unwrap().unwrap();
|
||||||
|
strings.push(scl_name);
|
||||||
|
},
|
||||||
|
Ok(None) => {},
|
||||||
|
Err(msg) => strings.push(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let display_text = strings.join("\n").to_string();
|
||||||
|
|
||||||
|
result_msg.set(display_text);
|
||||||
|
}>"Test Comparison"</ActionButton>
|
||||||
|
</Row>
|
||||||
|
</Panel>
|
||||||
|
}),
|
||||||
|
_ => Either::Left(view! {
|
||||||
|
<p>"Failed API requests."</p>
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Authenticated>
|
</Authenticated>
|
||||||
|
|||||||
+4
-52
@@ -13,7 +13,7 @@ use crate::common::{ExpandableInfo, UserClaims};
|
|||||||
use crate::pages::UnauthenticatedPage;
|
use crate::pages::UnauthenticatedPage;
|
||||||
use crate::components::{
|
use crate::components::{
|
||||||
ActionButton, CheckboxList, Loading, MultiEntry, OutlinedTextField, Panel, RadioList, Row,
|
ActionButton, CheckboxList, Loading, MultiEntry, OutlinedTextField, Panel, RadioList, Row,
|
||||||
Select, ChipsList
|
Select
|
||||||
};
|
};
|
||||||
use crate::input;
|
use crate::input;
|
||||||
use leptos::leptos_dom::logging::console_log;
|
use leptos::leptos_dom::logging::console_log;
|
||||||
@@ -305,61 +305,13 @@ pub fn HomePage() -> impl IntoView {
|
|||||||
data_map=expandable_react.data
|
data_map=expandable_react.data
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
|
||||||
<ChipsList
|
|
||||||
data_member="athletic_requirements"
|
|
||||||
data_map=expandable_react.data
|
|
||||||
displayed_text=vec!(
|
|
||||||
"Football", "Soccer", "Cross Country", "Cheerleading",
|
|
||||||
"Swimming", "Wrestling", "Ski", "Basketball",
|
|
||||||
"Lacrosse", "Softball", "Indoor/Outdoor Track",
|
|
||||||
"Golf", "Tennis", "Volleyball"
|
|
||||||
)
|
|
||||||
.into_iter().map(|s| s.to_owned())
|
|
||||||
.collect()
|
|
||||||
values=vec!(
|
|
||||||
"football", "soccer", "cross_country", "cheerleading",
|
|
||||||
"swimming", "wrestling", "ski", "basketball",
|
|
||||||
"lacrosse", "softball", "track",
|
|
||||||
"golf", "tennis", "volleyball"
|
|
||||||
)
|
|
||||||
.into_iter().map(|s| s.to_owned())
|
|
||||||
.collect()
|
|
||||||
disabled=elements_disabled
|
|
||||||
label="Sports/Athletic Requirements"
|
|
||||||
/>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<ChipsList
|
|
||||||
data_member="community_involvement"
|
|
||||||
data_map=expandable_react.data
|
|
||||||
displayed_text=vec!(
|
|
||||||
"Lion's Club", "Knights of Columbus",
|
|
||||||
"Community Service > 20hrs"
|
|
||||||
)
|
|
||||||
.into_iter().map(|s| s.to_owned())
|
|
||||||
.collect()
|
|
||||||
values=vec!(
|
|
||||||
"lions_club", "koc", "serv_20h"
|
|
||||||
)
|
|
||||||
.into_iter().map(|s| s.to_owned())
|
|
||||||
.collect()
|
|
||||||
disabled=elements_disabled
|
|
||||||
label="Required Community Involvement"
|
|
||||||
/>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
<Row>
|
||||||
<MultiEntry
|
<MultiEntry
|
||||||
data_map=expandable_react.data
|
data_map=expandable_react.data
|
||||||
data_member="test"
|
data_member="community_involvement"
|
||||||
name_member="first_name"
|
|
||||||
schema=vec![
|
schema=vec![
|
||||||
input!(Text, "first_name", "First Name:", "John"),
|
input!(Text, "service_name", "Activity Name:", "Some service activity..."),
|
||||||
input!(Text, "last_name", "Last Name:", "Smith"),
|
input!(Number, "service_hours", "Total Service Hours", "20")
|
||||||
input!(Select, "gender", "Gender:", ["Male", "Female"]),
|
|
||||||
input!(
|
|
||||||
Checkbox, "candy", "Favorite Candy:", ["Twizzlers", "Starburst"]
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ mod home_page;
|
|||||||
mod unauthenticated_page;
|
mod unauthenticated_page;
|
||||||
mod scholarship_info;
|
mod scholarship_info;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod api;
|
||||||
|
|
||||||
pub use self::{about_page::*, comparison_test::*, home_page::*, unauthenticated_page::*, scholarship_info::*};
|
pub use self::{about_page::*, comparison_test::*, home_page::*, unauthenticated_page::*, scholarship_info::*};
|
||||||
+111
-157
@@ -1,144 +1,13 @@
|
|||||||
#[cfg(feature = "ssr")]
|
|
||||||
use super::utils::server_utils::create_dynamo_client;
|
|
||||||
|
|
||||||
#[cfg(feature = "ssr")]
|
|
||||||
use aws_sdk_dynamodb::{
|
|
||||||
error::ProvideErrorMetadata,
|
|
||||||
types::AttributeValue,
|
|
||||||
};
|
|
||||||
|
|
||||||
use leptos::logging::log;
|
use leptos::logging::log;
|
||||||
use leptos::prelude::*;
|
use leptos::prelude::*;
|
||||||
use leptos_oidc::{AuthLoaded, Authenticated};
|
use leptos_oidc::{AuthLoaded, Authenticated};
|
||||||
use crate::common::{ComparisonType, ExpandableInfo, NumberComparison, ValueType};
|
use crate::common::ExpandableInfo;
|
||||||
use crate::components::{ActionButton, ChipsList, Loading, OutlinedTextField, Panel, Row};
|
use crate::components::{ActionButton, ChipsList, Loading, OutlinedTextField, Panel, RadioList, Row};
|
||||||
use super::UnauthenticatedPage;
|
use super::UnauthenticatedPage;
|
||||||
use traits::{AsReactive, ReactiveCapture};
|
use traits::{AsReactive, ReactiveCapture};
|
||||||
use crate::common::ComparisonData;
|
use crate::common::ComparisonData;
|
||||||
|
use super::api::{get_comparison_info, get_scholarship_info, CreateScholarshipInfo, CreateTestComparisons};
|
||||||
|
|
||||||
#[server(GetScholarshipInfo, endpoint = "/scholarship/info/get")]
|
|
||||||
pub async fn get_scholarship_info(id: String) -> Result<ExpandableInfo, ServerFnError> {
|
|
||||||
let client = create_dynamo_client().await;
|
|
||||||
|
|
||||||
// Perform the operation - we just want to return all data that's contained in this entry,
|
|
||||||
// or just return an empty ExpandableInfo struct.
|
|
||||||
log!("Getting scholarship info using id {:?}", id);
|
|
||||||
match client
|
|
||||||
.get_item()
|
|
||||||
.table_name("leptos-scholarship-test")
|
|
||||||
.key("subject", AttributeValue::S(id.clone()))
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(output) => {
|
|
||||||
if let Some(item) = output.item {
|
|
||||||
log!("Found output from API: {:?}", item);
|
|
||||||
Ok(serde_dynamo::from_item(item)?)
|
|
||||||
} else {
|
|
||||||
log!("Couldn't find any values, returning default struct.");
|
|
||||||
Ok(ExpandableInfo::new(id.clone()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
let msg = err.message().unwrap_or("An unknown error occurred");
|
|
||||||
Err(ServerFnError::new(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[server(CreateScholarshipInfo, endpoint = "/scholarship/info/create")]
|
|
||||||
pub async fn create_scholarship_info(info: ExpandableInfo) -> Result<(), ServerFnError> {
|
|
||||||
use super::utils::server_utils::create_dynamo_client;
|
|
||||||
use aws_sdk_dynamodb::error::ProvideErrorMetadata;
|
|
||||||
|
|
||||||
let client = create_dynamo_client().await;
|
|
||||||
|
|
||||||
log!("Creating or updating scholarship with ID {:?}", info.subject);
|
|
||||||
|
|
||||||
match client
|
|
||||||
.put_item()
|
|
||||||
.table_name("leptos-scholarship-test")
|
|
||||||
.set_item(Some(serde_dynamo::to_item(&info)?))
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(err) => {
|
|
||||||
let msg = err.message().unwrap_or("An unknown error occurred");
|
|
||||||
Err(ServerFnError::new(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[server]
|
|
||||||
async fn get_comparison_info() -> Result<Vec<ComparisonData>, ServerFnError> {
|
|
||||||
let client = create_dynamo_client().await;
|
|
||||||
|
|
||||||
log!("Getting all comparisons from the database");
|
|
||||||
|
|
||||||
// Query the database for all comparisons. The client is only going to use the
|
|
||||||
// id and display text, but we'll return the whole thing.
|
|
||||||
match client
|
|
||||||
.scan()
|
|
||||||
.table_name("leptos-comparison-test")
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(output) => {
|
|
||||||
if let Some(items) = output.items {
|
|
||||||
log!("Found comparisons from API: {:?}", items);
|
|
||||||
Ok(serde_dynamo::from_items(items)?)
|
|
||||||
} else {
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
let msg = err.message().unwrap_or("An unknown error occurred");
|
|
||||||
Err(ServerFnError::new(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[server(CreateTestComparisons, endpoint = "/comparisons/create-test")]
|
|
||||||
async fn create_test_comparisons() -> Result<(), ServerFnError> {
|
|
||||||
let client = create_dynamo_client().await;
|
|
||||||
|
|
||||||
log!("Creating test comparisons");
|
|
||||||
|
|
||||||
let test_comp = ComparisonData::new(
|
|
||||||
"comp1",
|
|
||||||
"unweighted_gpa",
|
|
||||||
ComparisonType::Number(NumberComparison::GreaterThanOrEqual),
|
|
||||||
ValueType::Number(Some(3.2.to_string())),
|
|
||||||
"Testing",
|
|
||||||
"GPA > 3.2"
|
|
||||||
);
|
|
||||||
|
|
||||||
let _comp_list = vec![
|
|
||||||
ComparisonData::new(
|
|
||||||
"comp1",
|
|
||||||
"unweighted_gpa",
|
|
||||||
ComparisonType::Number(NumberComparison::GreaterThanOrEqual),
|
|
||||||
ValueType::Number(Some(3.2.to_string())),
|
|
||||||
"Testing",
|
|
||||||
"GPA > 3.2"
|
|
||||||
)
|
|
||||||
];
|
|
||||||
|
|
||||||
match client
|
|
||||||
.put_item()
|
|
||||||
.table_name("leptos-comparison-test")
|
|
||||||
.set_item(Some(serde_dynamo::to_item(&test_comp)?))
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => Ok(()),
|
|
||||||
Err(err) => {
|
|
||||||
let msg = err.message().unwrap_or("An unknown error occurred");
|
|
||||||
Err(ServerFnError::new(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # Scholarship Info Page
|
/// # Scholarship Info Page
|
||||||
/// This page will handle creating or editing scholarship information given a specific
|
/// This page will handle creating or editing scholarship information given a specific
|
||||||
@@ -150,18 +19,18 @@ async fn create_test_comparisons() -> Result<(), ServerFnError> {
|
|||||||
/// changed before a full release.
|
/// changed before a full release.
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ScholarshipInfoPage() -> impl IntoView {
|
pub fn ScholarshipInfoPage() -> impl IntoView {
|
||||||
let scholarship_id = String::from("test-scholarship-id");
|
let scholarship_id = String::from("test-scholarship-id2");
|
||||||
|
|
||||||
let get_scholarship_action: Resource<ExpandableInfo> = Resource::new(
|
let get_scholarship_action: Resource<ExpandableInfo> = Resource::new(
|
||||||
move || scholarship_id.clone(),
|
move || scholarship_id.clone(),
|
||||||
async |id| {
|
async |id| {
|
||||||
get_scholarship_info(id).await
|
get_scholarship_info(id.clone()).await
|
||||||
// Note that this really should notify us of an error and then redirect or ask
|
// Note that this really should notify us of an error and then redirect or ask
|
||||||
// the user to try again.
|
// the user to try again.
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
log!("Failed to get scholarship info: {:?}", e);
|
log!("Failed to get scholarship info: {:?}", e);
|
||||||
log!("Using default ExpandableInfo");
|
log!("Using default ExpandableInfo");
|
||||||
ExpandableInfo::new("test-scholarship-id")
|
ExpandableInfo::new(id)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -186,27 +55,33 @@ pub fn ScholarshipInfoPage() -> impl IntoView {
|
|||||||
<AuthLoaded fallback=Loading>
|
<AuthLoaded fallback=Loading>
|
||||||
<Authenticated unauthenticated=UnauthenticatedPage>
|
<Authenticated unauthenticated=UnauthenticatedPage>
|
||||||
<Suspense fallback=Loading>
|
<Suspense fallback=Loading>
|
||||||
{move || Suspend::new(async move {
|
|
||||||
let response = get_scholarship_action.get();
|
|
||||||
let comparisons = get_comparison_info.get();
|
|
||||||
|
|
||||||
response
|
|
||||||
.zip(comparisons)
|
|
||||||
.map(|(response, comparison_list)| view! {
|
|
||||||
<ScholarshipForm
|
|
||||||
response=response
|
|
||||||
comparison_list=comparison_list
|
|
||||||
submit_action=create_scholarship_action
|
|
||||||
/>
|
|
||||||
})
|
|
||||||
.collect_view()
|
|
||||||
})}
|
|
||||||
<Row>
|
<Row>
|
||||||
<ActionButton
|
<div class="flex flex-col flex-1" />
|
||||||
on:click=move |_| {
|
{move || Suspend::new(async move {
|
||||||
create_test_comps.dispatch(CreateTestComparisons {});
|
let response = get_scholarship_action.get();
|
||||||
}
|
let comparisons = get_comparison_info.get();
|
||||||
>"Create test comparisons"</ActionButton>
|
|
||||||
|
response
|
||||||
|
.zip(comparisons)
|
||||||
|
.map(|(response, comparison_list)| view! {
|
||||||
|
<ScholarshipForm
|
||||||
|
response=response
|
||||||
|
comparison_list=comparison_list
|
||||||
|
submit_action=create_scholarship_action
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
.collect_view()
|
||||||
|
})}
|
||||||
|
<div class="hidden">
|
||||||
|
<Row>
|
||||||
|
<ActionButton
|
||||||
|
on:click=move |_| {
|
||||||
|
create_test_comps.dispatch(CreateTestComparisons {});
|
||||||
|
}
|
||||||
|
>"Create test comparisons"</ActionButton>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col flex-1" />
|
||||||
</Row>
|
</Row>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Authenticated>
|
</Authenticated>
|
||||||
@@ -241,6 +116,10 @@ fn ScholarshipForm(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// We'll collect the scholarship's name, num_awards, amount_per_award, total_awards,
|
||||||
|
// fafsa_required, award_to, transcript_required, recipient_selection, essay_requirement (and prompt)
|
||||||
|
// award_night_remarks
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Panel>
|
<Panel>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -257,6 +136,81 @@ fn ScholarshipForm(
|
|||||||
data_map=reactive_info.data
|
data_map=reactive_info.data
|
||||||
/>
|
/>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<OutlinedTextField
|
||||||
|
label="Amount per award: (if multiple, enter the highest value)"
|
||||||
|
placeholder="Enter an amount..."
|
||||||
|
disabled=elements_disabled
|
||||||
|
data_member="amount_per_award"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
input_type="number"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<OutlinedTextField
|
||||||
|
label="Total number of awards:"
|
||||||
|
placeholder="Enter an amount..."
|
||||||
|
disabled=elements_disabled
|
||||||
|
data_member="num_awards"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
input_type="number"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<OutlinedTextField
|
||||||
|
label="Total amount of all awards:"
|
||||||
|
placeholder="Enter an amount..."
|
||||||
|
disabled=elements_disabled
|
||||||
|
data_member="total_awards"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
input_type="number"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<RadioList
|
||||||
|
data_member="fafsa_required"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
items=vec!["Yes".to_string(), "No".to_string()]
|
||||||
|
disabled=elements_disabled
|
||||||
|
label="Do you require student financial information?"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<RadioList
|
||||||
|
data_member="transcript_required"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
items=vec!["Yes".to_string(), "No".to_string()]
|
||||||
|
disabled=elements_disabled
|
||||||
|
label="Do you require a student transcript?"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<RadioList
|
||||||
|
data_member="award_to"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
items=vec!["School".to_string(), "Student".to_string()]
|
||||||
|
disabled=elements_disabled
|
||||||
|
label="Will the award be made to the school or the student?"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<RadioList
|
||||||
|
data_member="essay_required"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
items=vec!["Yes".to_string(), "No".to_string()]
|
||||||
|
disabled=elements_disabled
|
||||||
|
label="Do you require a student essay?"
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<RadioList
|
||||||
|
data_member="essay_prompt"
|
||||||
|
data_map=reactive_info.data
|
||||||
|
items=vec!["Test 1", "Test 2", "Test 3"].iter().map(|s| s.to_string()).collect()
|
||||||
|
disabled=elements_disabled
|
||||||
|
label="If so, select a prompt from the list below."
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<ChipsList
|
<ChipsList
|
||||||
label="Scholarship Requirements"
|
label="Scholarship Requirements"
|
||||||
|
|||||||
Reference in new issue
Block a user