Skip to content

Commit dab64d4

Browse files
authored
Merge pull request #10 from database-playground/pan93412/dbp-68-login-頁面需要按兩次-google-登入
refactor: improve performance & fix up double login issue
2 parents 4c847de + 6f74b4d commit dab64d4

File tree

18 files changed

+284
-328
lines changed

18 files changed

+284
-328
lines changed

app/(app)/layout.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import AppShell from "@/components/app-shell";
2+
import AuthorizedApolloWrapper from "@/providers/use-apollo.rsc";
3+
import ProtectedRoute from "@/providers/use-protected-route";
24
import { unstable_ViewTransition as ViewTransition } from "react";
35

46
export default function Layout({ children }: { children: React.ReactNode }) {
57
return (
6-
<AppShell>
7-
<div className="mx-auto w-full max-w-7xl flex-1 p-3">
8-
<ViewTransition name="app-content">
9-
<div suppressHydrationWarning>
10-
{children}
8+
<ProtectedRoute>
9+
<AuthorizedApolloWrapper>
10+
<AppShell>
11+
<div className="mx-auto w-full max-w-7xl flex-1 p-3">
12+
<ViewTransition name="app-content">
13+
<div suppressHydrationWarning>{children}</div>
14+
</ViewTransition>
1115
</div>
12-
</ViewTransition>
13-
</div>
14-
</AppShell>
16+
</AppShell>
17+
</AuthorizedApolloWrapper>
18+
</ProtectedRoute>
1519
);
1620
}

app/layout.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import type { Metadata } from "next";
22
import "./globals.css";
33
import { Toaster } from "@/components/ui/sonner";
4-
import { getAuthToken } from "@/lib/auth";
5-
import { ApolloWrapper } from "@/providers/use-apollo";
64
import { ProgressProvider } from "@/providers/use-progress-provider";
75
import { PreloadResources } from "./preload-resources";
86

