Add tags in post

This commit is contained in:
Florian RICHER 2024-01-07 00:23:25 +01:00
parent cf65d5b8e9
commit d353161c92
3 changed files with 74 additions and 30 deletions

View file

@ -1,4 +1,5 @@
use leptos::*;
use leptos_router::A;
#[component]
pub fn Title(
@ -8,7 +9,7 @@ pub fn Title(
) -> impl IntoView {
view! {
<header>
<a href=href>r"< Retour"</a>
<A href=href>r"< Retour"</A>
<h1>{title}</h1>
<span></span>
</header>

View file

@ -9,12 +9,18 @@ use crate::app::{
};
#[server]
pub async fn get_posts() -> Result<Vec<Post>, ServerFnError> {
pub async fn get_posts(
tag: Option<String>
) -> Result<Vec<Post>, ServerFnError> {
leptos_actix::extract(
|data: actix_web::web::Data<crate::app::models::Data>| async move {
let data = data.into_inner();
data.posts
.iter()
let default = vec![];
let posts = match tag {
Some(tag) => data.posts_by_tag.get(&tag).unwrap_or(&default),
None => &data.posts
};
posts.iter()
.map(|post| {
Post {
metadata: post.metadata.clone(),
@ -44,44 +50,72 @@ pub async fn get_post(
.and_then(|post| post.ok_or_else(|| ServerFnError::ServerError("Post not found".to_string())))
}
#[component]
pub fn PostTags(
tags: Vec<String>
) -> impl IntoView {
view! {
<div class="tags_list">
{
tags.into_iter().map(|tag| view! { <A class="tag" href=format!("/posts?tag={}", tag)>{tag}</A>}).collect_view()
}
</div>
}
}
#[component]
pub fn PostListCard(
post: Post
) -> impl IntoView {
view! {
<div>
<img src={post.metadata.image_path.clone()} alt=format!("Image {}", post.metadata.title)/>
{
if post.metadata.draft {
Some(view!{
<div class="warning">
<Icon icon=Icon::from(IoIcon::IoConstruct)/>
</div>
})
} else {
None
}
}
<div>
<PostTags tags=post.metadata.tags.clone()/>
<h2>{post.metadata.title.clone()}</h2>
<p>{post.metadata.description.clone()}</p>
<span>{post.metadata.date.clone()}</span>
</div>
</div>
}
}
#[component]
pub fn PostList() -> impl IntoView {
let posts = create_resource(|| (), |_| get_posts());
let query = use_query_map();
let tag = move || query.with(|query| query.get("tag").cloned());
let posts = create_resource(move || tag(), move |_| get_posts(tag()));
let posts_view = move || {
posts.and_then(|posts| {
posts.iter()
.map(|post| view! {
<a href=format!("posts/{}", post.metadata.slug.clone())>
<img src={post.metadata.image_path.clone()} alt=format!("Image {}", post.metadata.title)/>
{
if post.metadata.draft {
Some(view!{
<div class="warning">
<Icon icon=Icon::from(IoIcon::IoConstruct)/>
</div>
})
} else {
None
}
}
<div>
<h2>{post.metadata.title.clone()}</h2>
<p>{post.metadata.description.clone()}</p>
<span>{post.metadata.date.clone()}</span>
</div>
</a>
})
.map(|post| view! { <PostListCard post=post.clone() /> })
.collect_view()
})
};
let title = move || match tag() {
Some(tag) => view! { <Title href="/posts".to_string() title=format!("Posts for {}", tag)/> },
None => view! { <Title href="/".to_string() title="Posts".to_string()/> }
};
view! {
<Suspense fallback=move || view! { <Loading title="Chargement des posts...".to_string() /> }>
<main class="posts">
<Title href="/".to_string() title="Posts".to_string()/>
{ title }
<div class="posts__cards">{posts_view}</div>
</main>
@ -101,6 +135,7 @@ pub fn PostElement() -> impl IntoView {
view! {
<>
<Title href="/posts".to_string() title=post.metadata.title.clone()/>
<PostTags tags=post.metadata.tags.clone()/>
{
if post.metadata.draft {
Some(view!{

View file

@ -42,13 +42,21 @@
& ol li {
@apply list-decimal list-inside;
}
& blockquote {
@apply border-l-4 border-primary/50 dark:border-dark_primary/50 pl-3 my-3;
}
& .tags_list {
@apply flex flex-row flex-wrap gap-2;
}
}
.posts {
& > .posts__cards {
@apply grid grid-cols-1 gap-5 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 m-5;
& > a {
& > div {
@apply rounded-xl overflow-hidden relative;
@apply bg-primary/10 dark:bg-dark_primary/10;
@apply shadow-md shadow-primary/5 dark:shadow-dark_primary/5;