Compare commits

...

5 Commits

Author SHA1 Message Date
鄭沛軒 452cdef641 fix: 保留通知按鈕在手機版,完善響應式設計
📱 手機版最終設計:
頂部:[🍔] DramaLing [🔔]
- 漢堡選單:導航功能
- Logo:品牌識別
- 通知按鈕:重要功能保留

🎯 響應式顯示策略:
- 通知按鈕:桌面和手機都顯示
- 用戶資訊:只在桌面版顯示(頭像、用戶名、登出)
- 下拉選單:手機版的用戶資訊區域

 現在的完美設計:
🖥️ 桌面:[🍔] DramaLing | 導航項目     [🔔] [👤 用戶名] [登出]
📱 手機:[🍔] DramaLing [🔔]

🚀 符合用戶期望的直覺設計!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 03:59:16 +08:00
鄭沛軒 41266742b4 fix: 完善手機版導航設計,隱藏頂部用戶資訊
📱 手機版 UI 最佳化:
- 頂部只保留漢堡選單和 Logo(極簡設計)
- 用戶資訊、通知按鈕移到桌面版專用(hidden md:flex)
- 手機版的用戶資訊完全在下拉選單中

🎯 現在的手機版佈局:
頂部:[🍔] DramaLing
下拉:導航 + 用戶資訊 + 登出

 符合移動端設計最佳實踐:
- 頂部導航條簡潔明瞭
- 避免小螢幕上的擁擠感
- 用戶資訊放在邏輯位置(選單底部)

🚀 DramaLing 現在有真正專業的響應式設計!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 03:56:57 +08:00
鄭沛軒 c4010c362c fix: 修正漢堡選單位置,符合標準 UI 模式
🔧 UI 位置修正:
- 將漢堡選單按鈕移到 Logo 左邊
- 符合標準的移動端 UI 設計模式
- 提升用戶的直覺操作體驗

📱 現在的手機版佈局:
[🍔] DramaLing                    [通知]

 標準 UI 模式:
- 漢堡選單在左上角是業界標準
- 用戶更容易找到和操作
- 與主流 App 的使用習慣一致

🎯 完美的響應式導航系統現已完成!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 03:53:26 +08:00
鄭沛軒 4797366a25 feat: 添加手機版響應式導航,實現漢堡選單
📱 手機版導航系統:
- 添加漢堡選單按鈕(三條線 ↔ X 圖示切換)
- 實作手機版下拉選單,包含所有導航項目
- 手機版用戶資訊區域(頭像 + 登出)
- 點擊導航項目後自動關閉選單

🎯 響應式設計改進:
- 桌面版:水平導航條 + 右側用戶資訊
- 手機版:漢堡選單 + 垂直下拉選單
- 當前頁面在手機版以主色調背景高亮

🔧 技術實作:
- 使用 Tailwind 的 md: 斷點控制顯示/隱藏
- useState 管理手機選單開關狀態
- 動態 SVG 圖示切換(選單/關閉)

 解決問題:
- 手機版現在有完整的導航功能
- 所有頁面在手機上都可以正常使用
- 專業級的響應式用戶體驗

🚀 DramaLing 現在完全支援桌面和手機裝置!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 03:51:17 +08:00
鄭沛軒 116daafc37 fix: 解決頁面切換時的晃動問題,強制顯示滾動軸
🔧 滾動軸晃動問題修復:
- 在 globals.css 中添加 `html { overflow-y: scroll; }`
- 強制垂直滾動軸始終顯示
- 防止內容長度不同的頁面切換時產生晃動
- 添加 `body { overflow-x: hidden; }` 防止橫向滾動

🎯 解決的問題:
- flashcards 頁面(內容少)vs dashboard/learn 頁面(內容多)
- 滾動軸出現/消失導致的頁面寬度變化
- 導航切換時的視覺跳動

 現在的體驗:
- 所有頁面都有一致的滾動軸
- 頁面切換完全穩定,無晃動
- 專業級的用戶體驗

🚀 DramaLing 的 UI/UX 品質再次提升!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 03:45:51 +08:00
31 changed files with 214 additions and 133 deletions

View File

@ -1,7 +1,7 @@
{
"/flashcards/page": "app/flashcards/page.js",
"/dashboard/page": "app/dashboard/page.js",
"/login/page": "app/login/page.js",
"/flashcards/page": "app/flashcards/page.js",
"/generate/page": "app/generate/page.js",
"/dashboard/page": "app/dashboard/page.js",
"/learn/page": "app/learn/page.js"
}

