Skip to content

Commit 77f6ef2

Browse files
authored
Merge pull request #2 from database-playground/pan93412/dbp-7-add-lint-and-format-check
DBP-7: add lint and format check
2 parents 8c91d16 + 312e5c7 commit 77f6ef2

File tree

4 files changed

+172
-105
lines changed

4 files changed

+172
-105
lines changed

.github/workflows/lint.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Lint and Format Check
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
jobs:
10+
lint:
11+
name: Run Linters
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- uses: pnpm/action-setup@v4
19+
name: Install pnpm
20+
with:
21+
version: 10
22+
run_install: false
23+
24+
- name: Install Node.js
25+
uses: actions/setup-node@v4
26+
with:
27+
node-version: 20
28+
cache: "pnpm"
29+
30+
- name: Install dependencies
31+
run: pnpm install --frozen-lockfile
32+
33+
- name: Run Next.js lint check
34+
run: pnpm lint
35+
36+
- name: Run dprint format check
37+
run: pnpm format:check

app/(admin)/(question-management)/questions/_components/create.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {
99
DialogTitle,
1010
DialogTrigger,
1111
} from "@/components/ui/dialog";
12+
import { QuestionDifficulty } from "@/gql/graphql";
1213
import { useMutation, useSuspenseQuery } from "@apollo/client";
1314
import { useRouter } from "next/navigation";
1415
import { useState } from "react";
1516
import { toast } from "sonner";
1617
import { QUESTION_CREATE_MUTATION } from "./mutation";
1718
import { DATABASE_LIST_QUERY, QUESTIONS_TABLE_QUERY } from "./query";
1819
import { UpdateQuestionForm, type UpdateQuestionFormData } from "./update-form";
19-
import { QuestionDifficulty } from "@/gql/graphql";
2020

