Changelog-Seite, option zum verstecken von Einträgen auf dieser
This commit is contained in:
68
apps/hub/app/(app)/changelog/_components/Timeline.tsx
Normal file
68
apps/hub/app/(app)/changelog/_components/Timeline.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
"use client";
|
||||
|
||||
import MDEditor from "@uiw/react-md-editor";
|
||||
import Image from "next/image";
|
||||
|
||||
export type TimelineEntry = {
|
||||
id: number;
|
||||
title: string;
|
||||
text: string;
|
||||
previewImage?: string | null;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
const formatReleaseDate = (value: string) =>
|
||||
new Intl.DateTimeFormat("en-GB", {
|
||||
day: "2-digit",
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
}).format(new Date(value));
|
||||
|
||||
export const ChangelogTimeline = ({ entries }: { entries: TimelineEntry[] }) => {
|
||||
if (!entries.length)
|
||||
return <p className="text-base-content/70">Es sind noch keine Changelog-Einträge vorhanden.</p>;
|
||||
|
||||
return (
|
||||
<div className="relative mt-6 pl-6">
|
||||
<div className="bg-base-300 absolute bottom-0 left-2 top-0 w-px" aria-hidden />
|
||||
<div className="space-y-8">
|
||||
{entries.map((entry, idx) => (
|
||||
<article key={entry.id ?? `${entry.title}-${idx}`} className="relative pl-4">
|
||||
<div className="bg-primary ring-base-100 absolute -left-[9px] top-3 h-4 w-4 rounded-full ring-4" />
|
||||
<div className="bg-base-200/80 rounded-xl p-5 shadow">
|
||||
<div className="flex flex-col gap-1 text-left md:flex-row md:justify-between">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold leading-tight">{entry.title}</h3>
|
||||
<p className="text-base-content/60 text-sm">
|
||||
Release Date: {formatReleaseDate(entry.createdAt)}
|
||||
</p>
|
||||
</div>
|
||||
{entry.previewImage && (
|
||||
<div className="absolute right-5 top-5 md:pl-4">
|
||||
<Image
|
||||
src={entry.previewImage}
|
||||
width={300}
|
||||
height={300}
|
||||
alt={`${entry.title} preview`}
|
||||
className="mt-3 max-w-[300px] rounded-lg object-cover md:mt-0"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="text-base-content/80 text-left" data-color-mode="dark">
|
||||
<MDEditor.Markdown
|
||||
source={entry.text}
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
fontSize: "0.95rem",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
26
apps/hub/app/(app)/changelog/page.tsx
Normal file
26
apps/hub/app/(app)/changelog/page.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { prisma } from "@repo/db";
|
||||
import { ChangelogTimeline } from "./_components/Timeline";
|
||||
import { ActivityLogIcon } from "@radix-ui/react-icons";
|
||||
|
||||
export default async function Page() {
|
||||
const changelog = await prisma.changelog.findMany({
|
||||
where: { showOnChangelogPage: true },
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
|
||||
const entries = changelog.map((entry) => ({
|
||||
...entry,
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
}));
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="w-full px-4">
|
||||
<p className="flex items-center gap-2 text-left text-2xl font-semibold">
|
||||
<ActivityLogIcon className="h-5 w-5" /> Changelog
|
||||
</p>
|
||||
</div>
|
||||
<ChangelogTimeline entries={entries} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user