Add icon to reading_time and datetime
This commit is contained in:
parent
76dd9b0783
commit
816ef54e82
9 changed files with 90 additions and 23 deletions
|
@ -19,8 +19,8 @@ serde = "1.0"
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
|
||||||
# https://carlosted.github.io/icondata/
|
# https://carlosted.github.io/icondata/
|
||||||
leptos_icons = "0.2.0"
|
leptos_icons = "0.2"
|
||||||
icondata = "0.3.0"
|
icondata = "0.3"
|
||||||
|
|
||||||
# dependecies for client (enable when csr or hydrate set)
|
# dependecies for client (enable when csr or hydrate set)
|
||||||
wasm-bindgen = { version = "0.2", optional = true }
|
wasm-bindgen = { version = "0.2", optional = true }
|
||||||
|
|
41
src/app/components/datetime.rs
Normal file
41
src/app/components/datetime.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
use leptos::*;
|
||||||
|
use chrono::Datelike;
|
||||||
|
|
||||||
|
fn human_datetime(datetime: &chrono::DateTime<chrono::Local>) -> String {
|
||||||
|
format!(
|
||||||
|
"{day} {month} {year}",
|
||||||
|
day = datetime.day(),
|
||||||
|
month = human_month(datetime.month()),
|
||||||
|
year = datetime.year()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn human_month<'a>(month: u32) -> &'a str {
|
||||||
|
match month {
|
||||||
|
1 => "Jan.",
|
||||||
|
2 => "Feb.",
|
||||||
|
3 => "Mar.",
|
||||||
|
4 => "Avr.",
|
||||||
|
5 => "Mai",
|
||||||
|
6 => "Juin",
|
||||||
|
7 => "Juillet",
|
||||||
|
8 => "Août",
|
||||||
|
9 => "Sept.",
|
||||||
|
10 => "Oct.",
|
||||||
|
11 => "Nov.",
|
||||||
|
12 => "Dec.",
|
||||||
|
_ => "Invalide"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn DateTime(
|
||||||
|
datetime: chrono::DateTime<chrono::Local>
|
||||||
|
) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<span class="icon_container">
|
||||||
|
<leptos_icons::Icon icon=icondata::BiCalendarAltRegular />
|
||||||
|
{ human_datetime(&datetime) }
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,3 +32,11 @@ mod nav;
|
||||||
pub use nav::Nav;
|
pub use nav::Nav;
|
||||||
|
|
||||||
pub use mon_parcours::MonParcours;
|
pub use mon_parcours::MonParcours;
|
||||||
|
|
||||||
|
mod reading_time;
|
||||||
|
|
||||||
|
pub use reading_time::ReadingTime;
|
||||||
|
|
||||||
|
mod datetime;
|
||||||
|
|
||||||
|
pub use datetime::DateTime;
|
24
src/app/components/reading_time.rs
Normal file
24
src/app/components/reading_time.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use leptos::*;
|
||||||
|
|
||||||
|
fn human_reading_time(reading_time: u64) -> String {
|
||||||
|
match reading_time {
|
||||||
|
0..=60 => format!("{reading_time}s"),
|
||||||
|
_ => {
|
||||||
|
let min = reading_time / 60;
|
||||||
|
let secs = reading_time - min * 60;
|
||||||
|
format!("{min}min {secs}s")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
pub fn ReadingTime(
|
||||||
|
time: u64
|
||||||
|
) -> impl IntoView {
|
||||||
|
view! {
|
||||||
|
<span class="icon_container">
|
||||||
|
<leptos_icons::Icon icon=icondata::BiTimeFiveRegular />
|
||||||
|
{ human_reading_time(time) }
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,7 @@ use leptos_router::*;
|
||||||
use crate::app::{
|
use crate::app::{
|
||||||
models::Post,
|
models::Post,
|
||||||
components::{
|
components::{
|
||||||
Loading, Nav
|
Loading, Nav, ReadingTime, DateTime
|
||||||
},
|
|
||||||
utils::{
|
|
||||||
datetime::human_datetime,
|
|
||||||
reading_time::human_reading_time
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,8 +86,8 @@ pub fn PostListCard(
|
||||||
<PostTags tags=post.metadata.tags.clone()/>
|
<PostTags tags=post.metadata.tags.clone()/>
|
||||||
<h2><A href=format!("/posts/{}", post.metadata.slug.clone())>{post.metadata.title.clone()}</A></h2>
|
<h2><A href=format!("/posts/{}", post.metadata.slug.clone())>{post.metadata.title.clone()}</A></h2>
|
||||||
<p>{post.metadata.description.clone()}</p>
|
<p>{post.metadata.description.clone()}</p>
|
||||||
<span>{human_datetime(&post.metadata.date)}</span>
|
<DateTime datetime=post.metadata.date />
|
||||||
<span>{human_reading_time(post.metadata.reading_time)}</span>
|
<ReadingTime time=post.metadata.reading_time />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -150,8 +146,8 @@ pub fn PostElement() -> impl IntoView {
|
||||||
<img src={post.metadata.image_path.clone()} alt=format!("Image {}", post.metadata.title)/>
|
<img src={post.metadata.image_path.clone()} alt=format!("Image {}", post.metadata.title)/>
|
||||||
<h1>{post.metadata.title.clone()}</h1>
|
<h1>{post.metadata.title.clone()}</h1>
|
||||||
<p>{post.metadata.description.clone()}</p>
|
<p>{post.metadata.description.clone()}</p>
|
||||||
<span>{human_datetime(&post.metadata.date)}</span>
|
<DateTime datetime=post.metadata.date />
|
||||||
<span>{human_reading_time(post.metadata.reading_time)}</span>
|
<ReadingTime time=post.metadata.reading_time />
|
||||||
<PostTags tags=post.metadata.tags.clone()/>
|
<PostTags tags=post.metadata.tags.clone()/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#[cfg(feature = "ssr")]
|
#[cfg(feature = "ssr")]
|
||||||
pub(crate) mod data_src;
|
pub(crate) mod data_src;
|
||||||
|
|
||||||
pub(crate) mod datetime;
|
|
||||||
pub(crate) mod reading_time;
|
pub(crate) mod reading_time;
|
|
@ -8,15 +8,4 @@ pub fn calculate_reading_time(content: &String) -> u64 {
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
estimated_read_time::text(&content, &doc_read_time).seconds()
|
estimated_read_time::text(&content, &doc_read_time).seconds()
|
||||||
}
|
|
||||||
|
|
||||||
pub fn human_reading_time(reading_time: u64) -> String {
|
|
||||||
match reading_time {
|
|
||||||
0..=60 => format!("{reading_time}s"),
|
|
||||||
_ => {
|
|
||||||
let min = reading_time / 60;
|
|
||||||
let secs = reading_time - min * 60;
|
|
||||||
format!("{min}min {secs}s")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
9
style/icon_container.css
Normal file
9
style/icon_container.css
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
@layer components {
|
||||||
|
.icon_container {
|
||||||
|
@apply flex items-center gap-2;
|
||||||
|
|
||||||
|
& > svg {
|
||||||
|
@apply scale-125;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@
|
||||||
@import './timeline.css';
|
@import './timeline.css';
|
||||||
@import './top_component.css';
|
@import './top_component.css';
|
||||||
@import './nav.css';
|
@import './nav.css';
|
||||||
|
@import './icon_container.css';
|
||||||
/*@import './mermaid.css';*/
|
/*@import './mermaid.css';*/
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
Loading…
Reference in a new issue