Improved Changelog, Changelog in Dispatch
This commit is contained in:
@@ -1,124 +0,0 @@
|
||||
"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";
|
||||
import { Changelog } from "@repo/db";
|
||||
|
||||
export const ChangelogModal = ({
|
||||
latestChangelog,
|
||||
isOpen,
|
||||
onClose,
|
||||
}: {
|
||||
latestChangelog: Changelog | null;
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
if (!isOpen || !latestChangelog) return null;
|
||||
|
||||
const handleClose = async () => {
|
||||
onClose();
|
||||
await updateChangelogAck();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="changelogModalToggle"
|
||||
className="modal-toggle"
|
||||
onChange={handleClose}
|
||||
/>
|
||||
<dialog open className="modal p-4">
|
||||
<div className="modal-box max-h-11/12 w-11/12 max-w-2xl overflow-y-auto">
|
||||
<form method="dialog">
|
||||
<button
|
||||
className="btn btn-sm btn-circle btn-ghost absolute right-3 top-3"
|
||||
onClick={handleClose}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</form>
|
||||
<h3 className="flex items-center gap-2 text-lg font-bold">
|
||||
<span className="text-primary">{latestChangelog.title}</span> ist nun Verfügbar!
|
||||
</h3>
|
||||
|
||||
<div className="flex flex-col items-center">
|
||||
{latestChangelog.previewImage && (
|
||||
<Image
|
||||
src={latestChangelog.previewImage}
|
||||
alt="Preview"
|
||||
width={800}
|
||||
height={400}
|
||||
className="mt-4 h-auto w-full object-cover"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="text-base-content/80 mb-2 mt-4 text-left">
|
||||
<MDEditor.Markdown
|
||||
source={latestChangelog.text}
|
||||
style={{
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="modal-action">
|
||||
<Button className="btn btn-info btn-outline" onClick={handleClose}>
|
||||
Weiter zum HUB
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<label className="modal-backdrop" htmlFor="changelogModalToggle">
|
||||
Close
|
||||
</label>
|
||||
</dialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ChangelogBtn = ({ latestChangelog }: { latestChangelog: Changelog | null }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
if (!latestChangelog) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<a
|
||||
href="#!"
|
||||
className="hover:text-primary flex items-center gap-1"
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<RefreshCw size={12} /> {latestChangelog.title}
|
||||
</a>
|
||||
<ChangelogModal
|
||||
latestChangelog={latestChangelog}
|
||||
isOpen={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const OpenChangelogOnPageload = ({
|
||||
latestChangelog,
|
||||
}: {
|
||||
latestChangelog: Changelog | null;
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
|
||||
if (!latestChangelog) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ChangelogModal
|
||||
latestChangelog={latestChangelog}
|
||||
isOpen={isOpen}
|
||||
onClose={() => setIsOpen(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
"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 latestChangelog[0];
|
||||
}
|
||||
|
||||
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 },
|
||||
});
|
||||
}
|
||||
}
|
||||
26
apps/hub/app/(app)/_components/ChangelogWrapper.tsx
Normal file
26
apps/hub/app/(app)/_components/ChangelogWrapper.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
"use client";
|
||||
import { updateUser } from "(app)/settings/actions";
|
||||
import { Changelog } from "@repo/db";
|
||||
import { ChangelogModalBtn } from "@repo/shared-components";
|
||||
import { useSession } from "next-auth/react";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
export const ChangelogWrapper = ({ latestChangelog }: { latestChangelog: Changelog | null }) => {
|
||||
const { data: session } = useSession();
|
||||
const autoOpen = !session?.user.changelogAck && !!latestChangelog;
|
||||
|
||||
if (!latestChangelog) return null;
|
||||
|
||||
return (
|
||||
<ChangelogModalBtn
|
||||
latestChangelog={latestChangelog}
|
||||
autoOpen={autoOpen}
|
||||
onClose={async () => {
|
||||
await updateUser({ changelogAck: true });
|
||||
if (!session?.user.changelogAck) {
|
||||
toast.success("Changelog als gelesen markiert");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -2,11 +2,22 @@ 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";
|
||||
import { ChangelogModalBtn } from "@repo/shared-components";
|
||||
import { getServerSession } from "api/auth/[...nextauth]/auth";
|
||||
import { updateUser } from "(app)/settings/actions";
|
||||
import toast from "react-hot-toast";
|
||||
import { ChangelogWrapper } from "(app)/_components/ChangelogWrapper";
|
||||
import { prisma } from "@repo/db";
|
||||
|
||||
export const Footer = async () => {
|
||||
const latestChangelog = await getLatestChangelog();
|
||||
const session = await getServerSession();
|
||||
const latestChangelog = await prisma.changelog.findFirst({
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
},
|
||||
});
|
||||
|
||||
const autoOpen = !session?.user.changelogAck && !!latestChangelog;
|
||||
|
||||
return (
|
||||
<footer className="footer bg-base-200 mt-4 flex items-center justify-between rounded-lg p-4 shadow-md">
|
||||
@@ -18,7 +29,7 @@ export const Footer = async () => {
|
||||
<a href="https://virtualairrescue.com/datenschutz/" className="hover:text-primary">
|
||||
Datenschutzerklärung
|
||||
</a>
|
||||
<ChangelogBtn latestChangelog={latestChangelog} />
|
||||
<ChangelogWrapper latestChangelog={latestChangelog} />
|
||||
</div>
|
||||
|
||||
{/* Center: Copyright */}
|
||||
|
||||
Reference in New Issue
Block a user