View File

@ -30,7 +30,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"9fdc4ff274b5\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjlmZGM0ZmYyNzRiNVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"258cb28ba210\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjI1OGNiMjhiYTIxMFwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
/***/ }),

View File

@ -30,7 +30,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"9fdc4ff274b5\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjlmZGM0ZmYyNzRiNVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"258cb28ba210\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjI1OGNiMjhiYTIxMFwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
/***/ }),

View File

@ -30,7 +30,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"9fdc4ff274b5\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjlmZGM0ZmYyNzRiNVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"258cb28ba210\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjI1OGNiMjhiYTIxMFwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
/***/ }),

View File

@ -19,7 +19,7 @@ exports.modules = {
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"9fdc4ff274b5\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjlmZGM0ZmYyNzRiNVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"258cb28ba210\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjI1OGNiMjhiYTIxMFwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
/***/ }),

View File

@ -19,7 +19,7 @@ exports.modules = {
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"9fdc4ff274b5\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjlmZGM0ZmYyNzRiNVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"258cb28ba210\");\nif (false) {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKHJzYykvLi9hcHAvZ2xvYmFscy5jc3MiLCJtYXBwaW5ncyI6Ijs7OztBQUFBLGlFQUFlLGNBQWM7QUFDN0IsSUFBSSxLQUFVLEVBQUUsRUFBdUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjI1OGNiMjhiYTIxMFwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(rsc)/./app/globals.css\n");
/***/ }),

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@
/***/ ((module, __webpack_exports__, __webpack_require__) => {
"use strict";
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"c2da5bf39299\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcImMyZGE1YmYzOTI5OVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"6197489b67d2\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjYxOTc0ODliNjdkMlwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ }),

File diff suppressed because one or more lines are too long

View File

