diff --git a/src/components/blog/Card.tsx b/src/components/blog/Card.tsx index e421e36..71e1a70 100644 --- a/src/components/blog/Card.tsx +++ b/src/components/blog/Card.tsx @@ -2,22 +2,7 @@ import { Show } from "solid-js"; import CardLinks from "./CardLinks"; import DeletePostButton from "./DeletePostButton"; import { Fire } from "~/components/icons/Fire"; - -export interface Post { - id: number; - title: string; - subtitle: string | null; - body: string | null; - banner_photo: string | null; - date: string; - published: boolean; - category: string; - author_id: string; - reads: number; - attachments: string | null; - total_likes: number; - total_comments: number; -} +import { Post } from "~/db/types"; export interface CardProps { post: Post; diff --git a/src/components/blog/PostSorting.tsx b/src/components/blog/PostSorting.tsx index 6aa302b..8a7fe81 100644 --- a/src/components/blog/PostSorting.tsx +++ b/src/components/blog/PostSorting.tsx @@ -1,5 +1,6 @@ import { For, Show, createMemo } from "solid-js"; -import Card, { Post } from "./Card"; +import Card from "./Card"; +import { Post } from "~/db/types"; export interface Tag { value: string; @@ -13,10 +14,22 @@ export interface PostSortingProps { filters?: string; sort?: string; include?: string; + status?: string; } export default function PostSorting(props: PostSortingProps) { const filteredPosts = createMemo(() => { + let filtered = props.posts; + + // Apply publication status filter (admin only) + if (props.privilegeLevel === "admin" && props.status) { + if (props.status === "published") { + filtered = filtered.filter((post) => post.published === 1); + } else if (props.status === "unpublished") { + filtered = filtered.filter((post) => post.published === 0); + } + } + // Build map of post_id -> tags for that post const postTags = new Map>(); props.tags.forEach((tag) => { @@ -41,7 +54,7 @@ export default function PostSorting(props: PostSortingProps) { const includeSet = new Set(includeList); - return props.posts.filter((post) => { + return filtered.filter((post) => { const tags = postTags.get(post.id); if (!tags || tags.size === 0) return false; @@ -61,12 +74,12 @@ export default function PostSorting(props: PostSortingProps) { // Empty blacklist means show everything if (filterList.length === 0) { - return props.posts; + return filtered; } const filterSet = new Set(filterList); - return props.posts.filter((post) => { + return filtered.filter((post) => { const tags = postTags.get(post.id); if (!tags || tags.size === 0) return true; // Show posts with no tags @@ -81,7 +94,7 @@ export default function PostSorting(props: PostSortingProps) { } // No filters: show all posts - return props.posts; + return filtered; }); const sortedPosts = createMemo(() => { diff --git a/src/components/blog/PostSortingSelect.tsx b/src/components/blog/PostSortingSelect.tsx index a933477..1b081b0 100644 --- a/src/components/blog/PostSortingSelect.tsx +++ b/src/components/blog/PostSortingSelect.tsx @@ -40,7 +40,7 @@ export default function PostSortingSelect(props: PostSortingSelectProps) { + + + + ); +} diff --git a/src/db/types.ts b/src/db/types.ts index 4192181..5e909cf 100644 --- a/src/db/types.ts +++ b/src/db/types.ts @@ -46,7 +46,7 @@ export interface Post { body: string; banner_photo?: string; date?: string | null; - published: boolean; + published: number; // 0 or 1 (sqlite) author_id: string; reads: number; attachments?: string; diff --git a/src/routes/blog/index.tsx b/src/routes/blog/index.tsx index 25dac44..514b248 100644 --- a/src/routes/blog/index.tsx +++ b/src/routes/blog/index.tsx @@ -6,6 +6,7 @@ import { getRequestEvent } from "solid-js/web"; import PostSortingSelect from "~/components/blog/PostSortingSelect"; import TagSelector from "~/components/blog/TagSelector"; import PostSorting from "~/components/blog/PostSorting"; +import PublishStatusToggle from "~/components/blog/PublishStatusToggle"; import { TerminalSplash } from "~/components/TerminalSplash"; const getPosts = query(async () => { @@ -79,6 +80,8 @@ export default function BlogIndex() { "filter" in searchParams ? searchParams.filter : undefined; const include = () => "include" in searchParams ? searchParams.include : undefined; + const status = () => + "status" in searchParams ? searchParams.status : undefined; const data = createAsync(() => getPosts(), { deferStream: true }); @@ -90,13 +93,17 @@ export default function BlogIndex() { }> {(loadedData) => ( <> -
+
0}> + + + +