From 0c80c046e17ad82e5bfe1ae1cf3768000e894c7b Mon Sep 17 00:00:00 2001 From: nocnico Date: Thu, 24 Jul 2025 16:33:10 +0200 Subject: [PATCH] =?UTF-8?q?+=20Changelog=20Funktionalit=C3=A4t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit completed #95 --- apps/hub/app/(app)/_components/Changelog.tsx | 127 +++++++++++++++ .../(app)/_components/ChangelogActions.tsx | 37 +++++ apps/hub/app/(app)/_components/Footer.tsx | 19 ++- .../app/(app)/admin/changelog/[id]/page.tsx | 13 ++ .../admin/changelog/_components/Form.tsx | 151 ++++++++++++++++++ apps/hub/app/(app)/admin/changelog/action.ts | 28 ++++ apps/hub/app/(app)/admin/changelog/layout.tsx | 19 +++ .../app/(app)/admin/changelog/new/page.tsx | 5 + apps/hub/app/(app)/admin/changelog/page.tsx | 49 ++++++ apps/hub/app/(app)/layout.tsx | 13 +- apps/hub/app/_components/Nav.tsx | 15 +- apps/hub/public/changelogImages/Frog.jpg | Bin 0 -> 457744 bytes .../database/prisma/schema/changelog.prisma | 7 + packages/database/prisma/schema/user.prisma | 18 ++- 14 files changed, 478 insertions(+), 23 deletions(-) create mode 100644 apps/hub/app/(app)/_components/Changelog.tsx create mode 100644 apps/hub/app/(app)/_components/ChangelogActions.tsx create mode 100644 apps/hub/app/(app)/admin/changelog/[id]/page.tsx create mode 100644 apps/hub/app/(app)/admin/changelog/_components/Form.tsx create mode 100644 apps/hub/app/(app)/admin/changelog/action.ts create mode 100644 apps/hub/app/(app)/admin/changelog/layout.tsx create mode 100644 apps/hub/app/(app)/admin/changelog/new/page.tsx create mode 100644 apps/hub/app/(app)/admin/changelog/page.tsx create mode 100644 apps/hub/public/changelogImages/Frog.jpg create mode 100644 packages/database/prisma/schema/changelog.prisma diff --git a/apps/hub/app/(app)/_components/Changelog.tsx b/apps/hub/app/(app)/_components/Changelog.tsx new file mode 100644 index 00000000..45ed9d63 --- /dev/null +++ b/apps/hub/app/(app)/_components/Changelog.tsx @@ -0,0 +1,127 @@ +"use client"; +import { useState } from "react"; +import Image from "next/image"; +import { Button } from "@repo/shared-components"; +import MDEditor from "@uiw/react-md-editor"; +import { RefreshCw } from "lucide-react"; +import { updateChangelogAck } from "./ChangelogActions"; + +export const ChangelogModal = ({ + latestChangelog, + isOpen, + onClose, +}: { + latestChangelog: { title: string; text: string; previewImage: string } | null; + isOpen: boolean; + onClose: () => void; +}) => { + if (!isOpen || !latestChangelog) return null; + + const handleClose = async () => { + onClose(); + await updateChangelogAck(); + }; + + return ( +
+ + +
+
+ +
+

+ {latestChangelog.title} ist nun Verfügbar! +

+ +
+ {latestChangelog.previewImage && ( + Preview + )} +
+ +
+ +
+ +
+ +
+
+ +
+
+ ); +}; + +export const ChangelogBtn = ({ + latestChangelog, +}: { + latestChangelog: { title: string; text: string; previewImage: string } | null; +}) => { + const [isOpen, setIsOpen] = useState(false); + + if (!latestChangelog) return null; + + return ( + <> + setIsOpen(true)} + > + {latestChangelog.title} + + setIsOpen(false)} + /> + + ); +}; + +export const OpenChangelogOnPageload = ({ + latestChangelog, +}: { + latestChangelog: { title: string; text: string; previewImage: string } | null; +}) => { + const [isOpen, setIsOpen] = useState(true); + + if (!latestChangelog) return null; + + return ( + <> + setIsOpen(false)} + /> + + ); +}; diff --git a/apps/hub/app/(app)/_components/ChangelogActions.tsx b/apps/hub/app/(app)/_components/ChangelogActions.tsx new file mode 100644 index 00000000..c446c81b --- /dev/null +++ b/apps/hub/app/(app)/_components/ChangelogActions.tsx @@ -0,0 +1,37 @@ +"use server"; +import { prisma } from "@repo/db"; +import { getServerSession } from "../../api/auth/[...nextauth]/auth"; + +export async function getLatestChangelog() { + try { + const latestChangelog = await prisma.changelog.findMany({ + orderBy: { + createdAt: "desc", + }, + take: 1, + }); + + if (latestChangelog.length > 0 && latestChangelog[0]) { + return { + title: latestChangelog[0].title, + text: latestChangelog[0].text, + previewImage: latestChangelog[0].previewImage || "", + }; + } + + return null; + } catch (error) { + console.error("Failed to fetch latest changelog:", error); + throw new Error("Failed to fetch latest changelog"); + } +} + +export async function updateChangelogAck() { + const session = await getServerSession(); + if (session?.user) { + await prisma.user.update({ + where: { id: session.user.id }, + data: { changelogAck: true }, + }); + } +} diff --git a/apps/hub/app/(app)/_components/Footer.tsx b/apps/hub/app/(app)/_components/Footer.tsx index 72c56ff6..2a914dc3 100644 --- a/apps/hub/app/(app)/_components/Footer.tsx +++ b/apps/hub/app/(app)/_components/Footer.tsx @@ -2,10 +2,14 @@ import Image from "next/image"; import { DiscordLogoIcon, InstagramLogoIcon, ReaderIcon } from "@radix-ui/react-icons"; import YoutubeSvg from "./youtube_wider.svg"; import FacebookSvg from "./facebook.svg"; +import { ChangelogBtn } from "./Changelog"; +import { getLatestChangelog } from "./ChangelogActions"; + +export const Footer = async () => { + const latestChangelog = await getLatestChangelog(); -export const Footer = () => { return ( -