Skip to content

Commit db30aa4

Browse files
committed
Refactor: 更新開發文件, Dev Container。AI重構404倒數邏輯、QR Code生成器的資源釋放、RFID轉換器的字串處理、刪除多餘首頁連結。
1 parent 3050e3e commit db30aa4

7 files changed

Lines changed: 57 additions & 40 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,13 @@
55
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
66
"image": "mcr.microsoft.com/devcontainers/javascript-node:24-bookworm",
77
"features": {
8-
"ghcr.io/devcontainers/features/github-cli:1": {
9-
"installDirectlyFromGitHubRelease": true,
10-
"version": "latest"
11-
},
8+
"ghcr.io/devcontainers/features/github-cli:1": {},
129
"ghcr.io/devcontainers/features/node:1": {
1310
"nodeGypDependencies": true,
1411
"installYarnUsingApt": true,
15-
"version": "24.14.0",
16-
"pnpmVersion": "latest",
17-
"nvmVersion": "latest"
12+
"version": "24.14.0"
1813
}
19-
}
14+
},
2015

2116
// Features to add to the dev container. More info: https://containers.dev/features.
2217
// "features": {},
@@ -25,7 +20,7 @@
2520
// "forwardPorts": [],
2621

2722
// Use 'postCreateCommand' to run commands after the container is created.
28-
// "postCreateCommand": "yarn install",
23+
"postCreateCommand": "yarn"
2924

3025
// Configure tool-specific properties.
3126
// "customizations": {},

CLAUDE.md renamed to AGENTS.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
1-
# CLAUDE.md
1+
# AGENTS.md
22

3-
此文件為 Claude Code (claude.ai/code) 在處理此專案時的開發指引。
3+
此文件為各種 AI Coding Agent 在處理此專案時的開發指引。
4+
5+
## Agent 必讀規範
6+
7+
- 只使用 Yarn,禁止使用 npm(安裝與執行腳本皆同)。
8+
- 不要修改 `public/` 內容:該目錄為建置產物,應由 `yarn build` 生成。
9+
- 變更應聚焦需求本身,避免順手重構不相干檔案。
10+
- 修改 JSON 資料時務必維持既有 schema,避免破壞 Gatsby build。
11+
- 提交前一定要執行 `yarn prettier` 以統一程式碼風格。
12+
- 涉及 API 端點(`functions/api/`)時,需保留 CORS 行為與既有回傳格式相容性。
13+
14+
## Agent 工作流程
15+
16+
1. 先讀需求,再找出受影響檔案與資料來源(頁面、模板、JSON、API)。
17+
2. 優先做最小變更,避免改動既有命名與資料路徑。
18+
3. 完成修改後執行格式化與必要建置檢查。
19+
4. 回報變更檔案、核心差異、驗證結果與未完成風險。
420

521
## 專案概述
622

@@ -47,7 +63,7 @@ yarn prettier
4763
### 專案結構
4864

4965
```
50-
├── CLAUDE.md # 開發指引文件
66+
├── AGENTS.md # Agent 開發指引文件
5167
├── README.md # 專案說明文件
5268
├── package.json # 相依套件與腳本
5369
├── gatsby-config.js # Gatsby 設定檔

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
## Quick start
1717

18-
先安裝依賴
18+
先安裝依賴(如使用 Dev Container 可省略)
1919

2020
```bash
2121
yarn

src/pages/404.js

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,39 +8,38 @@ const NotFoundPage = () => {
88

99
// 開始倒數
1010
React.useEffect(() => {
11-
let id = setInterval(() => {
12-
setCountDown(countDown - 1);
11+
const id = setInterval(() => {
12+
setCountDown((prev) => prev - 1);
1313
}, 1000);
1414
return () => clearInterval(id);
15-
});
15+
}, []);
1616

1717
// 倒數結束回首頁
1818
React.useEffect(() => {
1919
if (countDown <= 0) {
2020
window.location.href = "/";
2121
}
22-
});
22+
}, [countDown]);
2323

