Skip to content

Commit

Permalink
refactor: refactor project server side code, abandon nextjs server si…
Browse files Browse the repository at this point in the history
…de rendering
  • Loading branch information
MR-Addict committed Oct 31, 2024
1 parent 83fd2fc commit fa641d4
Show file tree
Hide file tree
Showing 45 changed files with 1,654 additions and 743 deletions.
1,144 changes: 1,100 additions & 44 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@
"@types/react-dom": "^18.3.1",
"@uiw/codemirror-theme-vscode": "^4.23.6",
"@uiw/react-codemirror": "^4.23.6",
"antd": "^5.21.6",
"autoprefixer": "^10.4.20",
"chart.js": "^4.4.6",
"chartjs-plugin-datalabels": "^2.2.0",
"clsx": "^2.1.1",
"framer-motion": "^11.11.10",
"postcss": "^8.4.47",
"prettier": "^3.3.3",
"react": "^18.3.1",
"react-chartjs-2": "^5.2.0",
"react-confetti": "^6.1.0",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.1",
Expand Down
4 changes: 2 additions & 2 deletions src/app/api/env/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export const dynamic = "force-dynamic";

import { PublicEnv } from "@/types/env";

export const dynamic = "force-dynamic";

export async function GET() {
return Response.json(PublicEnv.parse(process.env));
}
22 changes: 17 additions & 5 deletions src/app/api/note/route.ts → src/app/api/notes/route.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import { revalidatePath } from "next/cache";

import { PublicEnv } from "@/types/env";
import notes from "@/lib/mongodb/notes";
import getISOWeekNumber from "@/lib/utils/getISOWeekNumber";
import getArchivedNotes from "@/lib/notes/getArchivedNotes";

export async function GET(request: Request) {
const searchParams = new URL(request.url).searchParams;
const query = searchParams.get("query") || "";
const page = parseInt(searchParams.get("page") || "1");
const pageSize = parseInt(searchParams.get("pageSize") || "20");
const termIndex = parseInt(searchParams.get("termIndex") || "0");

if (termIndex > 0) {
const res = getArchivedNotes(termIndex - 1, page, pageSize, query);
return new Response(JSON.stringify(res), { headers: { "content-type": "application/json" }, status: res.code });
}

const result = await notes.query(page, pageSize, query);
return new Response(JSON.stringify(result), { headers: { "content-type": "application/json" }, status: result.code });
}

export async function POST(request: Request) {
const env = PublicEnv.parse(process.env);
Expand Down Expand Up @@ -48,8 +63,5 @@ export async function POST(request: Request) {
const week = getISOWeekNumber(now) - getISOWeekNumber(env.FIRST_WEEK) + 1;
const result = await notes.insert({ week, name, useMarkdown, content });

// revalidate and resonse result
if (result.success) revalidatePath("/view", "page");

return Response.json(result);
}
10 changes: 10 additions & 0 deletions src/app/api/terms/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Env } from "@/types/env";
import getArchivedTerms from "@/lib/notes/getArchivedTerms";

export const dynamic = "force-dynamic";

export async function GET() {
const currentTerm = Env.parse(process.env).CURRENT_TERM;
const archivedTerms = getArchivedTerms().map((term) => term.name);
return Response.json([currentTerm, ...archivedTerms]);
}
178 changes: 85 additions & 93 deletions src/app/form/components/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import Link from "next/link";
import toast from "react-hot-toast";
import Confetti from "react-confetti";

import { useRouter } from "next/navigation";
import { useState, useEffect } from "react";
import { MdOutlineFullscreen } from "react-icons/md";
import { FaRegUser, FaRegEdit } from "react-icons/fa";
Expand All @@ -22,8 +21,6 @@ import MarkdownEditor from "@/components/MarkdownEditor/MarkdownEditor";
const cookieName = "punch-last-submit-date";