@ -589,11 +589,18 @@ video {
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
html {
/* 強制顯示垂直滾動軸,防止頁面切換時晃動 */
overflow-y: scroll;
}
body {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
/* 確保 body 不會產生額外的滾動軸 */
overflow-x: hidden;
}
.pointer-events-none {
pointer-events: none;
@ -614,11 +621,8 @@ video {
top: 0px;
bottom: 0px;
}
.-right-2 {
right: -0.5rem;
}
.-top-1 {
top: -0.25rem;
.left-0 {
left: 0px;
}
.right-2 {
right: 0.5rem;
@ -626,9 +630,6 @@ video {
.top-2 {
top: 0.5rem;
}
.left-0 {
left: 0px;
}
.z-10 {
z-index: 10;
}
@ -757,18 +758,9 @@ video {
.h-full {
height: 100%;
}
.max-h-60 {
max-height: 15rem;
}
.max-h-\[80vh\] {
max-height: 80vh;
}
.max-h-\[90vh\] {
max-height: 90vh;
}
.min-h-\[280px\] {
min-height: 280px;
}
.min-h-screen {
min-height: 100vh;
}
@ -977,6 +969,10 @@ video {
.rounded-xl {
border-radius: 0.75rem;
}
.rounded-b-lg {
border-bottom-right-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
}
.rounded-t {
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
@ -985,10 +981,6 @@ video {
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
}
.rounded-b-lg {
border-bottom-right-radius: 0.5rem;
border-bottom-left-radius: 0.5rem;
}
.border {
border-width: 1px;
}
@ -1041,10 +1033,6 @@ video {
.border-transparent {
border-color: transparent;
}
.border-yellow-200 {
--tw-border-opacity: 1;
border-color: rgb(254 240 138 / var(--tw-border-opacity, 1));
}
.bg-black {
--tw-bg-opacity: 1;
background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
@ -1057,10 +1045,6 @@ video {
--tw-bg-opacity: 1;
background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
}
.bg-blue-500 {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));
}
.bg-gray-100 {
--tw-bg-opacity: 1;
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
@ -1085,13 +1069,9 @@ video {
--tw-bg-opacity: 1;
background-color: rgb(34 197 94 / var(--tw-bg-opacity, 1));
}
.bg-indigo-500 {
.bg-green-600 {
--tw-bg-opacity: 1;
background-color: rgb(99 102 241 / var(--tw-bg-opacity, 1));
}
.bg-orange-500 {
--tw-bg-opacity: 1;
background-color: rgb(249 115 22 / var(--tw-bg-opacity, 1));
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
}
.bg-primary {
--tw-bg-opacity: 1;
@ -1101,10 +1081,6 @@ video {
--tw-bg-opacity: 1;
background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
}
.bg-purple-100 {
--tw-bg-opacity: 1;
background-color: rgb(243 232 255 / var(--tw-bg-opacity, 1));
}
.bg-purple-50 {
--tw-bg-opacity: 1;
background-color: rgb(250 245 255 / var(--tw-bg-opacity, 1));
@ -1133,14 +1109,6 @@ video {
--tw-bg-opacity: 1;
background-color: rgb(254 249 195 / var(--tw-bg-opacity, 1));
}
.bg-yellow-50 {
--tw-bg-opacity: 1;
background-color: rgb(254 252 232 / var(--tw-bg-opacity, 1));
}
.bg-green-600 {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
}
.bg-opacity-50 {
--tw-bg-opacity: 0.5;
}
@ -1238,46 +1206,39 @@ video {
padding-top: 2rem;
padding-bottom: 2rem;
}
.py-6 {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
}
.pb-32 {
padding-bottom: 8rem;
}
.pl-3 {
padding-left: 0.75rem;
}
.pt-20 {
padding-top: 5rem;
}
.pt-3 {
padding-top: 0.75rem;
}
.pt-6 {
padding-top: 1.5rem;
}
.pb-4 {
padding-bottom: 1rem;
}
.pl-10 {
padding-left: 2.5rem;
}
.pl-3 {
padding-left: 0.75rem;
}
.pr-4 {
padding-right: 1rem;
}
.pt-20 {
padding-top: 5rem;
}
.pt-3 {
padding-top: 0.75rem;
}
.pt-4 {
padding-top: 1rem;
}
.pt-6 {
padding-top: 1.5rem;
}
.text-left {
text-align: left;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-2xl {
font-size: 1.5rem;
line-height: 2rem;
@ -1401,10 +1362,6 @@ video {
--tw-text-opacity: 1;
color: rgb(168 85 247 / var(--tw-text-opacity, 1));
}
.text-purple-600 {
--tw-text-opacity: 1;
color: rgb(147 51 234 / var(--tw-text-opacity, 1));
}
.text-purple-800 {
--tw-text-opacity: 1;
color: rgb(107 33 168 / var(--tw-text-opacity, 1));
@ -1425,10 +1382,6 @@ video {
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
.text-yellow-600 {
--tw-text-opacity: 1;
color: rgb(202 138 4 / var(--tw-text-opacity, 1));
}
.text-yellow-700 {
--tw-text-opacity: 1;
color: rgb(161 98 7 / var(--tw-text-opacity, 1));
@ -1515,11 +1468,6 @@ video {
border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
}
.hover\:border-gray-400:hover {
--tw-border-opacity: 1;
border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));
}
.hover\:bg-gray-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));
@ -1535,9 +1483,9 @@ video {
background-color: rgb(187 247 208 / var(--tw-bg-opacity, 1));
}
.hover\:bg-green-600:hover {
.hover\:bg-green-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(22 163 74 / var(--tw-bg-opacity, 1));
background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1));
}
.hover\:bg-primary-hover:hover {
@ -1550,6 +1498,10 @@ video {
background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
}
.hover\:bg-primary\/90:hover {
background-color: rgb(59 130 246 / 0.9);
}
.hover\:bg-red-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(254 202 202 / var(--tw-bg-opacity, 1));
@ -1565,19 +1517,15 @@ video {
background-color: rgb(254 240 138 / var(--tw-bg-opacity, 1));
}
.hover\:bg-primary\/90:hover {
background-color: rgb(59 130 246 / 0.9);
}
.hover\:bg-green-700:hover {
--tw-bg-opacity: 1;
background-color: rgb(21 128 61 / var(--tw-bg-opacity, 1));
}
.hover\:bg-opacity-100:hover {
--tw-bg-opacity: 1;
}
.hover\:text-blue-800:hover {
--tw-text-opacity: 1;
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
}
.hover\:text-gray-600:hover {
--tw-text-opacity: 1;
color: rgb(75 85 99 / var(--tw-text-opacity, 1));
@ -1593,11 +1541,6 @@ video {
color: rgb(17 24 39 / var(--tw-text-opacity, 1));
}
.hover\:text-green-700:hover {
--tw-text-opacity: 1;
color: rgb(21 128 61 / var(--tw-text-opacity, 1));
}
.hover\:text-primary:hover {
--tw-text-opacity: 1;
color: rgb(59 130 246 / var(--tw-text-opacity, 1));
@ -1618,11 +1561,6 @@ video {
color: rgb(185 28 28 / var(--tw-text-opacity, 1));
}
.hover\:text-blue-800:hover {
--tw-text-opacity: 1;
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
}
.hover\:text-red-800:hover {
--tw-text-opacity: 1;
color: rgb(153 27 27 / var(--tw-text-opacity, 1));
@ -1702,10 +1640,6 @@ video {
.md\:grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.md\:flex-row {
flex-direction: row;
}
}
@media (min-width: 1024px) {

View File

@ -0,0 +1 @@
{"c":["app/layout","webpack"],"r":[],"m":[]}

View File

@ -0,0 +1,22 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
self["webpackHotUpdate_N_E"]("app/layout",{
/***/ "(app-pages-browser)/./app/globals.css":
/*!*************************!*\
!*** ./app/globals.css ***!
\*************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"86d84626a51a\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjg2ZDg0NjI2YTUxYVwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ })
});

View File

@ -0,0 +1,22 @@
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
self["webpackHotUpdate_N_E"]("app/layout",{
/***/ "(app-pages-browser)/./app/globals.css":
/*!*************************!*\
!*** ./app/globals.css ***!
\*************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {
eval(__webpack_require__.ts("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (\"6197489b67d2\");\nif (true) { module.hot.accept() }\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKGFwcC1wYWdlcy1icm93c2VyKS8uL2FwcC9nbG9iYWxzLmNzcyIsIm1hcHBpbmdzIjoiOzs7O0FBQUEsaUVBQWUsY0FBYztBQUM3QixJQUFJLElBQVUsSUFBSSxpQkFBaUIiLCJzb3VyY2VzIjpbIi9Vc2Vycy9qZXR0Y2hlbmcxMDE4L2NvZGUvZHJhbWFsaW5nLXZvY2FiLWxlYXJuaW5nL2Zyb250ZW5kL2FwcC9nbG9iYWxzLmNzcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCBcIjYxOTc0ODliNjdkMlwiXG5pZiAobW9kdWxlLmhvdCkgeyBtb2R1bGUuaG90LmFjY2VwdCgpIH1cbiJdLCJuYW1lcyI6W10sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///(app-pages-browser)/./app/globals.css\n"));
/***/ })
});

View File

@ -0,0 +1 @@
{"c":["app/layout","webpack"],"r":[],"m":[]}

View File

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("d081a9c1aad14572")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCJkMDgxYTljMWFhZDE0NTcyXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View File

@ -0,0 +1,12 @@
"use strict";
self["webpackHotUpdate_N_E"]("webpack",{},
/******/ function(__webpack_require__) { // webpackRuntimeModules
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("76901f30cb3cebbd")
/******/ })();
/******/
/******/ }
)
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJpZ25vcmVMaXN0IjpbMF0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZXMiOlsid2VicGFjay1pbnRlcm5hbDovL25leHRqcy93ZWJwYWNrLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgc291cmNlIHdhcyBnZW5lcmF0ZWQgYnkgTmV4dC5qcyBiYXNlZCBvZmYgb2YgdGhlIGdlbmVyYXRlZCBXZWJwYWNrIHJ1bnRpbWUuXG4vLyBUaGUgbWFwcGluZ3MgYXJlIGluY29ycmVjdC5cbi8vIFRvIGdldCB0aGUgY29ycmVjdCBsaW5lL2NvbHVtbiBtYXBwaW5ncywgdHVybiBvZmYgc291cmNlbWFwcyBpbiB5b3VyIGRlYnVnZ2VyLlxuXG5zZWxmW1wid2VicGFja0hvdFVwZGF0ZV9OX0VcIl0oXCJ3ZWJwYWNrXCIse30sXG4vKioqKioqLyBmdW5jdGlvbihfX3dlYnBhY2tfcmVxdWlyZV9fKSB7IC8vIHdlYnBhY2tSdW50aW1lTW9kdWxlc1xuLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2dldEZ1bGxIYXNoICovXG4vKioqKioqLyAoKCkgPT4ge1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmggPSAoKSA9PiAoXCI3NjkwMWYzMGNiM2NlYmJkXCIpXG4vKioqKioqLyB9KSgpO1xuLyoqKioqKi8gXG4vKioqKioqLyB9XG4pIl19
;

View File

@ -42,8 +42,15 @@
}
@layer base {
html {
/* 強制顯示垂直滾動軸,防止頁面切換時晃動 */
overflow-y: scroll;
}
body {
@apply bg-white text-gray-900;
/* 確保 body 不會產生額外的滾動軸 */
overflow-x: hidden;
}
}

View File

@ -1,5 +1,6 @@
'use client'
import { useState } from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { useAuth } from '@/contexts/AuthContext'
@ -12,6 +13,7 @@ interface NavigationProps {
export function Navigation({ showExitLearning = false, onExitLearning }: NavigationProps = {}) {
const { user, logout } = useAuth()
const pathname = usePathname()
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
const navItems = [
{ href: '/dashboard', label: '儀表板' },
@ -24,9 +26,24 @@ export function Navigation({ showExitLearning = false, onExitLearning }: Navigat
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
<div className="flex items-center space-x-8">
{/* 手機版漢堡選單按鈕 */}
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="md:hidden p-2 text-gray-600 hover:text-gray-900"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{isMobileMenuOpen ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
<Link href="/dashboard" className="text-2xl font-bold text-primary">
DramaLing
</Link>
<div className="hidden md:flex space-x-6">
{navItems.map((item) => (
<Link
@ -45,28 +62,81 @@ export function Navigation({ showExitLearning = false, onExitLearning }: Navigat
</div>
<div className="flex items-center space-x-4">
{/* 通知按鈕 */}
<button className="p-2 text-gray-600 hover:text-gray-900">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
{/* 用戶資訊 */}
<div className="flex items-center space-x-2">
<div className="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-white font-semibold">
{user?.username?.[0]?.toUpperCase() || 'U'}
</div>
<span className="text-sm font-medium">{user?.displayName || user?.username}</span>
{/* 學習模式的結束學習按鈕 */}
{showExitLearning ? (
<button
onClick={logout}
className="ml-4 text-sm text-gray-600 hover:text-gray-900"
onClick={onExitLearning}
className="text-gray-600 hover:text-gray-900"
>
×
</button>
</div>
) : (
<>
{/* 通知按鈕 - 桌面和手機都顯示 */}
<button className="p-2 text-gray-600 hover:text-gray-900">
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
</button>
{/* 用戶資訊 - 只在桌面版顯示 */}
<div className="hidden md:flex items-center space-x-2">
<div className="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-white font-semibold">
{user?.username?.[0]?.toUpperCase() || 'U'}
</div>
<span className="text-sm font-medium">{user?.displayName || user?.username}</span>
<button
onClick={logout}
className="ml-4 text-sm text-gray-600 hover:text-gray-900"
>
</button>
</div>
</>
)}
</div>
</div>
{/* 手機版下拉選單 */}
{isMobileMenuOpen && (
<div className="md:hidden border-t border-gray-200">
<div className="px-4 py-4 space-y-2">
{navItems.map((item) => (
<Link
key={item.href}
href={item.href}
onClick={() => setIsMobileMenuOpen(false)}
className={`block py-2 px-3 rounded-lg font-medium transition-colors ${
pathname === item.href
? 'bg-primary text-white'
: 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'
}`}
>
{item.label}
</Link>
))}
{/* 手機版用戶區域 */}
<div className="pt-4 border-t border-gray-200 mt-4">
<div className="flex items-center space-x-3 px-3 py-2">
<div className="w-8 h-8 bg-primary rounded-full flex items-center justify-center text-white font-semibold">
{user?.username?.[0]?.toUpperCase() || 'U'}
</div>
<span className="text-sm font-medium">{user?.displayName || user?.username}</span>
</div>
<button
onClick={() => {
logout()
setIsMobileMenuOpen(false)
}}
className="w-full text-left py-2 px-3 text-gray-600 hover:text-gray-900 hover:bg-gray-100 rounded-lg"
>
</button>
</div>
</div>
</div>
)}
</div>
</nav>
)