diff --git a/src/api/v1/notifications/get.rs b/src/api/v1/notifications/get.rs index 91ad991d..3dbad32f 100644 --- a/src/api/v1/notifications/get.rs +++ b/src/api/v1/notifications/get.rs @@ -51,6 +51,7 @@ impl From for NotificationResp { } } } + /// route handler that gets all unread notifications #[my_codegen::get( path = "crate::V1_API_ROUTES.notifications.get", @@ -63,7 +64,14 @@ pub async fn get_notification( let receiver = id.identity().unwrap(); // TODO handle error where payload.to doesnt exist - let resp = runner::get_notification(&data, &receiver).await?; + let mut notifications = runner::get_notification(&data, &receiver).await?; + let resp: Vec = notifications + .drain(0..) + .map(|x| { + let y: NotificationResp = x.into(); + y + }) + .collect(); Ok(HttpResponse::Ok().json(resp)) } @@ -73,10 +81,10 @@ pub mod runner { pub async fn get_notification( data: &AppData, receiver: &str, - ) -> ServiceResult> { + ) -> ServiceResult> { // TODO handle error where payload.to doesnt exist - let mut notifications = sqlx::query_file_as!( + let notifications = sqlx::query_file_as!( Notification, "src/api/v1/notifications/get_all_unread.sql", &receiver @@ -84,15 +92,7 @@ pub mod runner { .fetch_all(&data.db) .await?; - let resp = notifications - .drain(0..) - .map(|x| { - let y: NotificationResp = x.into(); - y - }) - .collect(); - - Ok(resp) + Ok(notifications) } } diff --git a/src/pages/panel/notifications.rs b/src/pages/panel/notifications.rs index abeac243..e8258ee0 100644 --- a/src/pages/panel/notifications.rs +++ b/src/pages/panel/notifications.rs @@ -18,24 +18,72 @@ use actix_identity::Identity; use actix_web::{HttpResponse, Responder}; use sailfish::TemplateOnce; +use sqlx::types::time::OffsetDateTime; -use crate::api::v1::notifications::get::{runner, NotificationResp}; +use crate::api::v1::notifications::get::{self, runner}; use crate::errors::PageResult; use crate::AppData; +const MINUTE: i64 = 60; +const HOUR: i64 = MINUTE * 60; +const DAY: i64 = HOUR * 24; +const WEEK: i64 = DAY * 7; + #[derive(TemplateOnce)] #[template(path = "panel/notifications/index.html")] pub struct IndexPage { /// notifications - n: Vec, + n: Vec, } impl IndexPage { - fn new(n: Vec) -> Self { + fn new(n: Vec) -> Self { IndexPage { n } } } +pub struct Notification { + pub name: String, + pub heading: String, + pub message: String, + pub received: OffsetDateTime, + pub id: i32, +} + +impl From for Notification { + fn from(n: get::Notification) -> Self { + Notification { + name: n.name.unwrap(), + heading: n.heading.unwrap(), + received: n.received.unwrap(), + id: n.id.unwrap(), + message: n.message.unwrap(), + } + } +} + +impl Notification { + pub fn print_date(&self) -> String { + let date = self.received; + let timestamp = self.received.unix_timestamp(); + let now = OffsetDateTime::now_utc().unix_timestamp(); + + let difference = now - timestamp; + + if difference >= 3 * WEEK { + date.format("%d-%m-%y") + } else if (DAY..(3 * WEEK)).contains(&difference) { + format!("{} days ago", date.hour()) + } else if (HOUR..DAY).contains(&difference) { + format!("{} hours ago", date.hour()) + } else if (MINUTE..HOUR).contains(&difference) { + format!("{} minutes ago", date.minute()) + } else { + format!("{} seconds ago", date.second()) + } + } +} + const PAGE: &str = "Notifications"; #[my_codegen::get(path = "crate::PAGES.panel.notifications", wrap = "crate::CheckLogin")] @@ -43,10 +91,56 @@ pub async fn notifications(data: AppData, id: Identity) -> PageResult

<.= notification.message .>

<.= notification.name .> - . - <.= notification.received .> + · + <.= notification.print_date() .>
diff --git a/templates/panel/notifications/main.scss b/templates/panel/notifications/main.scss index d0ec94cf..a6c4faec 100644 --- a/templates/panel/notifications/main.scss +++ b/templates/panel/notifications/main.scss @@ -20,12 +20,12 @@ .notification__table { background-color: $white; width: 90%; + padding: 0 10px; } .notification__title-text { - padding-left: 10px; font-size: 1rem; - padding: 0.75rem 1.25rem; + padding: 0.75rem 0.5rem; box-sizing: border-box; text-align: left; width: 100%;