export default function Form() {
const router = useRouter();

const [useMarkdown, setUseMarkdown] = useState(false);
const [name, setName] = usePersistantState("form-name", "");
const [content, setContent] = usePersistantState("form-content", "");
Expand All @@ -44,10 +41,9 @@ export default function Form() {
const { success, message } = z.object({ success: z.boolean(), message: z.string() }).parse(res);

if (success) {
document.cookie = `${cookieName}=${new Date().toISOString()};max-age=${60 * 60 * 24};path=/;`;
setStatus("done");
setContent("");
router.refresh();
setStatus("done");
document.cookie = `${cookieName}=${new Date().toISOString()};max-age=${60 * 60 * 24};path=/;`;
} else {
console.error(message);
toast.error(message);
Expand All @@ -66,8 +62,9 @@ export default function Form() {
else setStatus("idle");
}, []);

if (!status) return <></>;
else if (status !== "idle") {
if (!status) return null;

if (status !== "idle") {
return (
<div className="flex flex-col items-center gap-3">
{status === "done" && (
Expand All @@ -82,93 +79,88 @@ export default function Form() {
</Link>
</div>
);
} else {
return (
<form className={style.form} onSubmit={handleSubmit}>
<MarkdownEditor
content={content}
openEditor={openEditor}
setContent={setContent}
setOpenEditor={setOpenEditor}
/>

<header className="w-full space-y-2">
<h1 className="text-2xl font-semibold border-b-4 border-b-black w-fit">值班笔记</h1>
<p className="text-gray-500 border-b border-b-gray-300 italic">"在无聊的时间里就从事学习"</p>
</header>

<div className="w-full flex flex-col gap-3">
<section className={style["input-element"]}>
<label className={style.label} htmlFor="submitFormName">
<FaRegUser size={13} />
<span>姓名</span>
</label>
<input
}

return (
<form className={style.form} onSubmit={handleSubmit}>
<MarkdownEditor content={content} openEditor={openEditor} setContent={setContent} setOpenEditor={setOpenEditor} />

<header className="w-full space-y-2">
<h1 className="text-2xl font-semibold border-b-4 border-b-black w-fit">值班笔记</h1>
<p className="text-gray-500 border-b border-b-gray-300 italic">"在无聊的时间里就从事学习"</p>
</header>

<div className="w-full flex flex-col gap-3">
<section className={style["input-element"]}>
<label className={style.label} htmlFor="submitFormName">
<FaRegUser size={13} />
<span>姓名</span>
</label>
<input
required
type="text"
name="name"
id="submitFormName"
placeholder="姓名"
minLength={2}
maxLength={10}
value={name}
className={style.input}
autoFocus={name.length === 0}
onChange={(e) => setName(e.target.value)}
/>
</section>

<section className={style["input-element"]}>
<label className={style.label} htmlFor="submitFormContent">
<FaRegEdit size={15} />
<span>值班笔记</span>
</label>

<div className={style.input}>
<textarea
required
type="text"
name="name"
id="submitFormName"
placeholder="姓名"
minLength={2}
maxLength={10}
value={name}
className={style.input}
autoFocus={name.length === 0}
onChange={(e) => setName(e.target.value)}
maxLength={1000}
name="content"
id="submitFormContent"
placeholder="写写今天都发生了什么"
value={content}
style={{ height: 150 }}
autoFocus={name.length > 0}
onChange={(e) => setContent(e.target.value)}
className="peer w-full h-full resize-none outline-none"
/>
</section>

<section className={style["input-element"]}>
<label className={style.label} htmlFor="submitFormContent">
<FaRegEdit size={15} />
<span>值班笔记</span>
</label>

<div className={style.input}>
<textarea
required
maxLength={1000}
name="content"
id="submitFormContent"
placeholder="写写今天都发生了什么"
value={content}
style={{ height: 150 }}
autoFocus={name.length > 0}
onChange={(e) => setContent(e.target.value)}
className="peer w-full h-full resize-none outline-none"
/>

<div className="flex flex-row items-center justify-between">
<p className={clsx("text-xs", content.length > 1000 ? "text-red-600" : "text-gray-600")}>
{`${content.length}/1000`}
</p>

<button
type="button"
title="打开Markdown编辑器"
onClick={() => setOpenEditor(true)}
className={clsx(style["open-editor-btn"], { [style.active]: useMarkdown })}
>
<MdOutlineFullscreen size={20} />
</button>
</div>

<div className="flex flex-row items-center justify-between">
<p className={clsx("text-xs", content.length > 1000 ? "text-red-600" : "text-gray-600")}>
{`${content.length}/1000`}
</p>

<button
type="button"
title="打开Markdown编辑器"
onClick={() => setOpenEditor(true)}
className={clsx(style["open-editor-btn"], { [style.active]: useMarkdown })}
>
<MdOutlineFullscreen size={20} />
</button>
</div>
</div>

<label htmlFor="submitFormUseMarkdown" className="flex flex-row items-center gap-1 mt-0.5">
<input
type="checkbox"
name="useMarkdown"
id="submitFormUseMarkdown"
checked={useMarkdown}
onChange={(e) => setUseMarkdown(e.target.checked)}
/>
<p className="select-none text-xs">使用Markdown</p>
</label>
</section>
</div>

<SubmitButton pending={pending} />
</form>
);
}
<label htmlFor="submitFormUseMarkdown" className="flex flex-row items-center gap-1 mt-0.5">
<input
type="checkbox"
name="useMarkdown"
id="submitFormUseMarkdown"
checked={useMarkdown}
onChange={(e) => setUseMarkdown(e.target.checked)}
/>
<p className="select-none text-xs">使用Markdown</p>
</label>
</section>
</div>

<SubmitButton pending={pending} />
</form>
);
}
19 changes: 13 additions & 6 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import "./globals.css";

import { Suspense } from "react";
import { Toaster } from "react-hot-toast";

import { AppContextProvider } from "@/contexts/App/AppProvider";
import { ViewContextProvider } from "@/contexts/View/ViewProvider";

import TopNavbar from "@/components/Navbar/TopNavbar/TopNavbar";
import BottomNavbar from "@/components/Navbar/BottomNavbar/BottomNavbar";
Expand All @@ -10,12 +13,16 @@ export default function RootLayout({ children }: { children: React.ReactNode })
return (
<html lang="zh-Hans">
<body>
<AppContextProvider>
<Toaster />
<TopNavbar />
{children}
<BottomNavbar />
</AppContextProvider>
<Suspense>
<AppContextProvider>
<ViewContextProvider>
<Toaster />
<TopNavbar />
{children}
<BottomNavbar />
</ViewContextProvider>
</AppContextProvider>
</Suspense>
</body>
</html>
);
Expand Down
47 changes: 4 additions & 43 deletions src/app/view/Client.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,13 @@
"use client";

import Tabs from "./components/Tabs/Tabs";
import Table from "./components/Table/Table";
import Chips from "./components/Chips/Chips";
import Filter from "./components/Filter/Filter";
import Message from "@/components/Message/Message";
import Searchbar from "./components/Searchbar/Searchbar";
import AreaCharts from "./components/AreaCharts/AreaCharts";
import Pagination from "./components/Pagination/Pagination";

import timeInterval from "@/lib/utils/timeInterval";
import { useViewContext } from "@/contexts/View/ViewProvider";
import Body from "./components/Body/Body";
import Header from "./components/Header/Header";

export default function Client() {
const { activeTab, archives, lastSynchronized } = useViewContext();

if (archives.length === 0) {
return (
<main className="flex flex-col items-center justify-center">
<Message message="还没有人提交值班笔记,快去提交一个吧" icon="people" />
</main>
);
}

return (
<main className="py-5 md:py-10 flex flex-col gap-6">
<div className="flex flex-row justify-between items-center">
{archives.length > 1 && <Filter />}
<Tabs />
</div>

<div className="flex-1 flex flex-col gap-4">
{activeTab === "table" && (
<>
<Searchbar />
<Table />
<Pagination />
</>
)}
{activeTab === "chart" && (
<>
<Chips />
<AreaCharts />
</>
)}
</div>

<p className="mx-auto text-xs text-gray-600">数据库上次同步于{timeInterval(lastSynchronized)}</p>
<Header />
<Body />
</main>
);
}
Loading

0 comments on commit fa641d4

Please sign in to comment.