2121
export function CreateQuestionTrigger() {
2222
const router = useRouter();

app/global-error.tsx

Lines changed: 133 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,13 @@
11
"use client";
22

3+
import { Logo } from "@/components/logo";
4+
import { Badge } from "@/components/ui/badge";
35
import { Button } from "@/components/ui/button";
46
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
5-
import { Badge } from "@/components/ui/badge";
6-
import {
7-
ERROR_NOT_FOUND,
8-
ERROR_UNAUTHORIZED,
9-
ERROR_USER_VERIFIED,
10-
ERROR_NOT_IMPLEMENTED
11-
} from "@/lib/apollo";
7+
import { ERROR_NOT_FOUND, ERROR_NOT_IMPLEMENTED, ERROR_UNAUTHORIZED, ERROR_USER_VERIFIED } from "@/lib/apollo";
128
import { ApolloError } from "@apollo/client";
13-
import {
14-
AlertCircle,
15-
RefreshCw,
16-
Home,
17-
Lock,
18-
Search,
19-
WifiOff,
20-
Code,
21-
Shield
22-
} from "lucide-react";
9+
import { AlertCircle, Code, Home, Lock, RefreshCw, Search, Shield, WifiOff } from "lucide-react";
2310
import Link from "next/link";
24-
import { Logo } from "@/components/logo";
2511
import { useEffect } from "react";
2612

2713
interface GlobalErrorProps {
@@ -33,32 +19,32 @@ function getErrorInfo(error: Error | ApolloError) {
3319
// Check if it's an ApolloError
3420
if (error instanceof ApolloError) {
3521
// Network errors
36-
if (error.networkError && 'statusCode' in error.networkError) {
22+
if (error.networkError && "statusCode" in error.networkError) {
3723
switch (error.networkError.statusCode) {
3824
case 401:
3925
return {
4026
title: "未經授權",
4127
description: "您的登入狀態已過期,請重新登入。",
4228
icon: Lock,
43-
actionHref: "/login"
29+
actionHref: "/login",
4430
};
4531
case 403:
4632
return {
47-
title: "權限不足",
33+
title: "權限不足",
4834
description: "您沒有權限執行此操作。",
49-
icon: Shield
35+
icon: Shield,
5036
};
5137
case 404:
5238
return {
5339
title: "找不到資源",
54-
description: "請求的資源不存在或已被移除。",
55-
icon: Search
40+
description: "請求的資源不存在或已被移除。",
41+
icon: Search,
5642
};
5743
case 500:
5844
return {
5945
title: "伺服器錯誤",
6046
description: "伺服器發生內部錯誤,請稍後再試。",
61-
icon: AlertCircle
47+
icon: AlertCircle,
6248
};
6349
}
6450
}
@@ -67,7 +53,7 @@ function getErrorInfo(error: Error | ApolloError) {
6753
return {
6854
title: "網路連線錯誤",
6955
description: "無法連接到伺服器,請檢查網路連線。",
70-
icon: WifiOff
56+
icon: WifiOff,
7157
};
7258
}
7359

@@ -81,33 +67,33 @@ function getErrorInfo(error: Error | ApolloError) {
8167
return {
8268
title: "找不到資料",
8369
description: "請求的資料不存在或已被刪除。",
84-
icon: Search
70+
icon: Search,
8571
};
8672
case ERROR_UNAUTHORIZED:
8773
return {
88-
title: "未經授權",
74+
title: "未經授權",
8975
description: "請登入後再試,或您的權限不足。",
9076
icon: Lock,
91-
actionHref: "/login"
77+
actionHref: "/login",
9278
};
9379
case ERROR_USER_VERIFIED:
9480
return {
9581
title: "帳號已驗證",
9682
description: "此帳號已經完成驗證程序。",
97-
icon: Shield
83+
icon: Shield,
9884
};
9985
case ERROR_NOT_IMPLEMENTED:
10086
return {
10187
title: "功能未實作",
10288
description: "此功能目前尚未實作,請稍後再試。",
103-
icon: Code
89+
icon: Code,
10490
};
10591
}
10692

10793
return {
10894
title: "GraphQL 查詢錯誤",
10995
description: firstError.message || "GraphQL 查詢發生錯誤。",
110-
icon: AlertCircle
96+
icon: AlertCircle,
11197
};
11298
}
11399
}
@@ -116,7 +102,7 @@ function getErrorInfo(error: Error | ApolloError) {
116102
return {
117103
title: "應用程式發生錯誤",
118104
description: error.message || "應用程式遇到預期外的錯誤。",
119-
icon: AlertCircle
105+
icon: AlertCircle,
120106
};
121107
}
122108

@@ -152,91 +138,141 @@ export default function GlobalError({ error, reset }: GlobalErrorProps) {
152138
</div>
153139
Database Playground
154140
</Link>
155-
156-
<Card className="min-w-md max-w-2xl">
157-
<CardHeader className="flex w-full flex-col items-center text-center">
141+
142+
<Card className="max-w-2xl min-w-md">
143+
<CardHeader
144+
className={`flex w-full flex-col items-center text-center`}
145+
>
158146
<errorInfo.icon className="mb-2 size-7 text-red-500" />
159147
<CardTitle className="text-xl">{errorInfo.title}</CardTitle>
160148
<CardDescription>
161149
{errorInfo.description}
162150
</CardDescription>
163151
</CardHeader>
164-
152+
165153
<CardContent className="flex flex-col items-center gap-4">
166-
<div className="w-full rounded-md bg-red-50 p-4 text-left">
167-
<details className="text-sm">
168-
<summary className="cursor-pointer font-medium text-red-800">
169-
錯誤詳細資訊
170-
</summary>
171-
<div className="text-red-700 space-y-2 mt-2">
172-
<p className="font-medium">{error.name}: {error.message}</p>
173-
174-
{error.stack && (
175-
<pre className="whitespace-pre-wrap text-xs bg-red-100 p-2 rounded overflow-x-auto">
154+
<div className="w-full rounded-md bg-red-50 p-4 text-left">
155+
<details className="text-sm">
156+
<summary className="cursor-pointer font-medium text-red-800">
157+
錯誤詳細資訊
158+
</summary>
159+
<div className="mt-2 space-y-2 text-red-700">
160+
<p className="font-medium">{error.name}: {error.message}</p>
161+
162+
{error.stack && (
163+
<pre
164+
className={`
165+
overflow-x-auto rounded bg-red-100 p-2 text-xs
166+
whitespace-pre-wrap
167+
`}
168+
>
176169
{error.stack}
177-
</pre>
178-
)}
179-
180-
{error instanceof ApolloError && (
181-
<div className="space-y-2">
182-
{error.networkError && (
183-
<div>
184-
<Badge variant="destructive" className="text-xs mb-1">Network Error</Badge>
185-
<pre className="whitespace-pre-wrap text-xs bg-red-100 p-2 rounded">
170+
</pre>
171+
)}
172+
173+
{error instanceof ApolloError && (
174+
<div className="space-y-2">
175+
{error.networkError && (
176+
<div>
177+
<Badge
178+
variant="destructive"
179+
className={`mb-1 text-xs`}
180+
>
181+
Network Error
182+
</Badge>
183+
<pre
184+
className={`
185+
rounded bg-red-100 p-2 text-xs
186+
whitespace-pre-wrap
187+
`}
188+
>
186189
{JSON.stringify(error.networkError, null, 2)}
187-
</pre>
188-
</div>
189-
)}
190-
191-
{error.graphQLErrors && error.graphQLErrors.length > 0 && (
192-
<div>
193-
<Badge variant="destructive" className="text-xs mb-1">
194-
GraphQL Errors ({error.graphQLErrors.length})
195-
</Badge>
196-
<pre className="whitespace-pre-wrap text-xs bg-red-100 p-2 rounded">
190+
</pre>
191+
</div>
192+
)}
193+
194+
{error.graphQLErrors && error.graphQLErrors.length > 0 && (
195+
<div>
196+
<Badge
197+
variant="destructive"
198+
className={`mb-1 text-xs`}
199+
>
200+
GraphQL Errors ({error.graphQLErrors.length})
201+
</Badge>
202+
<pre
203+
className={`
204+
rounded bg-red-100 p-2 text-xs
205+
whitespace-pre-wrap
206+
`}
207+
>
197208
{JSON.stringify(error.graphQLErrors, null, 2)}
198-
</pre>
199-
</div>
200-
)}
201-
</div>
202-
)}
203-
</div>
204-
</details>
205-
</div>
206-
207-
<div className="flex flex-col sm:flex-row gap-3">
208-
<Button onClick={reset} variant="default" className="flex items-center gap-2">
209+
</pre>
210+
</div>
211+
)}
212+
</div>
213+
)}
214+
</div>
215+
</details>
216+
</div>
217+
218+
<div
219+
className={`
220+
flex flex-col gap-3
221+
sm:flex-row
222+
`}
223+
>
224+
<Button
225+
onClick={reset}
226+
variant="default"
227+
className={`flex items-center gap-2`}
228+
>
209229
<RefreshCw className="size-4" />
210230
重試
211231
</Button>
212-
213-
{errorInfo.actionHref ? (
214-
<Button asChild variant="outline" className="flex items-center gap-2">
215-
<Link href={errorInfo.actionHref}>
216-
前往處理
217-
</Link>
218-
</Button>
219-
) : (
220-
<Button asChild variant="outline" className="flex items-center gap-2">
221-
<Link href="/">
222-
<Home className="size-4" />
223-
回到首頁
224-
</Link>
225-
</Button>
226-
)}
232+
233+
{errorInfo.actionHref
234+
? (
235+
<Button
236+
asChild
237+
variant="outline"
238+
className={`flex items-center gap-2`}
239+
>
240+
<Link href={errorInfo.actionHref}>
241+
前往處理
242+
</Link>
243+
</Button>
244+
)
245+
: (
246+
<Button
247+
asChild
248+
variant="outline"
249+
className={`flex items-center gap-2`}
250+
>
251+
<Link href="/">
252+
<Home className="size-4" />
253+
回到首頁
254+
</Link>
255+
</Button>
256+
)}
227257
</div>
228258
</CardContent>
229-
259+
230260
<CardFooter
231-
className={`justify-center text-center text-xs text-muted-foreground`}
261+
className={`
262+
justify-center text-center text-xs text-muted-foreground
263+
`}
232264
>
233265
<section className="flex flex-col items-center gap-1">
234266
<p>如果問題持續發生,請聯絡開發者進行處理。</p>
235267
<p className="text-red-600">
236-
錯誤時間:{new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' })}
268+
錯誤時間:{new Date().toLocaleString("zh-TW", { timeZone: "Asia/Taipei" })}
237269
</p>
238-
{'digest' in error && error.digest && (
239-
<p className="text-red-600">錯誤 ID:{error.digest}</p>
270+
{"digest" in error && error.digest && (
271+
<p
272+
className={`text-red-600`}
273+
>
274+
錯誤 ID:{error.digest}
275+
</p>
240276
)}
241277
</section>
242278
</CardFooter>

0 commit comments

Comments
 (0)