|
|
@ -1,5 +1,6 @@
|
|
|
|
import { createSignal, For, Show } from "solid-js";
|
|
|
|
import { createSignal, For, createMemo } from "solid-js";
|
|
|
|
import { cache, createAsync, A, type RouteDefinition } from "@solidjs/router";
|
|
|
|
import { cache, createAsync, A, type RouteDefinition } from "@solidjs/router";
|
|
|
|
|
|
|
|
import { classList } from "solid-js/web";
|
|
|
|
|
|
|
|
|
|
|
|
const getNewsList = cache(async () => {
|
|
|
|
const getNewsList = cache(async () => {
|
|
|
|
"use server";
|
|
|
|
"use server";
|
|
|
@ -24,19 +25,51 @@ export const route = {
|
|
|
|
|
|
|
|
|
|
|
|
export default () => {
|
|
|
|
export default () => {
|
|
|
|
const newsList = createAsync(() => getNewsList());
|
|
|
|
const newsList = createAsync(() => getNewsList());
|
|
|
|
const tags = createAsync(() => getNewsTags());
|
|
|
|
const tagsData = createAsync(() => getNewsTags());
|
|
|
|
|
|
|
|
const [tags, setTags] = createSignal(
|
|
|
|
|
|
|
|
Object.fromEntries(
|
|
|
|
|
|
|
|
tagsData()?.map((tag: string) => [tag, { active: false }]) ?? []
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const tagsActive = createMemo(() =>
|
|
|
|
|
|
|
|
Object.entries(tags())
|
|
|
|
|
|
|
|
.filter(([, { active }]) => active)
|
|
|
|
|
|
|
|
.map(([tag]) => tag)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<main class="container mx-auto p-4">
|
|
|
|
<main class="container mx-auto p-4">
|
|
|
|
<h1 class="mb-12 mt-40">News</h1>
|
|
|
|
<h1 class="mb-12 mt-40">News</h1>
|
|
|
|
<div class="flex flex-wrap gap-2">
|
|
|
|
<div class="flex flex-wrap gap-2">
|
|
|
|
<For each={tags()}>
|
|
|
|
<For each={Object.entries(tags())}>
|
|
|
|
{(tag) => (
|
|
|
|
{([tag, { active }]) => (
|
|
|
|
<button class="btn btn-sm">{tag}</button>
|
|
|
|
<button
|
|
|
|
|
|
|
|
class="btn btn-sm"
|
|
|
|
|
|
|
|
classList={{ "btn-primary": active }}
|
|
|
|
|
|
|
|
onClick={() =>
|
|
|
|
|
|
|
|
setTags({
|
|
|
|
|
|
|
|
...tags(),
|
|
|
|
|
|
|
|
[tag]: { active: !active },
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
{tag}
|
|
|
|
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</For>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<For each={newsList()}>
|
|
|
|
<For
|
|
|
|
|
|
|
|
each={
|
|
|
|
|
|
|
|
tagsActive()?.length
|
|
|
|
|
|
|
|
? newsList()?.filter((news) =>
|
|
|
|
|
|
|
|
Object.entries(tags())
|
|
|
|
|
|
|
|
.filter(([, state]) => state.active)
|
|
|
|
|
|
|
|
.some(([tag]) => news.keywords.includes(tag))
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
: newsList()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
>
|
|
|
|
{(post) => (
|
|
|
|
{(post) => (
|
|
|
|
<A href={`/news/${post.slug}`}>
|
|
|
|
<A href={`/news/${post.slug}`}>
|
|
|
|
<figure class="card md:card-side bg-base-100 shadow-xl mt-4">
|
|
|
|
<figure class="card md:card-side bg-base-100 shadow-xl mt-4">
|
|
|
@ -49,6 +82,11 @@ export default () => {
|
|
|
|
<h2 class="card-title">{post.title}</h2>
|
|
|
|
<h2 class="card-title">{post.title}</h2>
|
|
|
|
<p>{post.published}</p>
|
|
|
|
<p>{post.published}</p>
|
|
|
|
<p>{post.description}</p>
|
|
|
|
<p>{post.description}</p>
|
|
|
|
|
|
|
|
<div class="flex gap-2">
|
|
|
|
|
|
|
|
<For each={post.keywords}>
|
|
|
|
|
|
|
|
{(tag) => <div class="badge badge-secondary">{tag}</div>}
|
|
|
|
|
|
|
|
</For>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</figure>
|
|
|
|
</figure>
|
|
|
|
</A>
|
|
|
|
</A>
|
|
|
|