Merge pull request #56 from R15-Software-Dev/feat/table-changes

Final provider changes
This commit was merged in pull request #56.
This commit is contained in:
Lucas Vas authored and GitHub committed 2026-01-19 14:44:27 -05:00
commit 032e978a34
9 files changed
+103 -53

No files matched your search

+3 -2
View File
@@ -1,4 +1,4 @@
use crate::pages::{ProviderPortal, ScholarshipInfoPage, ProviderContactPage, LoanerShell, LoanerFallback, LoanerBorrowForm, LoanerReturnForm, AuthCallbackPage}; use crate::pages::{ProviderPortal, ScholarshipInfoPage, ProviderContactPage, LoanerShell, LoanerFallback, LoanerBorrowForm, LoanerReturnForm, AuthCallbackPage, ApplicantsPageFallback};
use leptos::prelude::*; use leptos::prelude::*;
use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context}; use leptos_meta::{MetaTags, Stylesheet, Title, provide_meta_context};
use leptos_oidc::AuthSignal; use leptos_oidc::AuthSignal;
@@ -73,8 +73,9 @@ pub fn AppWithRoutes() -> impl IntoView {
fn ProviderRoutes() -> impl MatchNestedRoutes + Clone { fn ProviderRoutes() -> impl MatchNestedRoutes + Clone {
view! { view! {
<ParentRoute path=path!("/providers") view=ProviderLoginContext> <ParentRoute path=path!("/providers") view=ProviderLoginContext>
<Route path=path!("/callback") view=AuthCallbackPage />
<Route path=path!("") view=ProviderPortal /> <Route path=path!("") view=ProviderPortal />
<Route path=path!("/applicants") view=ApplicantsPageFallback />
<Route path=path!("/callback") view=AuthCallbackPage />
<Route path=path!("/profile") view=ProviderContactPage /> <Route path=path!("/profile") view=ProviderContactPage />
<ParentRoute path=path!("/scholarships") view=ScholarshipInfoPage> <ParentRoute path=path!("/scholarships") view=ScholarshipInfoPage>
<Route path=path!(":id") view=ScholarshipInfoPage /> <Route path=path!(":id") view=ScholarshipInfoPage />
+1 -1
View File
@@ -16,7 +16,7 @@ use leptos::prelude::ServerFnError;
use leptos::server; use leptos::server;
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
static COMPARISONS_TABLE: &str = "leptos-comparison-test"; static COMPARISONS_TABLE: &str = "leptos-comparisons";
/// Helper function to create all sports comparisons. Only used to create initial /// 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. /// comparison data, and should be removed upon completion of a comparison editor page.
+5 -2
View File
@@ -12,13 +12,16 @@ use aws_sdk_dynamodb::{
Client as DynamoClient Client as DynamoClient
}; };
#[cfg(feature = "ssr")]
use crate::utils::server::create_dynamo_client;
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
use std::sync::Arc; use std::sync::Arc;
#[server] #[server]
pub async fn create_dates(dates: Vec<DateInfo>) -> Result<(), ServerFnError> { pub async fn create_dates(dates: Vec<DateInfo>) -> Result<(), ServerFnError> {
// Serialize and put dates into the database. // Serialize and put dates into the database.
let client = expect_context::<Arc<DynamoClient>>(); let client = create_dynamo_client().await;
log!("Creating dates: {:?}", dates); log!("Creating dates: {:?}", dates);
@@ -51,7 +54,7 @@ pub async fn create_dates(dates: Vec<DateInfo>) -> Result<(), ServerFnError> {
#[server] #[server]
pub async fn get_important_dates() -> Result<Vec<DateInfo>, ServerFnError> { pub async fn get_important_dates() -> Result<Vec<DateInfo>, ServerFnError> {
let client = expect_context::<Arc<DynamoClient>>(); let client = create_dynamo_client().await;
client client
.scan() .scan()
+9 -10
View File
@@ -18,9 +18,9 @@ use leptos::prelude::ServerFnError;
use leptos::server; use leptos::server;
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
static SCHOLARSHIPS_TABLE: &str = "leptos-scholarship-test"; static SCHOLARSHIPS_TABLE: &str = "leptos-scholarships";
#[server(GetScholarshipInfo, endpoint = "/scholarship/info/get")] #[server(GetScholarshipInfo)]
pub async fn get_scholarship_info(id: String) -> Result<ExpandableInfo, ServerFnError> { pub async fn get_scholarship_info(id: String) -> Result<ExpandableInfo, ServerFnError> {
let client = create_dynamo_client().await; let client = create_dynamo_client().await;
@@ -50,7 +50,7 @@ pub async fn get_scholarship_info(id: String) -> Result<ExpandableInfo, ServerFn
} }
} }
#[server(CreateScholarshipInfo, endpoint = "/scholarship/info/create")] #[server(CreateScholarshipInfo)]
pub async fn create_scholarship_info(info: ExpandableInfo) -> Result<(), ServerFnError> { pub async fn create_scholarship_info(info: ExpandableInfo) -> Result<(), ServerFnError> {
use aws_sdk_dynamodb::error::ProvideErrorMetadata; use aws_sdk_dynamodb::error::ProvideErrorMetadata;
@@ -73,7 +73,7 @@ pub async fn create_scholarship_info(info: ExpandableInfo) -> Result<(), ServerF
} }
} }
#[server(GetAllScholarshipInfo, endpoint = "/scholarship/info/get-all")] #[server(GetAllScholarshipInfo)]
pub async fn get_all_scholarship_info() -> Result<Vec<ExpandableInfo>, ServerFnError> { pub async fn get_all_scholarship_info() -> Result<Vec<ExpandableInfo>, ServerFnError> {
let client = create_dynamo_client().await; let client = create_dynamo_client().await;
log!("Getting all scholarship info"); log!("Getting all scholarship info");
@@ -98,7 +98,7 @@ pub async fn get_all_scholarship_info() -> Result<Vec<ExpandableInfo>, ServerFnE
} }
/// Gets all scholarships that are associated with the given scholarship provider's ID. /// Gets all scholarships that are associated with the given scholarship provider's ID.
#[server(GetProviderScholarships, "/providers/scholarships/get")] #[server(GetProviderScholarships)]
pub async fn get_provider_scholarships(provider_id: String) -> Result<Vec<ExpandableInfo>, ServerFnError> { pub async fn get_provider_scholarships(provider_id: String) -> Result<Vec<ExpandableInfo>, ServerFnError> {
let client = create_dynamo_client().await; let client = create_dynamo_client().await;
@@ -127,16 +127,15 @@ pub async fn get_provider_scholarships(provider_id: String) -> Result<Vec<Expand
} }
/// Creates a new scholarship with a unique ID, and then returns that ID. /// Creates a new scholarship with a unique ID, and then returns that ID.
#[server(RegisterScholarship, "/providers/scholarships/create")] #[server(RegisterScholarship)]
pub async fn register_scholarship(provider_id: String, scholarship_name: String) -> Result<String, ServerFnError> { pub async fn register_scholarship(provider_id: String) -> Result<String, ServerFnError> {
let client = create_dynamo_client().await; let client = create_dynamo_client().await;
log!("Creating scholarship for provider with ID {:?}", provider_id); log!("Creating scholarship for provider with ID {:?}", provider_id);
let mut current_uuid = "testing".to_string(); let mut current_uuid = Uuid::new_v4().to_string();
let mut item = ExpandableInfo::new(current_uuid.clone()); let mut item = ExpandableInfo::new(current_uuid.clone());
item.data.insert("provider_id".to_string(), ValueType::String(Some(provider_id))); item.data.insert("provider_id".to_string(), ValueType::String(Some(provider_id)));
item.data.insert("scholarship_name".to_string(), ValueType::String(Some(scholarship_name)));
loop { loop {
let ser_item = serde_dynamo::to_item(&item)?; let ser_item = serde_dynamo::to_item(&item)?;
match client match client
@@ -172,7 +171,7 @@ pub async fn register_scholarship(provider_id: String, scholarship_name: String)
} }
/// Deletes a provider's scholarship given their provider ID and scholarship ID. /// Deletes a provider's scholarship given their provider ID and scholarship ID.
#[server(DeleteProviderScholarship, "/providers/scholarships/delete")] #[server(DeleteProviderScholarship)]
pub async fn delete_provider_scholarship(provider_id: String, scholarship_id: String) -> Result<(), ServerFnError> { pub async fn delete_provider_scholarship(provider_id: String, scholarship_id: String) -> Result<(), ServerFnError> {
let client = create_dynamo_client().await; let client = create_dynamo_client().await;
+2 -1
View File
@@ -9,9 +9,10 @@ mod test_page;
mod unauthenticated_page; mod unauthenticated_page;
mod provider_contact; mod provider_contact;
mod auth_callback; mod auth_callback;
mod provider_applicants;
pub use self::{ pub use self::{
about_page::*, comparison_test::*, home_page::*, loaner_page::*, provider_portal::*, about_page::*, comparison_test::*, home_page::*, loaner_page::*, provider_portal::*,
test_page::*, unauthenticated_page::*, scholarship_info::*, provider_contact::*, test_page::*, unauthenticated_page::*, scholarship_info::*, provider_contact::*,
auth_callback::*, auth_callback::*, provider_applicants::*
}; };
+15
View File
@@ -0,0 +1,15 @@
use leptos::prelude::*;
use crate::components::Banner;
#[component]
pub fn ApplicantsPageFallback() -> impl IntoView {
view! {
<Banner title="R15 Scholarships" logo="/PHS_Stacked_Acronym.png" path="/providers" />
<div class="flex flex-col gap-4 mt-3 items-center justify-center">
<h1 class="text-3xl font-bold">"Applicants Page"</h1>
<p>"This page is under construction! It will show all the students that are eligible for your scholarship(s)."</p>
<p>"Come back soon!"</p>
</div>
}
}
+1 -1
View File
@@ -43,7 +43,7 @@ pub fn ProviderPortal() -> impl IntoView {
title="Applicants" title="Applicants"
description="View Scholarship Applicants" description="View Scholarship Applicants"
icon="/Form_Black.png" icon="/Form_Black.png"
path="/" path="/providers/applicants"
/> />
</section> </section>
<section class="space-y-4"> <section class="space-y-4">
+1 -2
View File
@@ -128,8 +128,7 @@ fn ScholarshipList(
// Button handlers // Button handlers
let create_on_click = move |_| { let create_on_click = move |_| {
create_action.dispatch(RegisterScholarship { create_action.dispatch(RegisterScholarship {
provider_id: provider_id.get().unwrap(), provider_id: provider_id.get().unwrap()
scholarship_name: "Testing Scholarship".to_string()
}); });
}; };
+66 -34
View File
@@ -1,43 +1,75 @@
use crate::components::DashboardButton; use chrono::DateTime;
use crate::components::ActionButton;
use leptos::prelude::*; use leptos::prelude::*;
use crate::common::{DateInfo, DateRange};
use crate::pages::api::{CreateDates, CreateTestComparisons};
fn get_important_dates() -> Vec<DateInfo> {
vec! [
DateInfo {
id: uuid::Uuid::new_v4().to_string(),
title: "Provider Forms Open".to_string(),
date: DateRange::Range(
DateTime::parse_from_rfc3339("2026-01-20T07:15:00-05:00").unwrap(),
DateTime::parse_from_rfc3339("2026-03-03T23:59:00-05:00").unwrap()
),
description: "".to_string(),
},
DateInfo {
id: uuid::Uuid::new_v4().to_string(),
title: "Student Forms Open".to_string(),
date: DateRange::Range(
DateTime::parse_from_rfc3339("2026-03-03T07:15:00-05:00").unwrap(),
DateTime::parse_from_rfc3339("2026-03-27T14:05:00-05:00").unwrap()
),
description: "".to_string(),
},
DateInfo {
id: uuid::Uuid::new_v4().to_string(),
title: "Scholarship Decision Window".to_string(),
date: DateRange::Range(
DateTime::parse_from_rfc3339("2026-04-10T07:15:00-05:00").unwrap(),
DateTime::parse_from_rfc3339("2026-05-01T23:59:00-05:00").unwrap()
),
description: "Start date may change if available sooner.".to_string(),
},
DateInfo {
id: uuid::Uuid::new_v4().to_string(),
title: "PHS Scholarship Committee".to_string(),
date: DateRange::Single(
DateTime::parse_from_rfc3339("2026-05-18T00:00:00-05:00").unwrap(),
),
description: "Time TBD".to_string(),
},
DateInfo {
id: uuid::Uuid::new_v4().to_string(),
title: "Scholarship and Awards Night".to_string(),
date: DateRange::Single(
DateTime::parse_from_rfc3339("2026-06-09T00:00:00-05:00").unwrap(),
),
description: "Time TBD".to_string(),
},
]
}
#[component] #[component]
pub fn TestPage() -> impl IntoView { pub fn TestPage() -> impl IntoView {
let create_comparisons = ServerAction::<CreateTestComparisons>::new();
let create_dates = ServerAction::<CreateDates>::new();
let on_click_comparisons = move |_| {
create_comparisons.dispatch(CreateTestComparisons{});
};
let on_click_dates = move |_| {
create_dates.dispatch(CreateDates{dates: get_important_dates()});
};
view! { view! {
<div class="mx-auto px-6"> <div class="mx-auto px-6">
<div class="container mx-auto px-6 py-8 space-y-8"> <div class="flex flex-col gap-4">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <ActionButton on:click=on_click_comparisons>"Create Comparisons"</ActionButton>
<section class="space-y-4"> <ActionButton on:click=on_click_dates>"Create Dates"</ActionButton>
<DashboardButton
title="Profile"
description="Edit user profile"
icon="/Person_Black.png"
path="/"
/>
<DashboardButton
title="Create Scholarship"
description="Navigate to Scholarship Creation Page"
icon="/Create_Black.png"
path="/"
/>
<DashboardButton
title="Applicants"
description="View Scholarship Applicants"
icon="/Form_Black.png"
path="/"
/>
</section>
<section class="space-y-2">
<div class="rounded-lg shadow-lg/25 overflow-hidden">
<div class="bg-red-900 text-white px-4 py-3 shadow-lg">
<h3 class="text-white font-bold">Important Dates</h3>
</div>
<div class="p-2">
<div class="flex flex-col p-3 gap-3"></div>
</div>
</div>
</section>
</div>
</div> </div>
</div> </div>
}.into_any() }.into_any()