CRUD based pages multilogs
This commit is contained in:
parent
e7f1a86172
commit
8056b67072
9 changed files with 258 additions and 297 deletions
|
@ -24,20 +24,7 @@ import {
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { logsSchema } from "@/lib/validations/validation";
|
import { logsSchema } from "@/lib/validations/validation";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
import {
|
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogHeader,
|
|
||||||
DialogFooter,
|
|
||||||
DialogTitle,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
|
|
||||||
const MarkdownEditor = dynamic(() => import("@uiw/react-md-editor"), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
interface LogEntry {
|
interface LogEntry {
|
||||||
_id: string;
|
_id: string;
|
||||||
|
@ -46,54 +33,13 @@ interface LogEntry {
|
||||||
bullets: { point: string }[];
|
bullets: { point: string }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PageEntry {
|
|
||||||
title: string;
|
|
||||||
slug: string;
|
|
||||||
content: string; // Add content to the PageEntry interface
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogsFormValues = z.infer<typeof logsSchema>;
|
type LogsFormValues = z.infer<typeof logsSchema>;
|
||||||
|
|
||||||
const AdminLogPage = () => {
|
const AdminLogPage = () => {
|
||||||
const [logs, setLogs] = useState<LogEntry[]>([]);
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||||
const [pages, setPages] = useState<PageEntry[]>([]);
|
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const router = useRouter();
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
const [pageTitle, setPageTitle] = useState("");
|
|
||||||
const [selectedPage, setSelectedPage] = useState<PageEntry | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetch("/api/mdx/pages")
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => setPages(data))
|
|
||||||
.catch((error) => console.error("Failed to load pages", error));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const createPage = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
const slug = pageTitle.toLowerCase().replace(/\s+/g, "-");
|
|
||||||
const response = await fetch("/api/mdx/pages", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ title: pageTitle, slug, content: "" }),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const newPage = await response.json();
|
|
||||||
setPages([...pages, newPage]);
|
|
||||||
setPageTitle("");
|
|
||||||
setOpen(false);
|
|
||||||
setLoading(false);
|
|
||||||
} else {
|
|
||||||
console.error("Failed to create page");
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const form = useForm<LogsFormValues>({
|
const form = useForm<LogsFormValues>({
|
||||||
resolver: zodResolver(logsSchema),
|
resolver: zodResolver(logsSchema),
|
||||||
|
@ -123,31 +69,6 @@ const AdminLogPage = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchPages = async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch("/api/mdx/pages", { method: "GET" });
|
|
||||||
if (response.ok) {
|
|
||||||
const data: PageEntry[] = await response.json();
|
|
||||||
setPages(data);
|
|
||||||
} else {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
setError(error.message || "Failed to fetch pages");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchLogs();
|
|
||||||
fetchPages();
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
fetchLogs();
|
|
||||||
fetchPages();
|
|
||||||
}, 10000);
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onSubmit: SubmitHandler<LogsFormValues> = async (data) => {
|
const onSubmit: SubmitHandler<LogsFormValues> = async (data) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await fetch("/api/uploadlogs", {
|
const response = await fetch("/api/uploadlogs", {
|
||||||
|
@ -182,6 +103,15 @@ const AdminLogPage = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLogs();
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
fetchLogs();
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="logs-page" className="wrapper container">
|
<section id="logs-page" className="wrapper container">
|
||||||
<h1 className="text-3xl font-bold py-6">Server Logs Form</h1>
|
<h1 className="text-3xl font-bold py-6">Server Logs Form</h1>
|
||||||
|
@ -258,71 +188,6 @@ const AdminLogPage = () => {
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
<section className="container mx-auto p-4">
|
|
||||||
{/* <h1 className="text-3xl font-bold">Changelog Management</h1> */}
|
|
||||||
<section id="create-page" className="py-16">
|
|
||||||
<h2 className="text-3xl md:text-4xl font-bold mb-2">
|
|
||||||
Multi Log Page
|
|
||||||
</h2>
|
|
||||||
<Button variant={"secondary"} onClick={() => setOpen(true)}>
|
|
||||||
Create New Page
|
|
||||||
</Button>
|
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
|
||||||
<DialogContent>
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Enter Page Title</DialogTitle>
|
|
||||||
</DialogHeader>
|
|
||||||
<Input
|
|
||||||
value={pageTitle}
|
|
||||||
onChange={(e) => setPageTitle(e.target.value)}
|
|
||||||
placeholder="Page Title"
|
|
||||||
/>
|
|
||||||
<DialogFooter>
|
|
||||||
<Button disabled={loading} onClick={createPage}>
|
|
||||||
Continue
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</section>
|
|
||||||
<section id="pages-list" className="pb-16">
|
|
||||||
<h2 className="text-3xl md:text-4xl font-bold">Existing Pages</h2>
|
|
||||||
<p className="mb-4">Total Pages: {pages.length}</p>
|
|
||||||
<Table className="w-full mt-4 border-muted">
|
|
||||||
<TableHeader>
|
|
||||||
<TableRow>
|
|
||||||
<TableHead className="border-b px-4 py-2">Slug</TableHead>
|
|
||||||
<TableHead className="border-b px-4 py-2">Actions</TableHead>
|
|
||||||
</TableRow>
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{pages.map((page) => (
|
|
||||||
<TableRow key={page.slug}>
|
|
||||||
<TableCell className="border-b px-4 py-2">
|
|
||||||
<a
|
|
||||||
href={`/changelogs/${page.slug}`}
|
|
||||||
className="text-blue-500 underline"
|
|
||||||
>
|
|
||||||
{page.slug}
|
|
||||||
</a>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell className="border-b px-4 py-2">
|
|
||||||
<Button
|
|
||||||
variant={"outline"}
|
|
||||||
onClick={() =>
|
|
||||||
router.push(`/admin/changelogs/${page.slug}`)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Section to list and delete logs */}
|
{/* Section to list and delete logs */}
|
||||||
<section id="logs-list" className="py-16 md:py-24">
|
<section id="logs-list" className="py-16 md:py-24">
|
||||||
<h2 className="text-3xl md:text-4xl font-bold">Existing Logs</h2>
|
<h2 className="text-3xl md:text-4xl font-bold">Existing Logs</h2>
|
||||||
|
@ -360,52 +225,6 @@ const AdminLogPage = () => {
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Section to edit selected page */}
|
|
||||||
{selectedPage && (
|
|
||||||
<section id="edit-page" className="py-16 md:py-24">
|
|
||||||
<h2 className="text-3xl md:text-4xl font-bold">Edit Page</h2>
|
|
||||||
<MarkdownEditor
|
|
||||||
value={selectedPage.content}
|
|
||||||
onChange={(value) => {
|
|
||||||
if (value !== undefined) {
|
|
||||||
setSelectedPage((prev) => ({
|
|
||||||
...prev!,
|
|
||||||
content: value,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
className="mt-4"
|
|
||||||
onClick={async () => {
|
|
||||||
if (selectedPage) {
|
|
||||||
const response = await fetch(
|
|
||||||
`/api/mdx/pages/${selectedPage.slug}`,
|
|
||||||
{
|
|
||||||
method: "PUT",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({
|
|
||||||
...selectedPage,
|
|
||||||
content: selectedPage.content,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (response.ok) {
|
|
||||||
toast({ description: "Page successfully updated" });
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
description: "Page update failed",
|
|
||||||
variant: "destructive",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Save Changes
|
|
||||||
</Button>
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,18 +32,16 @@ const EditPage = ({ params }: { params: { slug: string } }) => {
|
||||||
|
|
||||||
const savePage = async () => {
|
const savePage = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await fetch(`/api/mdx/pages/${slug}`, {
|
const response = await fetch(`/api/mdx/pages/${slug}?slug=${slug}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: { "Content-Type": "application/json" },
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ title, content }),
|
body: JSON.stringify({ title, content }),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
toast({ description: "Page successfully updated" });
|
toast({ description: "Page successfully updated" });
|
||||||
router.push("/admin/changelogs");
|
router.push("/admin/multi-logs");
|
||||||
} else {
|
} else {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
toast({ description: "Page update failed", variant: "destructive" });
|
toast({ description: "Page update failed", variant: "destructive" });
|
133
app/(auth)/admin/multi-logs/page.tsx
Normal file
133
app/(auth)/admin/multi-logs/page.tsx
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
"use client";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from "@/components/ui/table";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogFooter,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
|
||||||
|
interface PageEntry {
|
||||||
|
title: string;
|
||||||
|
slug: string;
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AdminLogPage = () => {
|
||||||
|
const [pages, setPages] = useState<PageEntry[]>([]);
|
||||||
|
const { toast } = useToast();
|
||||||
|
const router = useRouter();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [pageTitle, setPageTitle] = useState("");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("/api/mdx/pages")
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => setPages(data))
|
||||||
|
.catch((error) => console.error("Failed to load pages", error));
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const createPage = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const slug = pageTitle.toLowerCase().replace(/\s+/g, "-");
|
||||||
|
const response = await fetch("/api/mdx/pages", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ title: pageTitle, slug, content: "" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const newPage = await response.json();
|
||||||
|
setPages([...pages, newPage]);
|
||||||
|
setPageTitle("");
|
||||||
|
setOpen(false);
|
||||||
|
setLoading(false);
|
||||||
|
toast({ description: "Page created successfully" });
|
||||||
|
} else {
|
||||||
|
console.error("Failed to create page");
|
||||||
|
toast({ description: "Some Error Occured" });
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section id="logs-page" className="wrapper container">
|
||||||
|
<section id="create-page" className="py-16">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold mb-2">Create New Page</h2>
|
||||||
|
<Button variant={"secondary"} onClick={() => setOpen(true)}>
|
||||||
|
Create New Page
|
||||||
|
</Button>
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Enter Page Title</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<Input
|
||||||
|
value={pageTitle}
|
||||||
|
onChange={(e) => setPageTitle(e.target.value)}
|
||||||
|
placeholder="Page Title"
|
||||||
|
/>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button disabled={loading} onClick={createPage}>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</section>
|
||||||
|
<section id="pages-list" className="pb-16">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold">Existing Pages</h2>
|
||||||
|
<p className="mb-4">Total Pages: {pages.length}</p>
|
||||||
|
<Table className="w-full mt-4 border-muted">
|
||||||
|
<TableHeader>
|
||||||
|
<TableRow>
|
||||||
|
<TableHead className="border-b px-4 py-2">Slug</TableHead>
|
||||||
|
<TableHead className="border-b px-4 py-2">Actions</TableHead>
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{pages.map((page) => (
|
||||||
|
<TableRow key={page.slug}>
|
||||||
|
<TableCell className="border-b px-4 py-2">
|
||||||
|
<a
|
||||||
|
href={`/changelogs/${page.slug}`}
|
||||||
|
className="text-blue-500 underline"
|
||||||
|
>
|
||||||
|
{page.slug}
|
||||||
|
</a>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell className="border-b px-4 py-2">
|
||||||
|
<Button
|
||||||
|
variant={"outline"}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/admin/multi-logs/${page.slug}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AdminLogPage;
|
|
@ -11,7 +11,7 @@ const AdminPage = () => {
|
||||||
<Card title="Downloads" url="/admin/downloads" />
|
<Card title="Downloads" url="/admin/downloads" />
|
||||||
<Card title="Mods" url="/admin/mods" />
|
<Card title="Mods" url="/admin/mods" />
|
||||||
<Card title="Logs" url="/admin/changelogs" />
|
<Card title="Logs" url="/admin/changelogs" />
|
||||||
<Card title="Docs" url="/admin" />
|
<Card title="MultiLogs" url="/admin/multi-logs" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -8,15 +8,41 @@ const Page = ({ params }: { params: { slug: string } }) => {
|
||||||
const [page, setPage] = useState<{ title: string; content: string } | null>(
|
const [page, setPage] = useState<{ title: string; content: string } | null>(
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [notFound, setNotFound] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch(`/api/mdx/pages/${slug}`)
|
const fetchPage = async () => {
|
||||||
.then((response) => response.json())
|
try {
|
||||||
.then((data) => setPage(data))
|
const response = await fetch(`/api/mdx/pages/${slug}`);
|
||||||
.catch((error) => console.error("Failed to load page", error));
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
setPage(data);
|
||||||
|
} else {
|
||||||
|
if (response.status === 404) {
|
||||||
|
setNotFound(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load page", error);
|
||||||
|
setNotFound(true);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchPage();
|
||||||
}, [slug]);
|
}, [slug]);
|
||||||
|
|
||||||
if (!page) {
|
if (loading) {
|
||||||
|
return (
|
||||||
|
<section className="flex-center flex-col wrapper container">
|
||||||
|
<p className="text-lg">Loading...</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notFound) {
|
||||||
return (
|
return (
|
||||||
<section id="404error" className="flex-center flex-col wrapper container">
|
<section id="404error" className="flex-center flex-col wrapper container">
|
||||||
<h1 className="text-3xl md:text-5xl text-center">
|
<h1 className="text-3xl md:text-5xl text-center">
|
||||||
|
@ -29,10 +55,18 @@ const Page = ({ params }: { params: { slug: string } }) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!page) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="container mx-auto p-4">
|
<section className="wrapper container py-24 md:py-28 gap-4 flex flex-col">
|
||||||
<h1 className="text-3xl font-bold py-6">{page.title}</h1>
|
<h1 className="text-3xl md:text-5xl font-bold text-black dark:bg-clip-text dark:text-transparent dark:bg-gradient-to-b dark:from-white dark:to-neutral-400">
|
||||||
<ReactMarkdown>{page.content}</ReactMarkdown>
|
{page.title}
|
||||||
|
</h1>
|
||||||
|
<ReactMarkdown className="prose max-w-full prose-lg dark:prose-invert">
|
||||||
|
{page.content}
|
||||||
|
</ReactMarkdown>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,54 +1,22 @@
|
||||||
import { NextApiRequest, NextApiResponse } from "next";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import clientPromise from "@/lib/db";
|
import clientPromise from "@/lib/db";
|
||||||
|
|
||||||
export async function GET(req: NextApiRequest, res: NextApiResponse) {
|
export const GET = async (
|
||||||
const { slug } = req.query;
|
req: NextRequest,
|
||||||
try {
|
{ params }: { params: { slug: string } }
|
||||||
const client = await clientPromise;
|
) => {
|
||||||
const db = client.db();
|
const client = await clientPromise;
|
||||||
const page = await db.collection("pages").findOne({ slug });
|
const db = client.db();
|
||||||
if (page) {
|
const { slug } = params;
|
||||||
res.status(200).json(page);
|
|
||||||
} else {
|
|
||||||
res.status(404).json({ error: "Page not found" });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: "Failed to load page" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function PUT(req: NextApiRequest, res: NextApiResponse) {
|
if (!slug) {
|
||||||
const { slug } = req.query;
|
return NextResponse.json({ message: "Slug is required" }, { status: 400 });
|
||||||
const { title, content } = req.body;
|
|
||||||
try {
|
|
||||||
const client = await clientPromise;
|
|
||||||
const db = client.db();
|
|
||||||
const result = await db
|
|
||||||
.collection("pages")
|
|
||||||
.updateOne({ slug }, { $set: { title, content } });
|
|
||||||
if (result.matchedCount > 0) {
|
|
||||||
const updatedPage = await db.collection("pages").findOne({ slug });
|
|
||||||
res.status(200).json(updatedPage);
|
|
||||||
} else {
|
|
||||||
res.status(404).json({ error: "Page not found" });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: "Failed to update page" });
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export async function DELETE(req: NextApiRequest, res: NextApiResponse) {
|
const page = await db.collection("pages").findOne({ slug });
|
||||||
const { slug } = req.query;
|
if (page) {
|
||||||
try {
|
return NextResponse.json(page, { status: 200 });
|
||||||
const client = await clientPromise;
|
} else {
|
||||||
const db = client.db();
|
return NextResponse.json({ message: "Page not found" }, { status: 404 });
|
||||||
const result = await db.collection("pages").deleteOne({ slug });
|
|
||||||
if (result.deletedCount > 0) {
|
|
||||||
res.status(200).json({ message: "Page successfully deleted" });
|
|
||||||
} else {
|
|
||||||
res.status(404).json({ error: "Page not found" });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: "Failed to delete page" });
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,46 +1,55 @@
|
||||||
import { NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import clientPromise from "@/lib/db";
|
import clientPromise from "@/lib/db";
|
||||||
|
|
||||||
export async function GET() {
|
export const GET = async () => {
|
||||||
try {
|
const client = await clientPromise;
|
||||||
const client = await clientPromise;
|
const db = client.db();
|
||||||
const db = client.db();
|
const pages = await db.collection("pages").find().toArray();
|
||||||
const pages = await db.collection("pages").find({}).toArray();
|
return NextResponse.json(pages, { status: 200 });
|
||||||
return NextResponse.json(pages, { status: 200 });
|
};
|
||||||
} catch (error) {
|
|
||||||
|
export const PUT = async (
|
||||||
|
req: NextRequest,
|
||||||
|
{ params }: { params: { slug: string } }
|
||||||
|
) => {
|
||||||
|
const client = await clientPromise;
|
||||||
|
const db = client.db();
|
||||||
|
const { slug } = params;
|
||||||
|
const { title, content } = await req.json();
|
||||||
|
|
||||||
|
if (!slug) {
|
||||||
|
return NextResponse.json({ message: "Slug is required" }, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await db
|
||||||
|
.collection("pages")
|
||||||
|
.findOneAndUpdate(
|
||||||
|
{ slug },
|
||||||
|
{ $set: { title, content } },
|
||||||
|
{ returnDocument: "after" }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result && result.value) {
|
||||||
|
const page = result.value;
|
||||||
|
return NextResponse.json(page, { status: 200 });
|
||||||
|
} else {
|
||||||
|
return NextResponse.json({ message: "Page not found" }, { status: 404 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const POST = async (req: NextRequest) => {
|
||||||
|
const client = await clientPromise;
|
||||||
|
const db = client.db();
|
||||||
|
const { title, slug, content } = await req.json();
|
||||||
|
|
||||||
|
if (!title || !slug || !content) {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Failed to load pages" },
|
{ message: "Missing required fields" },
|
||||||
{ status: 500 }
|
{ status: 400 }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
const newPage = { title, slug, content };
|
||||||
try {
|
const result = await db.collection("pages").insertOne(newPage);
|
||||||
const body = await req.json();
|
return NextResponse.json(newPage, { status: 201 });
|
||||||
const { title, slug, content } = body;
|
};
|
||||||
|
|
||||||
const client = await clientPromise;
|
|
||||||
const db = client.db();
|
|
||||||
const result = await db
|
|
||||||
.collection("pages")
|
|
||||||
.insertOne({ title, slug, content });
|
|
||||||
|
|
||||||
if (result.acknowledged) {
|
|
||||||
const newPage = await db
|
|
||||||
.collection("pages")
|
|
||||||
.findOne({ _id: result.insertedId });
|
|
||||||
return NextResponse.json(newPage, { status: 201 });
|
|
||||||
} else {
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Failed to create page" },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
return NextResponse.json(
|
|
||||||
{ error: "Failed to create page" },
|
|
||||||
{ status: 500 }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
10
lib/db.ts
10
lib/db.ts
|
@ -2,21 +2,21 @@ import { MongoClient } from "mongodb";
|
||||||
|
|
||||||
// Ensure the environment variable is set
|
// Ensure the environment variable is set
|
||||||
if (!process.env.MONGODB_URI) {
|
if (!process.env.MONGODB_URI) {
|
||||||
throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
|
throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
|
||||||
}
|
}
|
||||||
|
|
||||||
const uri = process.env.MONGODB_URI;
|
const uri = process.env.MONGODB_URI;
|
||||||
const options = {
|
const options = {
|
||||||
// Add any SSL/TLS options if needed, for example:
|
// Add any SSL/TLS options if needed, for example:
|
||||||
// ssl: true,
|
// ssl: true,
|
||||||
// tlsAllowInvalidCertificates: true,
|
// tlsAllowInvalidCertificates: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
let client: MongoClient;
|
let client: MongoClient;
|
||||||
let clientPromise: Promise<MongoClient>;
|
let clientPromise: Promise<MongoClient>;
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
var _mongoClientPromise: Promise<MongoClient> | undefined;
|
var _mongoClientPromise: Promise<MongoClient> | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
client = new MongoClient(uri, options);
|
client = new MongoClient(uri, options);
|
||||||
|
|
0
lib/models/multiLogs.ts
Normal file
0
lib/models/multiLogs.ts
Normal file
Loading…
Reference in a new issue