Enhance project structure and functionality by adding new components and integrations. Updated .gitignore to exclude history and transformed images. Integrated Svelte, sitemap, and icon support in astro.config.mjs. Added multiple new components including BlogOverview, ContentRows, Footer, Header, and various block components for improved content management. Updated package.json with new dependencies and modified scripts for build and development processes.
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
<script lang="ts">
|
||||
import PostCard from "./PostCard.svelte";
|
||||
import Tag from "./Tag.svelte";
|
||||
import type { PostEntry } from "../lib/cms";
|
||||
import { postHref } from "../lib/blog-utils";
|
||||
|
||||
interface TagEntry {
|
||||
_slug?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
let {
|
||||
posts = [],
|
||||
tags = [],
|
||||
activeTag = null,
|
||||
currentPage = 1,
|
||||
totalPages = 1,
|
||||
totalPosts = 0,
|
||||
basePath = "/posts",
|
||||
}: {
|
||||
posts: PostEntry[];
|
||||
tags: TagEntry[];
|
||||
activeTag: string | null;
|
||||
currentPage: number;
|
||||
totalPages: number;
|
||||
totalPosts?: number;
|
||||
basePath?: string;
|
||||
} = $props();
|
||||
|
||||
function tagHref(tagSlug: string | null): string {
|
||||
if (!tagSlug) return basePath;
|
||||
return `${basePath}/tag/${encodeURIComponent(tagSlug)}`;
|
||||
}
|
||||
|
||||
function pageHref(page: number): string {
|
||||
if (page <= 1) return tagHref(activeTag);
|
||||
const tagPart = activeTag
|
||||
? `/tag/${encodeURIComponent(activeTag)}`
|
||||
: "";
|
||||
return `${basePath}${tagPart}/page/${page}`;
|
||||
}
|
||||
|
||||
const showPagination = $derived(totalPages > 1);
|
||||
const hasPrev = $derived(currentPage > 1);
|
||||
const hasNext = $derived(currentPage < totalPages);
|
||||
const prevPage = $derived(currentPage - 1);
|
||||
const nextPage = $derived(currentPage + 1);
|
||||
const totalCount = $derived(totalPosts);
|
||||
|
||||
const pageNumbers = $derived.by(() => {
|
||||
const max = 5;
|
||||
let start = Math.max(1, currentPage - Math.floor(max / 2));
|
||||
const end = Math.min(totalPages, start + max - 1);
|
||||
if (end - start + 1 < max) start = Math.max(1, end - max + 1);
|
||||
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
||||
});
|
||||
|
||||
const paginationLinkClass =
|
||||
"h-6 w-6 mx-[2px] flex justify-center items-center text-slate-950 no-underline text-xs font-medium border border-gray-600 bg-white shadow-md";
|
||||
</script>
|
||||
|
||||
<div class="blog-overview">
|
||||
{#if tags.length > 0}
|
||||
<div class="mb-2">
|
||||
<div class="flex flex-wrap gap-2" role="navigation" aria-label="Nach Tag filtern">
|
||||
<Tag
|
||||
label="Alle"
|
||||
href={tagHref(null)}
|
||||
variant={activeTag ? "blue" : "green"}
|
||||
active={!activeTag}
|
||||
/>
|
||||
{#each tags as tag}
|
||||
{@const slug = tag._slug ?? ""}
|
||||
<Tag
|
||||
label={tag.name}
|
||||
href={tagHref(slug)}
|
||||
variant={activeTag === slug ? "inactive" : "green"}
|
||||
active={activeTag === slug}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if showPagination}
|
||||
<div>
|
||||
<div class="inline-flex py-4">
|
||||
<div class="flex">
|
||||
{#if hasPrev}
|
||||
<a href={pageHref(prevPage)} class={paginationLinkClass} aria-label="Vorherige Seite">
|
||||
←
|
||||
</a>
|
||||
{/if}
|
||||
{#each pageNumbers as num}
|
||||
<a
|
||||
href={pageHref(num)}
|
||||
class="{paginationLinkClass} {num === currentPage ? 'opacity-50' : ''}"
|
||||
aria-current={num === currentPage ? 'page' : undefined}
|
||||
>
|
||||
{num}
|
||||
</a>
|
||||
{/each}
|
||||
{#if hasNext}
|
||||
<a href={pageHref(nextPage)} class={paginationLinkClass} aria-label="Nächste Seite">
|
||||
→
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="py-2 grid grid-cols-1 gap-4">
|
||||
{#each posts as post}
|
||||
<PostCard
|
||||
post={post}
|
||||
href={postHref(post)}
|
||||
tagBase={`${basePath}/tag`}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
{#if showPagination}
|
||||
<div class="inline-flex py-4">
|
||||
<div class="flex">
|
||||
{#if hasPrev}
|
||||
<a href={pageHref(prevPage)} class={paginationLinkClass} aria-label="Vorherige Seite">
|
||||
←
|
||||
</a>
|
||||
{/if}
|
||||
{#each pageNumbers as num}
|
||||
<a
|
||||
href={pageHref(num)}
|
||||
class="{paginationLinkClass} {num === currentPage ? 'opacity-50' : ''}"
|
||||
aria-current={num === currentPage ? 'page' : undefined}
|
||||
>
|
||||
{num}
|
||||
</a>
|
||||
{/each}
|
||||
{#if hasNext}
|
||||
<a href={pageHref(nextPage)} class={paginationLinkClass} aria-label="Nächste Seite">
|
||||
→
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="grow"></div>
|
||||
<div class="bg-white rounded-md font-thin">
|
||||
<div class="inline-flex text-xs p-2">
|
||||
{#if totalCount > 0}
|
||||
{posts.length} von {totalCount} Beiträgen, Seite {currentPage} von {totalPages}
|
||||
{:else}
|
||||
Seite {currentPage} von {totalPages}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user