feat: update Font Awesome to 7.1.0
All checks were successful
actionlint check / actionlint check (pull_request) Successful in 39s
conventional pull request title check / conventional pull request title check (pull_request) Successful in 8s
conventional commit messages check / conventional commit messages check (pull_request) Successful in 10s
GitLeaks check / GitLeaks check (pull_request) Successful in 46s
dotenv-linter check / dotenv-linter check (pull_request) Successful in 48s
hadolint check / hadolint check (pull_request) Successful in 51s
checkov check / checkov check (pull_request) Successful in 2m37s
htmlhint check / htmlhint check (pull_request) Successful in 1m9s
markdownlint check / markdownlint check (pull_request) Successful in 50s
Prettier check / Prettier check (pull_request) Successful in 30s
ShellCheck check / ShellCheck check (pull_request) Successful in 55s
Stylelint check / Stylelint check (pull_request) Successful in 54s
yamllint check / yamllint check (pull_request) Successful in 1m6s
Rust check / Rust check (pull_request) Successful in 24m52s

This commit is contained in:
2026-01-24 17:39:48 +01:00
parent d0a124ee75
commit d4235ef2ab
19 changed files with 315 additions and 176 deletions

9
Cargo.lock generated
View File

@@ -1299,6 +1299,14 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "dioxus-free-icons"
version = "0.10.0"
source = "git+https://github.com/matous-volf/dioxus-free-icons?rev=6488400003a3d6829e771a84a565c5c5f08a9aa0#6488400003a3d6829e771a84a565c5c5f08a9aa0"
dependencies = [
"dioxus",
]
[[package]] [[package]]
name = "dioxus-fullstack" name = "dioxus-fullstack"
version = "0.7.3" version = "0.7.3"
@@ -5440,6 +5448,7 @@ dependencies = [
"diesel", "diesel",
"diesel_migrations", "diesel_migrations",
"dioxus", "dioxus",
"dioxus-free-icons",
"dioxus-html", "dioxus-html",
"dioxus-i18n", "dioxus-i18n",
"feruca", "feruca",

View File

@@ -38,6 +38,11 @@ async-std = { version = "1.13.2", optional = true }
dioxus-i18n = "0.5.1" dioxus-i18n = "0.5.1"
voca_rs = "1.15.2" voca_rs = "1.15.2"
load-dotenv = "0.1.2" load-dotenv = "0.1.2"
# TODO: Switch to upstream once it merges the changes.
dioxus-free-icons = { git = "https://github.com/matous-volf/dioxus-free-icons", rev = "6488400003a3d6829e771a84a565c5c5f08a9aa0", features = [
"font-awesome-regular",
"font-awesome-solid",
] }
[features] [features]
default = ["web"] default = ["web"]

View File

@@ -37,7 +37,6 @@ pub(crate) fn App() -> Element {
document::Stylesheet { href: INPUT_NUMBER_ARROWS_CSS } document::Stylesheet { href: INPUT_NUMBER_ARROWS_CSS }
document::Stylesheet { href: INPUT_RANGE_CSS } document::Stylesheet { href: INPUT_RANGE_CSS }
document::Link { rel: "manifest", href: MANIFEST, crossorigin: "use-credentials" } document::Link { rel: "manifest", href: MANIFEST, crossorigin: "use-credentials" }
document::Script { src: "https://kit.fontawesome.com/3c1b409f8f.js" }
div { div {
class: "min-h-screen pt-4 pb-36 flex flex-col text-zinc-200 bg-zinc-800", class: "min-h-screen pt-4 pb-36 flex flex-col text-zinc-200 bg-zinc-800",

View File

@@ -40,7 +40,7 @@ pub(crate) fn BottomPanel(display_form: Signal<bool>) -> Element {
class: format!( class: format!(
"flex flex-col pointer-events-auto bg-zinc-700/50 rounded-t-xl border-t-zinc-600 border-t backdrop-blur drop-shadow-[0_-5px_10px_rgba(0,0,0,0.2)] transition-[height] duration-[500ms] ease-[cubic-bezier(0.79,0.14,0.15,0.86)] overflow-y-scroll {}", "flex flex-col pointer-events-auto bg-zinc-700/50 rounded-t-xl border-t-zinc-600 border-t backdrop-blur drop-shadow-[0_-5px_10px_rgba(0,0,0,0.2)] transition-[height] duration-[500ms] ease-[cubic-bezier(0.79,0.14,0.15,0.86)] overflow-y-scroll {}",
match (display_form(), current_route, navigation_expanded()) { match (display_form(), current_route, navigation_expanded()) {
(false, _, false) => "h-[66px]", (false, _, false) => "h-[64px]",
(false, _, true) => "h-[130px]", (false, _, true) => "h-[130px]",
(true, Route::ProjectsPage, _) => "h-[130px]", (true, Route::ProjectsPage, _) => "h-[130px]",
(true, _, _) => "h-[506px]", (true, _, _) => "h-[506px]",

View File

@@ -28,7 +28,7 @@ pub(crate) fn CategoryCalendarTaskList() -> Element {
div { div {
class: "flex flex-col gap-4", class: "flex flex-col gap-4",
div { div {
class: "px-8 flex flex-row items-center gap-2 font-bold", class: "px-7 flex flex-row items-center gap-2 font-bold",
div { div {
class: "pt-1", class: "pt-1",
{ {

View File

@@ -2,6 +2,10 @@ use crate::models::category::Category;
use dioxus::core_macro::rsx; use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{
FaCalendarDays, FaForward, FaHourglassHalf, FaInbox, FaQuestion, FaWater,
};
#[component] #[component]
pub(crate) fn CategoryInput( pub(crate) fn CategoryInput(
@@ -14,63 +18,71 @@ pub(crate) fn CategoryInput(
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg grow basis-0 {} cursor-pointer", "py-3 flex flex-row justify-center items-center rounded-lg grow basis-0 {} cursor-pointer",
if selected_category() == Category::SomedayMaybe { "bg-zinc-500/50" } if selected_category() == Category::SomedayMaybe { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
), ),
onclick: move |_| { onclick: move |_| {
selected_category.set(Category::SomedayMaybe); selected_category.set(Category::SomedayMaybe);
}, },
i { Icon {
class: "fa-solid fa-question" icon: FaQuestion,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg grow basis-0 {} cursor-pointer", "py-3 flex flex-row justify-center items-center rounded-lg grow basis-0 {} cursor-pointer",
if selected_category() == Category::LongTerm { "bg-zinc-500/50" } if selected_category() == Category::LongTerm { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
), ),
onclick: move |_| { onclick: move |_| {
selected_category.set(Category::LongTerm); selected_category.set(Category::LongTerm);
}, },
i { Icon {
class: "fa-solid fa-water" icon: FaWater,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg grow basis-0 {} cursor-pointer", "py-3 flex flex-row justify-center items-center rounded-lg grow basis-0 {} cursor-pointer",
if let Category::WaitingFor(_) = selected_category() { "bg-zinc-500/50" } if let Category::WaitingFor(_) = selected_category() { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
), ),
onclick: move |_| { onclick: move |_| {
selected_category.set(Category::WaitingFor(String::new())); selected_category.set(Category::WaitingFor(String::new()));
}, },
i { Icon {
class: "fa-solid fa-hourglass-half" icon: FaHourglassHalf,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg grow basis-0 {} cursor-pointer", "py-3 flex flex-row justify-center items-center rounded-lg grow basis-0 {} cursor-pointer",
if selected_category() == Category::NextSteps { "bg-zinc-500/50" } if selected_category() == Category::NextSteps { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
), ),
onclick: move |_| { onclick: move |_| {
selected_category.set(Category::NextSteps); selected_category.set(Category::NextSteps);
}, },
i { Icon {
class: "fa-solid fa-forward" icon: FaForward,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg grow basis-0 {} cursor-pointer", "py-3 flex flex-row justify-center items-center rounded-lg grow basis-0 {} cursor-pointer",
if let Category::Calendar { .. } = selected_category() { "bg-zinc-500/50" } if let Category::Calendar { .. } = selected_category() { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
), ),
@@ -81,22 +93,26 @@ pub(crate) fn CategoryInput(
time: None, time: None,
}); });
}, },
i { Icon {
class: "fa-solid fa-calendar-days" icon: FaCalendarDays,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg grow basis-0 {} cursor-pointer", "py-3 flex flex-row justify-center items-center rounded-lg grow basis-0 {} cursor-pointer",
if selected_category() == Category::Inbox { "bg-zinc-500/50" } if selected_category() == Category::Inbox { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
), ),
onclick: move |_| { onclick: move |_| {
selected_category.set(Category::Inbox); selected_category.set(Category::Inbox);
}, },
i { Icon {
class: "fa-solid fa-inbox" icon: FaInbox,
height: 16,
width: 16
} }
} }
} }

View File

@@ -6,6 +6,8 @@ use crate::models::category::Category;
use crate::models::task::TaskWithSubtasks; use crate::models::task::TaskWithSubtasks;
use chrono::Local; use chrono::Local;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{FaCalendarCheck, FaCalendarXmark, FaWater};
use dioxus_i18n::t; use dioxus_i18n::t;
use dioxus_i18n::use_i18n::i18n; use dioxus_i18n::use_i18n::i18n;
use voca_rs::Voca; use voca_rs::Voca;
@@ -48,12 +50,12 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
div { div {
class: "flex flex-col gap-4", class: "flex flex-col gap-4",
div { div {
class: "px-8 flex flex-row items-center gap-2 font-bold", class: "px-7 flex flex-row items-center gap-2 font-bold",
i { Icon {
class: "fa-solid fa-water text-xl w-6 text-center" class: "mx-1",
icon: FaWater
} }
div { div {
class: "mt-1",
{t!("long-term")._upper_first()} {t!("long-term")._upper_first()}
} }
} }
@@ -62,7 +64,7 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
div { div {
key: "{task.task.id}", key: "{task.task.id}",
class: format!( class: format!(
"px-8 pt-5 {} flex flex-row gap-4", "px-7 pt-5 {} flex flex-row gap-4",
if task.task.deadline.is_some() { if task.task.deadline.is_some() {
"pb-0.5" "pb-0.5"
} else { } else {
@@ -80,12 +82,14 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
div { div {
class: "flex flex-col gap-4", class: "flex flex-col gap-4",
div { div {
class: "px-8 flex flex-row items-center gap-2 font-bold", class: "px-7 flex flex-row items-center gap-2 font-bold",
i { Icon {
class: "fa-solid fa-calendar-xmark text-xl w-6 text-center" class: "mx-1",
height: 22,
width: 22,
icon: FaCalendarXmark
} }
div { div {
class: "mt-1",
{t!("overdue")._upper_first()} {t!("overdue")._upper_first()}
} }
} }
@@ -98,12 +102,14 @@ pub(crate) fn CategoryTodayTaskList() -> Element {
div { div {
class: "flex flex-col gap-4", class: "flex flex-col gap-4",
div { div {
class: "px-8 flex flex-row items-center gap-2 font-bold", class: "px-7 flex flex-row items-center gap-2 font-bold",
i { Icon {
class: "fa-solid fa-calendar-check text-xl w-6 text-center" class: "mx-1",
height: 22,
width: 22,
icon: FaCalendarCheck
} }
div { div {
class: "mt-1",
{ {
let format = t!("date-weekday-format"); let format = t!("date-weekday-format");
let today_date = today_date.format_localized( let today_date = today_date.format_localized(

View File

@@ -1,6 +1,8 @@
use dioxus::core_macro::rsx; use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::FaTriangleExclamation;
#[component] #[component]
pub(crate) fn ErrorBoundaryMessage(children: Element, class: Option<String>) -> Element { pub(crate) fn ErrorBoundaryMessage(children: Element, class: Option<String>) -> Element {
@@ -11,8 +13,10 @@ pub(crate) fn ErrorBoundaryMessage(children: Element, class: Option<String>) ->
div { div {
class: "grow flex flex-col justify-center items-center", class: "grow flex flex-col justify-center items-center",
div { div {
i { Icon {
class: "text-3xl fa-solid fa-triangle-exclamation" icon: FaTriangleExclamation,
height: 32,
width: 32
} }
} }
} }

View File

@@ -1,6 +1,10 @@
use crate::models::project::Project; use crate::models::project::Project;
use crate::models::task::Task; use crate::models::task::Task;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::{
Icon,
icons::fa_solid_icons::{FaPlus, FaXmark},
};
#[component] #[component]
pub(crate) fn FormOpenButton(opened: Signal<bool>) -> Element { pub(crate) fn FormOpenButton(opened: Signal<bool>) -> Element {
@@ -9,7 +13,7 @@ pub(crate) fn FormOpenButton(opened: Signal<bool>) -> Element {
rsx! { rsx! {
button { button {
class: "pointer-events-auto m-4 py-3 px-5 self-end text-center bg-zinc-300/50 rounded-xl border-t-zinc-200 border-t backdrop-blur drop-shadow-[0_-5px_10px_rgba(0,0,0,0.2)] text-2xl text-zinc-200 cursor-pointer", class: "pointer-events-auto m-4 py-4 px-5 self-end text-center bg-zinc-300/50 rounded-xl border-t-zinc-200 border-t backdrop-blur drop-shadow-[0_-5px_10px_rgba(0,0,0,0.2)] text-2xl text-zinc-200 cursor-pointer",
onclick: move |_| { onclick: move |_| {
if opened() { if opened() {
project_being_edited.set(None); project_being_edited.set(None);
@@ -17,8 +21,18 @@ pub(crate) fn FormOpenButton(opened: Signal<bool>) -> Element {
} }
opened.set(!opened()); opened.set(!opened());
}, },
i { if opened() {
class: format!("min-w-6 fa-solid {}", if opened() { "fa-xmark" } else { "fa-plus" }), Icon {
icon: FaXmark,
height: 24,
width: 24
}
} else {
Icon {
icon: FaPlus,
height: 24,
width: 24
}
} }
} }
} }

View File

@@ -1,6 +1,11 @@
use crate::components::navigation_item::NavigationItem; use crate::components::navigation_item::NavigationItem;
use crate::route::Route; use crate::route::Route;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{
FaBars, FaCalendarDay, FaCalendarDays, FaCheck, FaForward, FaHourglassHalf, FaInbox, FaList,
FaTrashCan, FaWater,
};
#[component] #[component]
pub(crate) fn Navigation(expanded: Signal<bool>) -> Element { pub(crate) fn Navigation(expanded: Signal<bool>) -> Element {
@@ -9,70 +14,54 @@ pub(crate) fn Navigation(expanded: Signal<bool>) -> Element {
class: "grid grid-cols-5 justify-stretch", class: "grid grid-cols-5 justify-stretch",
button { button {
class: format!( class: format!(
"py-4 text-center text-2xl {} cursor-pointer", "py-5 flex flex-row justify-center items-center {} cursor-pointer",
if expanded() { "text-zinc-200" } if expanded() { "text-zinc-200" }
else { "text-zinc-500" } else { "text-zinc-500" }
), ),
onclick: move |_| expanded.set(!expanded()), onclick: move |_| expanded.set(!expanded()),
i { Icon {
class: "fa-solid fa-bars" icon: FaBars,
height: 24,
width: 24
} }
}, },
NavigationItem { NavigationItem {
route: Route::CategoryNextStepsPage, route: Route::CategoryNextStepsPage,
i { icon: FaForward
class: "fa-solid fa-forward"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryCalendarPage, route: Route::CategoryCalendarPage,
i { icon: FaCalendarDays
class: "fa-solid fa-calendar-days"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryTodayPage, route: Route::CategoryTodayPage,
i { icon: FaCalendarDay
class: "fa-solid fa-calendar-day"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryInboxPage, route: Route::CategoryInboxPage,
i { icon: FaInbox
class: "fa-solid fa-inbox"
}
}, },
{if expanded() { {if expanded() {
rsx! { rsx! {
NavigationItem { NavigationItem {
route: Route::ProjectsPage, route: Route::ProjectsPage,
i { icon: FaList
class: "fa-solid fa-list"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryTrashPage, route: Route::CategoryTrashPage,
i { icon: FaTrashCan
class: "fa-solid fa-trash-can"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryDonePage, route: Route::CategoryDonePage,
i { icon: FaCheck
class: "fa-solid fa-check"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryLongTermPage, route: Route::CategoryLongTermPage,
i { icon: FaWater
class: "fa-solid fa-water"
}
}, },
NavigationItem { NavigationItem {
route: Route::CategoryWaitingForPage, route: Route::CategoryWaitingForPage,
i { icon: FaHourglassHalf
class: "fa-solid fa-hourglass-half"
}
} }
} }
} else { VNode::empty() }} } else { VNode::empty() }}

View File

@@ -1,19 +1,27 @@
use crate::route::Route; use crate::route::Route;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::{Icon, IconShape};
#[component] #[component]
pub(crate) fn NavigationItem(route: Route, children: Element) -> Element { pub(crate) fn NavigationItem<I: IconShape + Clone + PartialEq + 'static>(
route: Route,
icon: I,
) -> Element {
let current_route = use_route::<Route>(); let current_route = use_route::<Route>();
rsx! { rsx! {
Link { Link {
to: route.clone(), to: route.clone(),
class: format!( class: format!(
"py-4 text-center text-2xl {}", "py-5 flex flex-row justify-center items-center {}",
if current_route == route { "text-zinc-200" } if current_route == route { "text-zinc-200" }
else { "text-zinc-500" } else { "text-zinc-500" }
), ),
children Icon {
icon,
height: 24,
width: 24
}
} }
} }
} }

View File

@@ -3,6 +3,8 @@ use crate::server::projects::{create_project, delete_project, edit_project};
use dioxus::core_macro::{component, rsx}; use dioxus::core_macro::{component, rsx};
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{FaFloppyDisk, FaPenClip, FaTrashCan};
#[component] #[component]
pub(crate) fn ProjectForm( pub(crate) fn ProjectForm(
@@ -30,9 +32,12 @@ pub(crate) fn ProjectForm(
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "input_title", r#for: "input_title",
class: "min-w-6 text-center", class: "flex flex-row justify-center items-center min-w-6",
i { Icon {
class: "fa-solid fa-pen-clip text-zinc-400/50" class: "text-zinc-400/50",
icon: FaPenClip,
height: 16,
width: 16
} }
} }
input { input {
@@ -48,7 +53,7 @@ pub(crate) fn ProjectForm(
class: "flex flex-row justify-between mt-auto", class: "flex flex-row justify-between mt-auto",
button { button {
r#type: "button", r#type: "button",
class: "py-2 px-4 bg-zinc-300/50 rounded-lg cursor-pointer", class: "py-3 px-4 bg-zinc-300/50 rounded-lg cursor-pointer",
onclick: move |_| { onclick: move |_| {
let project = project.clone(); let project = project.clone();
async move { async move {
@@ -58,15 +63,19 @@ pub(crate) fn ProjectForm(
on_successful_submit.call(()); on_successful_submit.call(());
} }
}, },
i { Icon {
class: "fa-solid fa-trash-can" icon: FaTrashCan,
height: 16,
width: 16
} }
} }
button { button {
r#type: "submit", r#type: "submit",
class: "py-2 px-4 bg-zinc-300/50 rounded-lg cursor-pointer", class: "py-3 px-4 bg-zinc-300/50 rounded-lg cursor-pointer",
i { Icon {
class: "fa-solid fa-floppy-disk" icon: FaFloppyDisk,
height: 16,
width: 16
} }
} }
} }

View File

@@ -13,7 +13,7 @@ pub(crate) fn ProjectList() -> Element {
div { div {
key: "{project.id}", key: "{project.id}",
class: format!( class: format!(
"px-8 py-4 select-none {}", "px-7 py-4 select-none {}",
if project_being_edited().is_some_and(|p| p.id == project.id) { if project_being_edited().is_some_and(|p| p.id == project.id) {
"bg-zinc-700" "bg-zinc-700"
} else { "" } } else { "" }

View File

@@ -2,6 +2,8 @@ use crate::models::category::ReoccurrenceInterval;
use dioxus::core_macro::rsx; use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{FaBan, FaEarthEurope, FaMoon, FaSun};
#[component] #[component]
pub(crate) fn ReoccurrenceIntervalInput( pub(crate) fn ReoccurrenceIntervalInput(
@@ -12,7 +14,7 @@ pub(crate) fn ReoccurrenceIntervalInput(
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg {} {} cursor-pointer", "py-2 flex flex-row justify-center items-center rounded-lg {} {} cursor-pointer",
class_buttons.unwrap_or(""), class_buttons.unwrap_or(""),
if reoccurrence_interval().is_none() { "bg-zinc-500/50" } if reoccurrence_interval().is_none() { "bg-zinc-500/50" }
else { "bg-zinc-800/50" } else { "bg-zinc-800/50" }
@@ -20,14 +22,16 @@ pub(crate) fn ReoccurrenceIntervalInput(
onclick: move |_| { onclick: move |_| {
reoccurrence_interval.set(None); reoccurrence_interval.set(None);
}, },
i { Icon {
class: "fa-solid fa-ban" icon: FaBan,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg {} {} cursor-pointer", "py-2 flex flex-row justify-center items-center rounded-lg {} {} cursor-pointer",
class_buttons.unwrap_or(""), class_buttons.unwrap_or(""),
if let Some(ReoccurrenceInterval::Day) = reoccurrence_interval() if let Some(ReoccurrenceInterval::Day) = reoccurrence_interval()
{ "bg-zinc-500/50" } { "bg-zinc-500/50" }
@@ -36,14 +40,16 @@ pub(crate) fn ReoccurrenceIntervalInput(
onclick: move |_| { onclick: move |_| {
reoccurrence_interval.set(Some(ReoccurrenceInterval::Day)) reoccurrence_interval.set(Some(ReoccurrenceInterval::Day))
}, },
i { Icon {
class: "fa-solid fa-sun" icon: FaSun,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg {} {} cursor-pointer", "py-2 flex flex-row justify-center items-center rounded-lg {} {} cursor-pointer",
class_buttons.unwrap_or(""), class_buttons.unwrap_or(""),
if let Some(ReoccurrenceInterval::Month) = reoccurrence_interval() if let Some(ReoccurrenceInterval::Month) = reoccurrence_interval()
{ "bg-zinc-500/50" } { "bg-zinc-500/50" }
@@ -52,14 +58,16 @@ pub(crate) fn ReoccurrenceIntervalInput(
onclick: move |_| { onclick: move |_| {
reoccurrence_interval.set(Some(ReoccurrenceInterval::Month)) reoccurrence_interval.set(Some(ReoccurrenceInterval::Month))
}, },
i { Icon {
class: "fa-solid fa-moon" icon: FaMoon,
height: 16,
width: 16
} }
}, },
button { button {
r#type: "button", r#type: "button",
class: format!( class: format!(
"py-2 rounded-lg {} {} cursor-pointer", "py-2 flex flex-row justify-center items-center rounded-lg {} {} cursor-pointer",
class_buttons.unwrap_or(""), class_buttons.unwrap_or(""),
if let Some(ReoccurrenceInterval::Year) = reoccurrence_interval() if let Some(ReoccurrenceInterval::Year) = reoccurrence_interval()
{ "bg-zinc-500/50" } { "bg-zinc-500/50" }
@@ -68,8 +76,10 @@ pub(crate) fn ReoccurrenceIntervalInput(
onclick: move |_| { onclick: move |_| {
reoccurrence_interval.set(Some(ReoccurrenceInterval::Year)) reoccurrence_interval.set(Some(ReoccurrenceInterval::Year))
}, },
i { Icon {
class: "fa-solid fa-earth-europe" icon: FaEarthEurope,
height: 16,
width: 16
} }
} }
} }

View File

@@ -5,6 +5,9 @@ use crate::server::subtasks::{create_subtask, delete_subtask, edit_subtask};
use dioxus::core_macro::{component, rsx}; use dioxus::core_macro::{component, rsx};
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_regular_icons::FaSquare;
use dioxus_free_icons::icons::fa_solid_icons::{FaListCheck, FaPlus, FaSquareCheck, FaTrashCan};
#[component] #[component]
pub(crate) fn SubtasksForm(task: Task) -> Element { pub(crate) fn SubtasksForm(task: Task) -> Element {
@@ -31,9 +34,12 @@ pub(crate) fn SubtasksForm(task: Task) -> Element {
}, },
label { label {
r#for: "input_new_title", r#for: "input_new_title",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-list-check text-zinc-400/50" class: "text-zinc-400/50",
icon: FaListCheck,
height: 16,
width: 16
} }
} }
div { div {
@@ -49,9 +55,11 @@ pub(crate) fn SubtasksForm(task: Task) -> Element {
} }
button { button {
r#type: "submit", r#type: "submit",
class: "py-2 col-span-1 bg-zinc-800/50 rounded-lg", class: "py-2 col-span-1 flex flex-row justify-center items-center bg-zinc-800/50 rounded-lg",
i { Icon {
class: "fa-solid fa-plus" icon: FaPlus,
height: 16,
width: 16
} }
} }
} }
@@ -60,15 +68,8 @@ pub(crate) fn SubtasksForm(task: Task) -> Element {
div { div {
key: "{subtask.id}", key: "{subtask.id}",
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
i { button {
class: format!( class: "min-w-6 flex flex-row justify-center items-center text-zinc-400/50",
"{} min-w-6 text-center text-2xl text-zinc-400/50",
if subtask.is_completed {
"fa solid fa-square-check"
} else {
"fa-regular fa-square"
}
),
onclick: { onclick: {
let subtask = subtask.clone(); let subtask = subtask.clone();
move |_| { move |_| {
@@ -85,6 +86,19 @@ pub(crate) fn SubtasksForm(task: Task) -> Element {
).await; ).await;
} }
} }
},
if subtask.is_completed {
Icon {
icon: FaSquareCheck,
height: 24,
width: 24
}
} else {
Icon {
icon: FaSquare,
height: 24,
width: 24
}
} }
} }
div { div {
@@ -118,7 +132,7 @@ pub(crate) fn SubtasksForm(task: Task) -> Element {
} }
button { button {
r#type: "button", r#type: "button",
class: "py-2 col-span-1 bg-zinc-800/50 rounded-lg", class: "py-2 flex flex-row justify-center items-center col-span-1 bg-zinc-800/50 rounded-lg",
onclick: { onclick: {
let subtask = subtask.clone(); let subtask = subtask.clone();
move |_| { move |_| {
@@ -128,8 +142,10 @@ pub(crate) fn SubtasksForm(task: Task) -> Element {
} }
} }
}, },
i { Icon {
class: "fa-solid fa-trash-can" icon: FaTrashCan,
height: 16,
width: 16
} }
} }
} }

View File

@@ -11,6 +11,11 @@ use chrono::Duration;
use dioxus::core_macro::{component, rsx}; use dioxus::core_macro::{component, rsx};
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{
FaBell, FaBomb, FaClock, FaFloppyDisk, FaHourglassEnd, FaLayerGroup, FaList, FaPenClip,
FaRepeat, FaTrashCan,
};
use dioxus_i18n::t; use dioxus_i18n::t;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -160,10 +165,13 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "input_title", r#for: "input_title",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-pen-clip text-zinc-400/50" class: "text-zinc-400/50",
}, icon: FaPenClip,
height: 16,
width: 16
}
}, },
input { input {
name: "title", name: "title",
@@ -178,9 +186,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "input_project", r#for: "input_project",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-list text-zinc-400/50" class: "text-zinc-400/50",
icon: FaList,
height: 16,
width: 16
} }
}, },
SuspenseBoundary { SuspenseBoundary {
@@ -204,9 +215,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "input_deadline", r#for: "input_deadline",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-bomb text-zinc-400/50" class: "text-zinc-400/50",
icon: FaBomb,
height: 16,
width: 16
} }
}, },
input { input {
@@ -221,9 +235,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
div { div {
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-layer-group text-zinc-400/50" class: "text-zinc-400/50",
icon: FaLayerGroup,
height: 16,
width: 16
} }
}, },
CategoryInput { CategoryInput {
@@ -236,10 +253,13 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
div { div {
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "input_deadline", r#for: "input_waiting_for",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-hourglass-end text-zinc-400/50" class: "text-zinc-400/50",
icon: FaHourglassEnd,
height: 16,
width: 16
} }
}, },
input { input {
@@ -257,9 +277,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "input_category_calendar_date", r#for: "input_category_calendar_date",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-clock text-zinc-400/50" class: "text-zinc-400/50",
icon: FaClock,
height: 16,
width: 16
} }
}, },
div { div {
@@ -291,9 +314,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "category_calendar_reoccurrence_length", r#for: "category_calendar_reoccurrence_length",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-repeat text-zinc-400/50" class: "text-zinc-400/50",
icon: FaRepeat,
height: 16,
width: 16
} }
}, },
div { div {
@@ -323,9 +349,12 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row items-center gap-3", class: "flex flex-row items-center gap-3",
label { label {
r#for: "category_calendar_reminder_offset_index", r#for: "category_calendar_reminder_offset_index",
class: "min-w-6 text-center", class: "min-w-6 flex flex-row justify-center items-center",
i { Icon {
class: "fa-solid fa-bell text-zinc-400/50" class: "text-zinc-400/50",
icon: FaBell,
height: 16,
width: 16
} }
}, },
input { input {
@@ -375,7 +404,7 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
class: "flex flex-row justify-between mt-auto", class: "flex flex-row justify-between mt-auto",
button { button {
r#type: "button", r#type: "button",
class: "py-2 px-4 bg-zinc-300/50 rounded-lg cursor-pointer", class: "py-3 px-4 bg-zinc-300/50 rounded-lg cursor-pointer",
onclick: move |_| { onclick: move |_| {
let task = task.clone(); let task = task.clone();
async move { async move {
@@ -395,16 +424,20 @@ pub(crate) fn TaskForm(task: Option<Task>, on_successful_submit: EventHandler<()
on_successful_submit.call(()); on_successful_submit.call(());
} }
}, },
i { Icon {
class: "fa-solid fa-trash-can" icon: FaTrashCan,
height: 16,
width: 16
} }
} }
button { button {
form: "form_task", form: "form_task",
r#type: "submit", r#type: "submit",
class: "py-2 px-4 bg-zinc-300/50 rounded-lg cursor-pointer", class: "py-3 px-4 flex flex-row justify-center items-center bg-zinc-300/50 rounded-lg cursor-pointer",
i { Icon {
class: "fa-solid fa-floppy-disk" icon: FaFloppyDisk,
height: 16,
width: 16
} }
} }
} }

View File

@@ -5,6 +5,9 @@ use crate::server::tasks::complete_task;
use dioxus::core_macro::rsx; use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_regular_icons::FaSquare;
use dioxus_free_icons::icons::fa_solid_icons::FaSquareCheck;
#[component] #[component]
pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>) -> Element { pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>) -> Element {
@@ -16,17 +19,17 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>
div { div {
key: "{task.task.id}", key: "{task.task.id}",
class: format!( class: format!(
"px-8 pt-4 {} flex flex-row gap-4 select-none {}", "px-7 pt-4.25 {} flex flex-row items-start gap-4 select-none {}",
if task.task.deadline.is_some() || !task.subtasks.is_empty() { if task.task.deadline.is_some() || !task.subtasks.is_empty() {
"pb-0.5" "pb-0.25"
} else if let Category::Calendar { time, .. } = &task.task.category { } else if let Category::Calendar { time, .. } = &task.task.category {
if time.is_some() { if time.is_some() {
"pb-0.5" "pb-0.25"
} else { } else {
"pb-4" "pb-4.25"
} }
} else { } else {
"pb-4" "pb-4.25"
}, },
if task_being_edited().is_some_and(|t| t.id == task.task.id) { if task_being_edited().is_some_and(|t| t.id == task.task.id) {
"bg-zinc-700" "bg-zinc-700"
@@ -36,15 +39,8 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>
let task = task.clone(); let task = task.clone();
move |_| task_being_edited.set(Some(task.task.clone())) move |_| task_being_edited.set(Some(task.task.clone()))
}, },
i { button {
class: format!( class: "text-zinc-500",
"{} text-3xl align-middle h-9 text-zinc-500",
if let Category::Done = task.task.category {
"fa solid fa-square-check"
} else {
"fa-regular fa-square cursor-pointer"
}
),
onclick: { onclick: {
move |event: Event<MouseData>| { move |event: Event<MouseData>| {
// To prevent editing the task. // To prevent editing the task.
@@ -53,6 +49,20 @@ pub(crate) fn TaskList(tasks: Vec<TaskWithSubtasks>, class: Option<&'static str>
let _ = complete_task(task.task.id).await; let _ = complete_task(task.task.id).await;
} }
} }
},
if let Category::Done = task.task.category {
Icon {
icon: FaSquareCheck,
height: 30,
width: 30
}
} else {
Icon {
class: "cursor-pointer",
icon: FaSquare,
height: 30,
width: 30
}
} }
}, },
TaskListItem { TaskListItem {

View File

@@ -5,6 +5,8 @@ use chrono::{Datelike, Local};
use dioxus::core_macro::rsx; use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::{FaBomb, FaClock, FaListCheck};
use dioxus_i18n::prelude::i18n; use dioxus_i18n::prelude::i18n;
use dioxus_i18n::t; use dioxus_i18n::t;
use voca_rs::Voca; use voca_rs::Voca;
@@ -14,19 +16,21 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element {
let today_date = Local::now().date_naive(); let today_date = Local::now().date_naive();
rsx! { rsx! {
div { div {
class: "flex flex-col", class: "pt-0.75 flex flex-col",
div { div {
class: "mt-1 grow font-medium", class: "grow font-medium",
{task.task.title} {task.task.title}
}, },
div { div {
class: "flex flex-row gap-4", class: "flex flex-row gap-4",
if let Some(deadline) = task.task.deadline { if let Some(deadline) = task.task.deadline {
div { div {
class: "text-sm text-zinc-400", class: "flex flex-row items-center gap-1 text-sm text-zinc-400",
i { Icon {
class: "fa-solid fa-bomb" icon: FaBomb,
}, height: 14,
width: 14
}
{ {
format!( format!(
" {}", " {}",
@@ -72,10 +76,12 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element {
if let Category::Calendar { time, .. } = task.task.category { if let Category::Calendar { time, .. } = task.task.category {
if let Some(calendar_time) = time { if let Some(calendar_time) = time {
div { div {
class: "text-sm text-zinc-400", class: "flex flex-row items-center gap-1 text-sm text-zinc-400",
i { Icon {
class: "fa-solid fa-clock" icon: FaClock,
}, height: 14,
width: 14
}
{ {
let format = t!("time-format"); let format = t!("time-format");
format!(" {}", calendar_time.time.format(format.as_str())) format!(" {}", calendar_time.time.format(format.as_str()))
@@ -85,10 +91,12 @@ pub(crate) fn TaskListItem(task: TaskWithSubtasks) -> Element {
} }
if !task.subtasks.is_empty() { if !task.subtasks.is_empty() {
div { div {
class: "text-sm text-zinc-400", class: "flex flex-row items-center gap-1 text-sm text-zinc-400",
i { Icon {
class: "fa-solid fa-list-check" icon: FaListCheck,
}, height: 14,
width: 14
}
{format!( {format!(
" {}/{}", " {}/{}",
task.subtasks.iter() task.subtasks.iter()

View File

@@ -7,6 +7,8 @@ use crate::route::Route;
use dioxus::core_macro::rsx; use dioxus::core_macro::rsx;
use dioxus::dioxus_core::Element; use dioxus::dioxus_core::Element;
use dioxus::prelude::*; use dioxus::prelude::*;
use dioxus_free_icons::Icon;
use dioxus_free_icons::icons::fa_solid_icons::FaCog;
#[component] #[component]
pub(crate) fn Main() -> Element { pub(crate) fn Main() -> Element {
@@ -25,10 +27,11 @@ pub(crate) fn Main() -> Element {
rsx! { rsx! {
div { div {
class: "grow flex flex-col justify-center items-center", class: "grow flex flex-col justify-center items-center",
div { Icon {
i { class: "animate-[spin_2000ms_linear_infinite]",
class: "text-3xl fa-solid fa-cog fa-spin" icon: FaCog,
} height: 32,
width: 32
} }
} }
} }