@@ -18,8 +16,6 @@ export default async function RootLayout({
1816
}: Readonly<{
1917
children: React.ReactNode;
2018
}>) {
21-
const token = await getAuthToken();
22-
2319
return (
2420
<html lang="zh-hant-tw">
2521
<head>
@@ -31,9 +27,7 @@ export default async function RootLayout({
3127
/>
3228
</head>
3329
<body className={`font-sans antialiased`}>
34-
<ApolloWrapper token={token}>
35-
<ProgressProvider delay={500}>{children}</ProgressProvider>
36-
</ApolloWrapper>
30+
<ProgressProvider delay={500}>{children}</ProgressProvider>
3731
<Toaster />
3832
</body>
3933
</html>

app/login/do-you-know.tsx renamed to app/login/_components/do-you-know/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,5 @@ export default async function DoYouKnow() {
2626
</div>
2727
);
2828
}
29+
30+
export { DoYouKnowSkeleton } from "./skeleton";
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Skeleton } from "@/components/ui/skeleton";
2+
3+
export function DoYouKnowSkeleton() {
4+
return (
5+
<div className="flex flex-col justify-center gap-2 text-center">
6+
<div className="text-sm text-gray-500">你知道嗎?</div>
7+
<Skeleton className="h-12 w-56 self-center" />
8+
</div>
9+
);
10+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
2+
3+
export default function GithubLink() {
4+
return (
5+
<Tooltip>
6+
<TooltipTrigger>
7+
<a
8+
className="flex items-center gap-2"
9+
href="https://github.com/database-playground"
10+
target="_blank"
11+
>
12+
<svg
13+
className="h-3.5 w-3.5"
14+
role="img"
15+
viewBox="0 0 24 24"
16+
xmlns="http://www.w3.org/2000/svg"
17+
>
18+
<title>GitHub</title>
19+
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
20+
</svg>
21+
<span className="text-sm">GitHub</span>
22+
</a>
23+
</TooltipTrigger>
24+
25+
<TooltipContent>
26+
向 GitHub 貢獻程式碼,每次都能直接獲得 200 - 700 點不等的點數!
27+
</TooltipContent>
28+
</Tooltip>
29+
);
30+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"use client";
2+
3+
import { Alert, AlertDescription } from "@/components/ui/alert";
4+
import { AlertCircle } from "lucide-react";
5+
import { useSearchParams } from "next/navigation";
6+
7+
export function ErrorAlert() {
8+
const searchParams = useSearchParams();
9+
const error = searchParams.get("error");
10+
const errorDescription = searchParams.get("error_description");
11+
12+
if (!error || !errorDescription) {
13+
return null;
14+
}
15+
16+
return (
17+
<Alert variant="destructive">
18+
<AlertCircle className="h-4 w-4" />
19+
<AlertDescription>
20+
{getErrorMessage(error, errorDescription)}
21+
</AlertDescription>
22+
</Alert>
23+
);
24+
}
25+
26+
function getErrorMessage(error: string, description?: string | null): string {
27+
if (description) return description;
28+
29+
switch (error) {
30+
case "invalid_request":
31+
return "登入請求無效,請重試。";
32+
case "unauthorized":
33+
return "您沒有權限存取此應用程式。";
34+
case "access_denied":
35+
return "登入已取消或拒絕。";
36+
case "server_error":
37+
return "伺服器發生錯誤,請稍後再試。";
38+
case "temporarily_unavailable":
39+
return "服務暫時無法使用,請稍後再試。";
40+
case "auth_error":
41+
return "認證過程中發生錯誤,請重新登入。";
42+
case "logout_failed":
43+
return "登出時發生錯誤,但您的本地工作階段已清除。";
44+
case "forbidden":
45+
return "您沒有權限存取此應用程式。";
46+
default:
47+
return "登入時發生未知錯誤,請重試。";
48+
}
49+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Button } from "@/components/ui/button";
2+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
3+
import { cn } from "@/lib/utils";
4+
import { Suspense } from "react";
5+
import { ErrorAlert } from "./error-alert";
6+
import { MessageAlert } from "./message-alert";
7+
8+
export function LoginForm({
9+
className,
10+
...props
11+
}: React.ComponentPropsWithoutRef<"div">) {
12+
return (
13+
<div className={cn("flex flex-col gap-6", className)} {...props}>
14+
<Suspense>
15+
<ErrorAlert />
16+
<MessageAlert />
17+
</Suspense>
18+
19+
<Card>
20+
<CardHeader className="text-center">
21+
<CardTitle className="text-xl">登入資料庫練功坊</CardTitle>
22+
<CardDescription>
23+
使用您的學校 Gmail 登入資料庫練功坊。
24+
</CardDescription>
25+
</CardHeader>
26+
<CardContent>
27+
<div className="grid gap-6">
28+
<div className="flex flex-col gap-4">
29+
<a href="/api/auth/login">
30+
<Button variant="outline" className="w-full">
31+
<svg
32+
xmlns="http://www.w3.org/2000/svg"
33+
viewBox="0 0 24 24"
34+
className={`mr-2 h-4 w-4`}
35+
>
36+
<path
37+
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
38+
fill="currentColor"
39+
/>
40+
</svg>
41+
使用 Google 登入
42+
</Button>
43+
</a>
44+
</div>
45+
</div>
46+
</CardContent>
47+
</Card>
48+
</div>
49+
);
50+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"use client";
2+
3+
import { Alert, AlertDescription } from "@/components/ui/alert";
4+
import { AlertCircle } from "lucide-react";
5+
import { useSearchParams } from "next/navigation";
6+
7+
export function MessageAlert() {
8+
const searchParams = useSearchParams();
9+
const message = searchParams.get("message");
10+
11+
if (!message) {
12+
return null;
13+
}
14+
15+
return (
16+
<Alert variant="default">
17+
<AlertCircle className="h-4 w-4" />
18+
<AlertDescription>
19+
{getSuccessMessage(message)}
20+
</AlertDescription>
21+
</Alert>
22+
);
23+
}
24+
25+
function getSuccessMessage(message: string): string {
26+
switch (message) {
27+
case "logged_out":
28+
return "您已成功登出。";
29+
default:
30+
return message;
31+
}
32+
}

app/login/status.action.ts renamed to app/login/_components/status/action.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ export async function getUpstreamLatency(): Promise<number> {
66
try {
77
const start = Date.now();
88

9-
const response = await fetch(buildUri("/"));
9+
const response = await fetch(buildUri("/"), {
10+
next: {
11+
revalidate: 120, // update latency every 2 minutes
12+
},
13+
});
1014
if (!response.ok) {
1115
return -1;
1216
}

app/login/status.tsx renamed to app/login/_components/status/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
22
import { Circle } from "lucide-react";
3-
import { getUpstreamLatency } from "./status.action";
3+
import { getUpstreamLatency } from "./action";
44

55
export async function UpstreamStatus() {
66
const latency = await getUpstreamLatency();

0 commit comments

Comments
 (0)