diff --git a/src/common/date_info.rs b/src/common/date_info.rs index fbd508a..269c300 100644 --- a/src/common/date_info.rs +++ b/src/common/date_info.rs @@ -1,14 +1,20 @@ -use chrono::{DateTime, FixedOffset}; +use chrono::{DateTime, FixedOffset, Local}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DateInfo { - #[serde()] - pub(crate) title: String, - #[serde(rename = "date")] - pub(crate) date: DateRange, - #[serde(rename = "desc")] - pub(crate) description: String, + pub id: String, + pub title: String, + pub date: DateRange, + pub description: String, +} + +impl DateInfo { + pub fn get_start_date(&self) -> DateTime { + match self.date { + DateRange::Single(date) | DateRange::Range(date, _) => date, + } + } } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -17,11 +23,41 @@ pub enum DateRange { Range(DateTime, DateTime), } -#[derive(Debug, Clone, Serialize, Deserialize)] +impl DateRange { + pub fn get_status(&self) -> DateStatus { + match self { + DateRange::Single(_) => DateStatus::Blank, + DateRange::Range(start_date, end_date) => { + let local = Local::now(); + // Check the amount of time from now to the start date. Values that are negative + // indicate that the start date has already passed. + if dbg!(start_date.signed_duration_since(local).num_days()) > 0 { + DateStatus::Upcoming + } else { + // Check the amount of time from now to the end date. The value will be positive if + // the end date is in the future. We will be specific to the minute. + let duration_until = dbg!(end_date).signed_duration_since(local); + let num_days = dbg!(duration_until.num_days()); + let num_mins = dbg!(duration_until.num_minutes()); + + if num_mins <= 0 { + DateStatus::Closed + } else if num_days <= 5 { + DateStatus::Deadline + } else { + DateStatus::Open + } + } + } + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Ord)] pub enum DateStatus { + Closed, + Deadline, + Open, + Upcoming, Blank, - Upcoming, - Open, - Deadline, - Closed, } diff --git a/src/components/date.rs b/src/components/date.rs index 541aed2..88c66f8 100644 --- a/src/components/date.rs +++ b/src/components/date.rs @@ -1,4 +1,3 @@ -use chrono::Local; use crate::common::{DateInfo, DateRange, DateStatus}; use leptos::prelude::*; @@ -15,40 +14,8 @@ fn render_dates(dates: DateRange) -> impl IntoView { view! { {move || date_text.clone()} } } -fn get_date_status(date: &DateRange) -> DateStatus { - // We need a threshold - maybe within 5 days, the status is deadline, - // further away is open, upcoming is when the range has not started yet, - // and closed is past the date. - - match date { - DateRange::Single(_) => DateStatus::Blank, - DateRange::Range(start_date, end_date) => { - let local = Local::now(); - // Check the amount of time from now to the start date. Values that are negative - // indicate that the start date has already passed. - if dbg!(start_date.signed_duration_since(local).num_days()) > 0 { - DateStatus::Upcoming - } else { - // Check the amount of time from now to the end date. The value will be positive if - // the end date is in the future. We will be specific to the minute. - let duration_until = dbg!(end_date).signed_duration_since(local); - let num_days = dbg!(duration_until.num_days()); - let num_mins = dbg!(duration_until.num_minutes()); - - if num_mins <= 0 { - DateStatus::Closed - } else if num_days <= 5 { - DateStatus::Deadline - } else { - DateStatus::Open - } - } - } - } -} - fn render_status(date: DateRange) -> impl IntoView { - let status = get_date_status(&date); + let status = date.get_status(); let status_text = match dbg!(status.clone()) { DateStatus::Blank => "", @@ -141,11 +108,12 @@ fn Date( /// ``` #[component] pub fn DateList( - #[prop(into)] dates: Vec, + #[prop(into)] dates: Signal>, ) -> impl IntoView { view! { {move || { dates + .get() .iter() .map(|info| { view! { } diff --git a/src/pages/api/mod.rs b/src/pages/api/mod.rs index e13ff2b..f7aa9bf 100644 --- a/src/pages/api/mod.rs +++ b/src/pages/api/mod.rs @@ -1,4 +1,7 @@ mod comparisons; +pub use comparisons::*; mod scholarships; +pub use scholarships::*; +mod dates; +pub use dates::*; -pub use self::{comparisons::*, scholarships::*}; diff --git a/src/pages/test_page.rs b/src/pages/test_page.rs index 546c41e..6000eea 100644 --- a/src/pages/test_page.rs +++ b/src/pages/test_page.rs @@ -1,10 +1,100 @@ use chrono::DateTime; use crate::common::{DateInfo, DateRange}; -use crate::components::{DashboardButton, DateList}; +use crate::components::{ActionButton, DashboardButton, DateList}; use leptos::prelude::*; +use crate::pages::api::{get_important_dates, CreateDates}; #[component] pub fn TestPage() -> impl IntoView { + let reload_signal = RwSignal::new(0); + + let dates_resource = Resource::new( + move || reload_signal.get(), + async move |_| { + get_important_dates().await + } + ); + + let dates_list = RwSignal::new(Vec::new()); + + Effect::new(move || { + if let Some(Ok(mut dates)) = dates_resource.get() { + dates.sort_by_key(|info| info.date.get_status()); + dates_list.set(dates); + } + }); + + let create_dates = ServerAction::::new(); + + let on_click = move |_| { + let dates_list = vec![ + DateInfo { + id: uuid::Uuid::new_v4().to_string(), + title: "Open Example".to_string(), + date: DateRange::Range( + DateTime::parse_from_rfc3339("2026-01-15T07:15:00-05:00") + .unwrap_or_default(), + DateTime::parse_from_rfc3339("2026-01-30T14:05:00-05:00") + .unwrap_or_default() + ), + description: "This is a test".to_string(), + }, + DateInfo { + id: uuid::Uuid::new_v4().to_string(), + title: "Closed Example".to_string(), + date: DateRange::Range( + DateTime::parse_from_rfc3339("2026-01-01T07:15:00-05:00") + .unwrap_or_default(), + DateTime::parse_from_rfc3339("2026-01-14T14:05:00-05:00") + .unwrap_or_default() + ), + description: "".to_string(), + }, + DateInfo { + id: uuid::Uuid::new_v4().to_string(), + title: "Deadline Example".to_string(), + date: DateRange::Range( + DateTime::parse_from_rfc3339("2026-01-15T07:15:00-05:00") + .unwrap_or_default(), + DateTime::parse_from_rfc3339("2026-01-20T14:05:00-05:00") + .unwrap_or_default() + ), + description: "This is a test".to_string(), + }, + DateInfo { + id: uuid::Uuid::new_v4().to_string(), + title: "Upcoming Example".to_string(), + date: DateRange::Range( + DateTime::parse_from_rfc3339("2026-01-30T07:15:00-05:00") + .unwrap_or_default(), + DateTime::parse_from_rfc3339("2026-02-20T14:05:00-05:00") + .unwrap_or_default() + ), + description: "This is a test".to_string(), + }, + DateInfo { + id: uuid::Uuid::new_v4().to_string(), + title: "Single Date (Blank)".to_string(), + date: DateRange::Single( + DateTime::parse_from_rfc3339("2026-01-15T14:05:00-05:00") + .unwrap_or_default() + ), + description: "".to_string(), + } + ]; + + create_dates.dispatch(CreateDates { + dates: dates_list + }); + }; + + Effect::new(move || { + if let Some(Ok(_)) = create_dates.value().get() { + create_dates.clear(); + reload_signal.update(|v| *v += 1); + } + }); + view! {
@@ -36,60 +126,14 @@ pub fn TestPage() -> impl IntoView {
- +
+
+ "Create Dates List" +