Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions app/(app)/challenges/[id]/_components/gated-ai-assistant.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use server";

import { getAuthorizedUserInfo } from "@/lib/auth.rsc";
import { AIAssistant, type AIAssistantProps } from "./ai-assistant";

export async function GatedAIAssistant({ questionId }: AIAssistantProps) {
const userInfo = await getAuthorizedUserInfo(["*", "ai"]);
if (!userInfo) {
return null;
}

return <AIAssistant questionId={questionId} />;
}
6 changes: 4 additions & 2 deletions app/(app)/challenges/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Metadata } from "next";
import { Suspense } from "react";
import { AIAssistant } from "./_components/ai-assistant";
import { GatedAIAssistant } from "./_components/gated-ai-assistant";
import Header from "./_components/header";
import HeaderSkeleton from "./_components/header/skeleton";
import PracticeIDE from "./_components/ide";
Expand All @@ -26,7 +26,9 @@ export default async function ChallengePage({
<PracticeIDE id={id} />
</Suspense>

<AIAssistant questionId={id} />
<Suspense>
<GatedAIAssistant questionId={id} />
</Suspense>
</div>
);
}
5 changes: 5 additions & 0 deletions app/(app)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ENABLE_STATISTICS_PAGE } from "@/lib/features";
import { redirect } from "next/navigation";

export default function App() {
if (!ENABLE_STATISTICS_PAGE) {
redirect("/challenges");
}

redirect("/statistics");
}
16 changes: 16 additions & 0 deletions app/(app)/statistics/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { ENABLE_STATISTICS_PAGE } from "@/lib/features";
import { AlertCircle } from "lucide-react";
import type { Metadata } from "next";
import { Suspense } from "react";
import Board from "./_components/board";
Expand All @@ -10,6 +13,19 @@ export const metadata: Metadata = {
};

export default function StatisticsPage() {
if (!ENABLE_STATISTICS_PAGE) {
return (
<Alert>
<AlertCircle />
<AlertTitle>系統管理員停用了「統計資料」頁面。</AlertTitle>
<AlertDescription>
如果您需要統計資料,請聯絡系統管理員開啟。<br />
如果您是系統管理員:請將環境變數中 NEXT_PUBLIC_FEATURE_STATISTICS_PAGE 的否定值改為 true。
</AlertDescription>
</Alert>
);
}

return (
<div>
<Board />
Expand Down
13 changes: 9 additions & 4 deletions app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Logo } from "@/components/logo";
import { ENABLE_SOCIAL_PLATFORM } from "@/lib/features";
import type { Metadata } from "next";
import Link from "next/link";
import { Suspense } from "react";
Expand Down Expand Up @@ -59,13 +60,17 @@ export default async function LoginPage() {
<UpstreamStatus />
</Suspense>

<Separator />
{ENABLE_SOCIAL_PLATFORM && (
<>
<Separator />

<GithubLink />
<GithubLink />

<Separator />
<Separator />

<DiscordLink />
<DiscordLink />
</>
)}
</div>
</div>
</div>
Expand Down
27 changes: 16 additions & 11 deletions components/app-navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import AppAvatar from "@/components/avatar";
import { Logo } from "@/components/logo";
import { Button } from "@/components/ui/button";
import useUser from "@/hooks/use-user";
import { ENABLE_SOCIAL_PLATFORM, ENABLE_STATISTICS_PAGE } from "@/lib/features";
import { cn } from "@/lib/utils";
import { BarChart3, BookOpen, ChevronDown, Menu, MessageSquare, Swords, X } from "lucide-react";
import Link from "next/link";
Expand Down Expand Up @@ -171,11 +172,13 @@ interface ExternalNavItem extends BaseNavItem {
type NavItem = InternalNavItem | ExternalNavItem;

const navItems: NavItem[] = [
{
icon: <BarChart3 className="h-full w-full" />,
label: "統計資料",
pathPrefix: "/statistics",
},
ENABLE_STATISTICS_PAGE
? {
icon: <BarChart3 className="h-full w-full" />,
label: "統計資料",
pathPrefix: "/statistics",
}
: undefined,
{
icon: <Swords className="h-full w-full" />,
label: "挑戰題目",
Expand All @@ -186,12 +189,14 @@ const navItems: NavItem[] = [
label: "補充資料",
pathPrefix: "/materials",
},
{
icon: <MessageSquare className="h-full w-full" />,
label: "意見分享",
externalLink: "https://community.dbplay.app/discord",
},
];
ENABLE_SOCIAL_PLATFORM
? {
icon: <MessageSquare className="h-full w-full" />,
label: "意見分享",
externalLink: "https://community.dbplay.app/discord",
}
: undefined,
].filter((item) => item !== undefined);

function getActiveNavItemLabel(path: string): string | null {
for (const item of navItems) {
Expand Down
9 changes: 9 additions & 0 deletions lib/features.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const ENABLE_STATISTICS_PAGE = requireExplicitlyDisabled(process.env.NEXT_PUBLIC_FEATURE_STATISTICS_PAGE);
export const ENABLE_SOCIAL_PLATFORM = requireExplicitlyDisabled(process.env.NEXT_PUBLIC_FEATURE_SOCIAL_PLATFORM);

/**
* Return false if the feature is explicitly disabled; true otherwise.
*/
function requireExplicitlyDisabled(feature: string | undefined) {
return !(feature === "false" || feature === "0");
}