2424
return (
2525
<div
2626
className="h-screen w-screen content-center items-center justify-center m-0"
2727
style={{ background: "#4d689b" }}
2828
>
29-
<AppHeader title="iOS Club - 404 Opps" />
29+
<AppHeader title="iOS Club - 404 Oops" />
3030
<div className="h-full w-full flex flex-col justify-center items-center p-20">
3131
<div className="w-full flex flex-col md:flex-row items-center justify-center space-x-4 space-y-3">
3232
<LogoSvg className="h-48 w-48 md:w-32 md:h-32 text-white fill-current" />
33-
<h2 className="text-white text-xl md:text-3xl">網頁努力建置中...</h2>
33+
<h2 className="px-3 text-white text-xl md:text-3xl font-bold">
34+
網頁努力建置中⋯⋯
35+
</h2>
3436
</div>
35-
<p className="py-3 text-white">{countDown} 秒後幫您回首頁</p>
36-
<a
37-
href="/"
38-
className="pt-3 underline underline-offset-2 text-white font-blod"
39-
>
40-
..或點我回首頁
37+
<p className="py-3 text-white">{countDown} 秒後幫您回到首頁</p>
38+
<a href="/" className="pt-3 underline underline-offset-2 text-white">
39+
或者點我直接回首頁
4140
</a>
4241
<div className="mt-10">
43-
<h2 className="text-lg text-white">404 Not Found</h2>
42+
<h2 className="text-lg text-white font-bold">404:Page Not Found</h2>
4443
</div>
4544
</div>
4645
</div>

src/pages/index.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ const AnnouncementLiet = (props) => {
314314
<a
315315
className="text-blue-500 underline underline-offset-2 font-bold"
316316
href={node.url}
317-
target="__blank"
317+
target="_blank"
318318
>
319319
{node.urlText}
320320
</a>
@@ -422,11 +422,6 @@ const socialItems = [
422422
icon: "akar-icons:discord-fill",
423423
href: "https://discord.com/invite/z2VPCNFupv",
424424
},
425-
{
426-
name: "Threads",
427-
icon: "akar-icons--threads-fill",
428-
href: "https://www.threads.net/@fcu.iosclub",
429-
},
430425
];
431426

432427
export const qldata = graphql`

src/pages/qrcode_generator.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
import * as React from "react";
2-
import { useState } from "react";
2+
import { useEffect, useState } from "react";
33
import Footer from "../components/footer";
44
import Navbar from "../components/navbar";
55
import AppHeader from "../components/header";
66
import SliderButton from "../components/buttons/slider_button";
77
import { Icon } from "@iconify/react";
88

9+
const logo = "https://i.meee.com.tw/0SiZRVA.jpg";
10+
911
const QRCodeGeneratorPage = () => {
1012
const [urlInput, setUrlInput] = useState("");
1113
const [qrCodeUrl, setQrCodeUrl] = useState(null);
1214
const [loading, setLoading] = useState(false);
1315
const [error, setError] = useState(null);
1416

15-
const logo = "https://i.meee.com.tw/0SiZRVA.jpg";
17+
useEffect(() => {
18+
return () => {
19+
if (qrCodeUrl && qrCodeUrl.startsWith("blob:")) {
20+
URL.revokeObjectURL(qrCodeUrl);
21+
}
22+
};
23+
}, [qrCodeUrl]);
1624

1725
const generateQRCode = async () => {
1826
if (!urlInput.trim()) {
@@ -95,6 +103,10 @@ const QRCodeGeneratorPage = () => {
95103
const blob = await imgResponse.blob();
96104
const url = URL.createObjectURL(blob);
97105
setQrCodeUrl(url);
106+
setTimeout(
107+
() => previewRef.current?.scrollIntoView({ behavior: "smooth" }),
108+
100,
109+
);
98110
} else {
99111
throw new Error(`圖片下載失敗 (${imgResponse.status})`);
100112
}

src/pages/rfid_converter.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const RfidConverterPage = () => {
2525
// 分割成位元組
2626
const bytes = [];
2727
for (let i = 0; i < hexStr.length; i += 2) {
28-
bytes.push(hexStr.substr(i, 2));
28+
bytes.push(hexStr.slice(i, i + 2));
2929
}
3030

3131
// 創建副本來避免修改原始數組
@@ -62,7 +62,7 @@ const RfidConverterPage = () => {
6262
// 分割成位元組
6363
const bytes = [];
6464
for (let i = 0; i < hex.length; i += 2) {
65-
bytes.push(hex.substr(i, 2));
65+
bytes.push(hex.slice(i, i + 2));
6666
}
6767

6868
// 創建副本來避免修改原始數組
@@ -133,11 +133,11 @@ const RfidConverterPage = () => {
133133
value={hexInput}
134134
onChange={(e) => setHexInput(e.target.value)}
135135
placeholder="請輸入16進制卡號..."
136-
className="flex-1 px-4 py-3 border-2 border-gray-300 rounded-lg font-mono text-lg focus:border-btnbg focus:outline-none transition-colors"
136+
className="flex-1 px-4 py-3 border-2 border-gray-300 rounded-full font-mono text-lg focus:border-btnbg focus:outline-none transition-colors"
137137
/>
138138
<button
139139
onClick={clearHex}
140-
className="px-4 py-3 border border-gray-400 text-gray-700 rounded-lg hover:bg-btnbg hover:text-white transition-colors flex items-center justify-center"
140+
className="px-4 py-3 text-gray-700 rounded-full hover:bg-btnbg hover:text-white transition-colors flex items-center justify-center"
141141
title="清除輸入"
142142
>
143143
<Icon icon="mdi:close" className="text-xl" />
@@ -199,11 +199,11 @@ const RfidConverterPage = () => {
199199
value={decInput}
200200
onChange={(e) => setDecInput(e.target.value)}
201201
placeholder="請輸入10進制卡號..."
202-
className="flex-1 px-4 py-3 border-2 border-gray-300 rounded-lg font-mono text-lg focus:border-btnbg focus:outline-none transition-colors"
202+
className="flex-1 px-4 py-3 border-2 border-gray-300 rounded-full font-mono text-lg focus:border-btnbg focus:outline-none transition-colors"
203203
/>
204204
<button
205205
onClick={clearDec}
206-
className="px-4 py-3 border border-gray-400 text-gray-700 rounded-lg hover:bg-btnbg hover:text-white transition-colors flex items-center justify-center"
206+
className="px-4 py-3 text-gray-700 rounded-full hover:bg-btnbg hover:text-white transition-colors flex items-center justify-center"
207207
title="清除輸入"
208208
>
209209
<Icon icon="mdi:close" className="text-xl" />

0 commit comments

Comments
 (0)