Skip to content

Commit 25dd153

Browse files
authored
Merge pull request #32 from database-playground/pan93412/dbp-35-redirect-comments-to-discord-community
DBP-35: redirect comments page to discord community
2 parents b0690ef + 2b1cf30 commit 25dd153

File tree

8 files changed

+190
-116
lines changed

8 files changed

+190
-116
lines changed

app/(app)/comments/page.tsx

Lines changed: 0 additions & 27 deletions
This file was deleted.

app/not-found.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import NotFoundLayout from "@/components/not-found-layout";
2+
3+
export default async function NotFoundPage() {
4+
return <NotFoundLayout />;
5+
}

components/app-navbar.tsx

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function NavItem({ icon, label, active = false }: NavItemProps) {
2727
active && "bg-primary text-primary-foreground",
2828
)}
2929
>
30-
<div className="h-4 w-4 flex-shrink-0">{icon}</div>
30+
<div className="h-4 w-4 shrink-0">{icon}</div>
3131
<span className="whitespace-nowrap">{label}</span>
3232
</Button>
3333
);
@@ -45,7 +45,7 @@ function UserMenu() {
4545
>
4646
<AppAvatar src={user?.avatar} name={user?.name} className="h-4 w-4" />
4747
<span className="whitespace-nowrap">{user?.name}</span>
48-
<ChevronDown className="h-4 w-4 flex-shrink-0" />
48+
<ChevronDown className="h-4 w-4 shrink-0" />
4949
</Button>
5050
</DropdownMenuTrigger>
5151

@@ -86,14 +86,11 @@ export default function AppNavbar({ path }: { path: string }) {
8686
`}
8787
>
8888
{navItems.map((item) => (
89-
<Link href={item.pathPrefix} key={item.label}>
90-
<NavItem
91-
key={item.label}
92-
icon={item.icon}
93-
label={item.label}
94-
active={navItemLabel === item.label}
95-
/>
96-
</Link>
89+
<NavItemLink
90+
key={item.label}
91+
item={item}
92+
active={navItemLabel === item.label}
93+
/>
9794
))}
9895
</div>
9996
</div>
@@ -136,18 +133,12 @@ export default function AppNavbar({ path }: { path: string }) {
136133
<div className="flex flex-col space-y-1 px-6 py-4">
137134
{/* Mobile Navigation Items */}
138135
{navItems.map((item) => (
139-
<Link
140-
href={item.pathPrefix}
136+
<NavItemLink
141137
key={item.label}
138+
item={item}
139+
active={navItemLabel === item.label}
142140
onClick={() => setIsMobileMenuOpen(false)}
143-
>
144-
<NavItem
145-
key={item.label}
146-
icon={item.icon}
147-
label={item.label}
148-
active={navItemLabel === item.label}
149-
/>
150-
</Link>
141+
/>
151142
))}
152143

153144
{/* Mobile User Menu */}
@@ -164,12 +155,21 @@ export default function AppNavbar({ path }: { path: string }) {
164155
);
165156
}
166157

167-
interface NavItem {
158+
interface BaseNavItem {
168159
icon: React.ReactNode;
169160
label: string;
161+
}
162+
163+
interface InternalNavItem extends BaseNavItem {
170164
pathPrefix: string;
171165
}
172166

167+
interface ExternalNavItem extends BaseNavItem {
168+
externalLink: string;
169+
}
170+
171+
type NavItem = InternalNavItem | ExternalNavItem;
172+
173173
const navItems: NavItem[] = [
174174
{
175175
icon: <BarChart3 className="h-full w-full" />,
@@ -181,24 +181,48 @@ const navItems: NavItem[] = [
181181
label: "挑戰題目",
182182
pathPrefix: "/challenges",
183183
},
184-
{
185-
icon: <MessageSquare className="h-full w-full" />,
186-
label: "經驗分享",
187-
pathPrefix: "/comments",
188-
},
189184
{
190185
icon: <BookOpen className="h-full w-full" />,
191186
label: "補充資料",
192187
pathPrefix: "/materials",
193188
},
189+
{
190+
icon: <MessageSquare className="h-full w-full" />,
191+
label: "意見分享",
192+
externalLink: "https://community.dbplay.app/discord",
193+
},
194194
];
195195

196196
function getActiveNavItemLabel(path: string): string | null {
197197
for (const item of navItems) {
198-
if (path.startsWith(item.pathPrefix)) {
198+
if ("pathPrefix" in item && path.startsWith(item.pathPrefix)) {
199199
return item.label;
200200
}
201201
}
202202

203203
return null;
204204
}
205+
206+
function NavItemLink({ item, active, onClick }: { item: NavItem; active?: boolean; onClick?: () => void }) {
207+
if ("pathPrefix" in item) {
208+
return (
209+
<Link href={item.pathPrefix} onClick={onClick}>
210+
<NavItem
211+
icon={item.icon}
212+
label={item.label}
213+
active={active}
214+
/>
215+
</Link>
216+
);
217+
}
218+
219+
return (
220+
<a href={item.externalLink} target="_blank" rel="noopener noreferrer" onClick={onClick}>
221+
<NavItem
222+
icon={item.icon}
223+
label={item.label}
224+
active={active}
225+
/>
226+
</a>
227+
);
228+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use client";
2+
3+
import dynamic from "next/dynamic";
4+
import CurrentPage from "./current-page";
5+
6+
export const CurrentPageLazy = dynamic(() => Promise.resolve(CurrentPage), {
7+
ssr: false,
8+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Get the current page URL.
3+
*
4+
* Note that this function is not SSR-friendly.
5+
* You should import it with `current-page.lazy.tsx`, which disables SSR.
6+
*/
7+
export default function CurrentPage() {
8+
return <p>網址:{window.location.href}</p>;
9+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Logo } from "@/components/logo";
2+
import { Button } from "@/components/ui/button";
3+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
4+
import { AlertTriangle } from "lucide-react";
5+
import Link from "next/link";
6+
import { Suspense } from "react";
7+
import { CurrentPageLazy } from "./current-page.lazy";
8+
9+
export default async function NotFoundLayout() {
10+
return (
11+
<div
12+
className={`
13+
flex min-h-svh flex-col items-center justify-center gap-6
14+
bg-linear-to-br from-red-50 via-white to-red-100 p-6
15+
md:p-10
16+
`}
17+
>
18+
<Link
19+
href="/"
20+
className={`flex items-center gap-2 self-center font-medium`}
21+
>
22+
<div
23+
className={`
24+
flex size-6 items-center justify-center rounded-md
25+
text-primary-foreground
26+
`}
27+
>
28+
<Logo />
29+
</div>
30+
資料庫練功坊
31+
</Link>
32+
<Card className="min-w-md">
33+
<CardHeader className="flex w-full flex-col items-center text-center">
34+
<AlertTriangle className="mb-2 size-7 text-red-500" />
35+
<CardTitle className="text-xl">找不到此頁面</CardTitle>
36+
<CardDescription>
37+
此頁面不存在或已經被移除。<br />請確認網址是否正確,或回到首頁。
38+
</CardDescription>
39+
</CardHeader>
40+
<CardContent className="flex flex-col items-center gap-4">
41+
<Button asChild variant="outline">
42+
<Link href="/">回到首頁</Link>
43+
</Button>
44+
</CardContent>
45+
<CardFooter
46+
className={`justify-center text-center text-xs text-muted-foreground`}
47+
>
48+
<Suspense>
49+
<CurrentPageLazy />
50+
</Suspense>
51+
</CardFooter>
52+
</Card>
53+
</div>
54+
);
55+
}

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
"foxact": "^0.2.49",
5050
"graphql": "^16.11.0",
5151
"lucide-react": "^0.546.0",
52-
"next": "16.0.0-canary.17",
52+
"next": "16.0.0",
5353
"next-themes": "^0.4.6",
5454
"posthog-js": "1.278.0",
5555
"posthog-node": "^5.10.2",
@@ -81,7 +81,7 @@
8181
"@typescript-eslint/parser": "^8.46.2",
8282
"dprint": "^0.50.2",
8383
"eslint": "^9.38.0",
84-
"eslint-config-next": "16.0.0-canary.17",
84+
"eslint-config-next": "16.0.0",
8585
"eslint-plugin-better-tailwindcss": "^3.7.10",
8686
"tailwindcss": "^4.1.15",
8787
"tw-animate-css": "^1.4.0",

0 commit comments

Comments
 (0)