Add tags in post
This commit is contained in:
parent
cf65d5b8e9
commit
d353161c92
3 changed files with 74 additions and 30 deletions
|
@ -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>
|
||||
|
|
|
@ -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!{
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue