From 9dde7cd945f249fd82a4306d2b29d6b6858083d5 Mon Sep 17 00:00:00 2001 From: Ada Werefox Date: Mon, 25 Mar 2024 20:42:59 -0500 Subject: [PATCH] HRT tracker page works, but with the caveat of being on the UTC time offset. This needs to be fixed eventually. --- Cargo.toml | 5 + public/tailwind.css | 77 +++++++++++++++ src/components.rs | 3 +- src/components/back_button.rs | 2 +- src/components/basic_page.rs | 1 - src/components/faq_card.rs | 32 +++++++ src/components/footer_card.rs | 2 +- src/lib.rs | 172 +++++++++++++++++++++++++--------- 8 files changed, 246 insertions(+), 48 deletions(-) create mode 100644 src/components/faq_card.rs diff --git a/Cargo.toml b/Cargo.toml index a1b2e92..b151590 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ dioxus-autofmt = "0.5.0-alpha.0" console_error_panic_hook = "0.1.7" log = "0.4.17" manganis = "*" +serde = "*" [dependencies.dioxus-router] version = "0.5.0-alpha.0" @@ -24,3 +25,7 @@ features = ["web", "fullstack"] default = [] server = ["dioxus/axum"] web = ["dioxus/web"] + +[dependencies.time] +verison = "0.3.34" +features = ["wasm-bindgen", "macros", "local-offset"] \ No newline at end of file diff --git a/public/tailwind.css b/public/tailwind.css index 3493814..3e6d616 100644 --- a/public/tailwind.css +++ b/public/tailwind.css @@ -592,6 +592,14 @@ video { position: relative; } +.order-1 { + order: 1; +} + +.order-2 { + order: 2; +} + .mx-auto { margin-left: auto; margin-right: auto; @@ -633,6 +641,10 @@ video { display: inline-block; } +.inline { + display: inline; +} + .flex { display: flex; } @@ -657,10 +669,22 @@ video { height: 2rem; } +.h-full { + height: 100%; +} + +.min-h-full { + min-height: 100%; +} + .min-h-screen { min-height: 100vh; } +.w-16 { + width: 4rem; +} + .w-4 { width: 1rem; } @@ -698,6 +722,10 @@ video { flex: 1 1 0%; } +.flex-shrink-0 { + flex-shrink: 0; +} + .basis-full { flex-basis: 100%; } @@ -759,6 +787,10 @@ video { grid-template-columns: repeat(1, minmax(0, 1fr)); } +.grid-rows-4 { + grid-template-rows: repeat(4, minmax(0, 1fr)); +} + .grid-rows-9 { grid-template-rows: repeat(9, minmax(0, 1fr)); } @@ -783,6 +815,10 @@ video { gap: 0px; } +.gap-2 { + gap: 0.5rem; +} + .space-y-2 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); @@ -795,6 +831,10 @@ video { margin-bottom: calc(1rem * var(--tw-space-y-reverse)); } +.overflow-auto { + overflow: auto; +} + .overflow-visible { overflow: visible; } @@ -866,6 +906,10 @@ video { padding-left: 0.5rem; } +.pl-4 { + padding-left: 1rem; +} + .pr-2 { padding-right: 0.5rem; } @@ -918,6 +962,11 @@ video { line-height: 1rem; } +.text-alice-werefox-blue-dark { + --tw-text-opacity: 1; + color: rgb(51 0 255 / var(--tw-text-opacity)); +} + .text-alice-werefox-grey-dark { --tw-text-opacity: 1; color: rgb(18 18 18 / var(--tw-text-opacity)); @@ -950,6 +999,11 @@ video { box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); } +.ring-alice-werefox-blue-dark { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(51 0 255 / var(--tw-ring-opacity)); +} + .ring-alice-werefox-grey { --tw-ring-opacity: 1; --tw-ring-color: rgb(36 36 36 / var(--tw-ring-opacity)); @@ -1039,6 +1093,14 @@ video { height: 1.5rem; } + .sm\:min-h-full { + min-height: 100%; + } + + .sm\:w-32 { + width: 8rem; + } + .sm\:w-6 { width: 1.5rem; } @@ -1059,6 +1121,11 @@ video { font-size: 1.125rem; line-height: 1.75rem; } + + .sm\:text-xl { + font-size: 1.25rem; + line-height: 1.75rem; + } } @media (min-width: 768px) { @@ -1107,6 +1174,11 @@ video { background-color: rgb(18 18 18 / var(--tw-bg-opacity)); } + .dark\:text-alice-werefox-blue-light { + --tw-text-opacity: 1; + color: rgb(145 151 243 / var(--tw-text-opacity)); + } + .dark\:text-alice-werefox-grey-light { --tw-text-opacity: 1; color: rgb(204 204 204 / var(--tw-text-opacity)); @@ -1122,6 +1194,11 @@ video { color: rgb(224 133 135 / var(--tw-text-opacity)); } + .dark\:ring-alice-werefox-blue { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(27 41 224 / var(--tw-ring-opacity)); + } + .dark\:ring-alice-werefox-grey-darker { --tw-ring-opacity: 1; --tw-ring-color: rgb(0 0 0 / var(--tw-ring-opacity)); diff --git a/src/components.rs b/src/components.rs index bc153ab..67030fb 100644 --- a/src/components.rs +++ b/src/components.rs @@ -10,4 +10,5 @@ pub mod page_button; pub mod identity_button; pub mod project_card; pub mod back_button; -pub mod project_foldable; \ No newline at end of file +pub mod project_foldable; +pub mod faq_card; \ No newline at end of file diff --git a/src/components/back_button.rs b/src/components/back_button.rs index 30ab328..b2fbdee 100644 --- a/src/components/back_button.rs +++ b/src/components/back_button.rs @@ -1,4 +1,4 @@ -use crate::{info_app::Route, utils::prop_structs::ImageProps}; +use crate::info_app::Route; use dioxus::prelude::*; use dioxus_router::prelude::*; diff --git a/src/components/basic_page.rs b/src/components/basic_page.rs index 2c0d06f..b850adb 100644 --- a/src/components/basic_page.rs +++ b/src/components/basic_page.rs @@ -2,7 +2,6 @@ use crate::components::footer_card::*; use crate::components::title_card::*; use crate::components::back_button::*; use crate::info_app::Route; -use crate::utils::prop_structs::ImageProps; use dioxus::prelude::*; #[component] diff --git a/src/components/faq_card.rs b/src/components/faq_card.rs new file mode 100644 index 0000000..90f3e8e --- /dev/null +++ b/src/components/faq_card.rs @@ -0,0 +1,32 @@ +use crate::utils::prop_structs::ImageProps; +use dioxus::prelude::*; + +#[component] +pub fn FaqCard(question: String, answer: String, image_props: ImageProps) -> Element { + rsx! { + div { class: "space-y-2", + div { class: "ring-2 ring-alice-werefox-blue-dark dark:ring-alice-werefox-blue", + p { class: "p-8 text-center text-lg sm:text-xl text-alice-werefox-blue-dark dark:text-alice-werefox-blue-light", + "{question}" + } + } + div { class: " ring-2 ring-alice-werefox-red-dark dark:ring-alice-werefox-red hover:ring-alice-werefox-blue-dark dark:hover:ring-alice-werefox-blue text-alice-werefox-red-dark dark:text-alice-werefox-red-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:animate-yip transition", + a { href: "https://bark.lgbt/@alicew", target: "_blank", + div { class: "p-2 flex", + div { class: "order-1 flex-shrink-0 relative inline sm:w-32 w-16 min-h-full items-center justify-center align-middle pt-4 pb-4 pl-4", + img { + alt: "{image_props.alt}", + src: "{image_props.src}" + } + } + div { class: "order-2 flex overflow-auto items-center justify-center animate-wiggle p-4 sm:text-lg text-xs text-center sm:min-h-full h-full", + "{answer}" + br {} + "{\"- @alice\"}" + } + } + } + } + } + } +} diff --git a/src/components/footer_card.rs b/src/components/footer_card.rs index fa72080..044f2fc 100644 --- a/src/components/footer_card.rs +++ b/src/components/footer_card.rs @@ -7,7 +7,7 @@ pub fn FooterCard() -> Element { footer { class: "p-4 space-y-2 rounded-lg ring-2 ring-alice-werefox-grey dark:ring-alice-werefox-grey-darker bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark", div { class: "flex text-alice-werefox-red-darker dark:text-alice-werefox-red-light", div { class: "flex-1" } - FooterButton { url: "https://info.werefox.cafe/contacts", inner_text: "Contact" } + FooterButton { url: "https://werefox.cafe/", inner_text: "Contact" } FooterButton { url: "https://gitea.werefox.cafe/ada/werefox-cafe", inner_text: " /src" } div { class: "flex-1" } } diff --git a/src/lib.rs b/src/lib.rs index ded105e..5259abe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,15 +16,17 @@ pub mod info_app { // import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types pub use dioxus::prelude::*; + use serde::{Deserialize, Serialize}; use crate::components::basic_page::*; + use crate::components::faq_card::*; use crate::components::home_page::*; use crate::components::identity_button::*; use crate::components::introduction_card::*; use crate::components::page_button::*; use crate::components::project_card::*; - use crate::components::werefox_card::*; use crate::components::project_foldable::*; + use crate::components::werefox_card::*; use crate::utils::prop_structs::*; use dioxus_router::prelude::*; @@ -42,8 +44,6 @@ pub mod info_app { Hrt {}, #[route("/faq")] Faq {}, - #[route("/support")] - Support {}, } pub fn DioxusApp() -> Element { rsx! { Router:: {} } @@ -129,14 +129,6 @@ pub mod info_app { alt: "Red question mark emoji".to_string(), }, ), - ( - "Support Me?", - Route::Support {}, - ImageProps { - src: "/emoji/green_money.svg".to_string(), - alt: "Green money emoji".to_string(), - }, - ), ]; rsx! { HomePage { page_title: "About a Werefox", card_title: "Hi! I'm Alice Werefox!", @@ -312,36 +304,43 @@ pub mod info_app { ), ]; rsx! { - BasicPage { page_title: "Some stuff I do!", - div { class: "rounded-lg ring-2 ring-alice-werefox-grey dark:ring-alice-werefox-grey-darker bg-alice-werefox-grey-light dark:bg-alice-werefox-grey", - WerefoxCard { card_title: "Personal Projects", - for project in project_list { - ProjectCard { project_title: project.0, project_description: project.1, project_link: project.2, image_props: project.3 } - } - ProjectFoldable { project_title: "Services", - project_description: "Click here for a list of the services I host.", - image_props: ImageProps { - src: "/emoji/crt_blue_screen.svg".to_string(), - alt: "A CRT blue screen emoji.".to_string(), - } - for service in service_list { - ProjectCard { project_title: service.0, project_description: service.1, project_link: service.2, image_props: service.3 } - } - } - ProjectFoldable { project_title: "Personal Use", - project_description: "Click here for a list of services I have set up for just me.", - image_props: ImageProps { - src: "/emoji/crt_blue_screen.svg".to_string(), - alt: "A CRT blue screen emoji.".to_string(), - } - for personal in personal_list { - ProjectCard { project_title: personal.0, project_description: personal.1, project_link: personal.2, image_props: personal.3 } + BasicPage { page_title: "Some stuff I do!", + div { class: "rounded-lg ring-2 ring-alice-werefox-grey dark:ring-alice-werefox-grey-darker bg-alice-werefox-grey-light dark:bg-alice-werefox-grey", + WerefoxCard { card_title: "Personal Projects", + for project in project_list { + ProjectCard { project_title: project.0, project_description: project.1, project_link: project.2, image_props: project.3 } + } + ProjectFoldable { + project_title: "Services", + project_description: "Click here for a list of the services I host.", + image_props: ImageProps { + src: "/emoji/crt_blue_screen.svg".to_string(), + alt: "A CRT blue screen emoji.".to_string(), + }, + for service in service_list { + ProjectCard { project_title: service.0, project_description: service.1, project_link: service.2, image_props: service.3 } + } + } + ProjectFoldable { + project_title: "Personal Use", + project_description: "Click here for a list of services I have set up for just me.", + image_props: ImageProps { + src: "/emoji/crt_blue_screen.svg".to_string(), + alt: "A CRT blue screen emoji.".to_string(), + }, + for personal in personal_list { + ProjectCard { + project_title: personal.0, + project_description: personal.1, + project_link: personal.2, + image_props: personal.3 + } + } + } } } } } - } - } } #[component] @@ -351,16 +350,101 @@ pub mod info_app { #[component] pub fn Hrt() -> Element { - rsx! { div {} } + // let time_elapsed: TimeElapsed = GetHrtTime().await(); + // let mut test = get_hrt_time(); + let time_elapsed = use_signal(|| TimeElapsed { + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + }); + use_coroutine(|_rx: UnboundedReceiver<()>| { + to_owned![time_elapsed]; + async move { + loop { + time_elapsed.set(get_hrt_time().await.unwrap()); + } + } + }); + rsx! { + BasicPage { page_title: "Track my HRT progress!", + WerefoxCard { card_title: "I'm so glad you're interested!!", + div { class: "p-2 sm:text-xl text-lg text-center text-alice-werefox-red-dark dark:text-alice-werefox-red-light grid grid-cols-1 grid-rows-4 gap-2", + p { "I've been on HRT for:" } + p { "{time_elapsed.read().days} days" } + p { "{time_elapsed.read().hours} hours" } + p { "{time_elapsed.read().minutes} minutes" } + p { "{time_elapsed.read().seconds} seconds" } + } + } + } + } + } + + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] + pub struct TimeElapsed { + days: i64, + hours: i64, + minutes: i64, + seconds: i64, + } + + #[server] + async fn get_hrt_time() -> Result { + use time::{macros::datetime, Duration, OffsetDateTime, UtcOffset}; + let mut hrt_start_date: OffsetDateTime = datetime!(2020-12-11 0:00 UTC); + // TODO: Fix this so that the offset time total matches the server's UTC offset. + // let hrt_start_date_offset: UtcOffset = UtcOffset::local_offset_at(hrt_start_date).unwrap(); + // hrt_start_date = hrt_start_date.replace_offset(hrt_start_date_offset); + let now: OffsetDateTime = OffsetDateTime::now_utc(); + let duration: Duration = now - hrt_start_date; + Ok(TimeElapsed { + days: duration.whole_days(), + hours: duration.whole_hours() % 24, + minutes: duration.whole_minutes() % 60, + seconds: duration.whole_seconds() % 60, + }) } #[component] pub fn Faq() -> Element { - rsx! { div {} } - } - - #[component] - pub fn Support() -> Element { - rsx! { div {} } + let faq_list = [( + "So is Werefox like a species or...?", + "That's a good question! No, my fursona's full name is Alice Icehart Werefox, Werefox is just a last name. I got it from playing Second Life back in the day.", + ImageProps { + src: "/images/AliceDefault.png".to_string(), + alt: "Alice as an emoji".to_string(), + }, + ),( + "How can you be Pansexual and a Lesbian?", + "I believe I've been told the proper term is \"sapphic\", it just means I *am* Pansexual, but I tend to prefer those who identify more femme.", + ImageProps { + src: "/images/AliceHeartRainbow.png".to_string(), + alt: "Alice with a gay pride heart".to_string(), + }, + ),( + "How do I get those Xenia stickers?", + "Yeah, about that. So, I've made a few posts about this, but when I first started giving those out, I was in a good financial position, among other things. Now I'm not! I will get to it when I do.", + ImageProps { + src: "/images/alice_Sweatdrop.svg".to_string(), + alt: "Alice with a sweatdrop".to_string(), + }, + ),( + "What do you do?", + "Lots of things! If you want to know more about what I do, you can check out \"Stuff I do!\" from the main page, or \"Support Me?\" if you wanna toss a donation! I'm currently still unemployed, so any extra funds would be appreciated!", + ImageProps { + src: "/images/AliceEmojiAliceYay.png".to_string(), + alt: "Happy Alice emoji".to_string(), + }, + )]; + rsx! { + BasicPage { page_title: "Here are some FAQs", + div { class: "p-4 space-y-4 rounded-lg ring-2 ring-alice-werefox-grey dark:ring-alice-werefox-grey-darker bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark", + for faq in faq_list { + FaqCard { question: faq.0, answer: faq.1, image_props: faq.2 } + } + } + } + } } }