@coze-arch/cli 0.0.1-alpha.77c1b0 → 0.0.1-alpha.7d92f8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/lib/__templates__/expo/.cozeproj/scripts/deploy_build.sh +25 -18
  2. package/lib/__templates__/expo/.cozeproj/scripts/deploy_run.sh +28 -46
  3. package/lib/__templates__/expo/_npmrc +1 -1
  4. package/lib/__templates__/expo/client/contexts/AuthContext.tsx +14 -107
  5. package/lib/__templates__/expo/client/screens/home/index.tsx +1 -4
  6. package/lib/__templates__/expo/client/screens/home/styles.ts +1 -273
  7. package/lib/__templates__/expo/client/scripts/install-missing-deps.js +36 -12
  8. package/lib/__templates__/expo/client/utils/index.ts +1 -2
  9. package/lib/__templates__/expo/metro.config.js +15 -15
  10. package/lib/__templates__/expo/package.json +13 -3
  11. package/lib/__templates__/expo/pnpm-lock.yaml +134 -7
  12. package/lib/__templates__/expo/src/index.ts +2 -2
  13. package/lib/__templates__/expo/template.config.js +1 -1
  14. package/lib/__templates__/nextjs/.coze +3 -3
  15. package/lib/__templates__/nextjs/README.md +341 -19
  16. package/lib/__templates__/nextjs/_npmrc +1 -1
  17. package/lib/__templates__/nextjs/components.json +21 -0
  18. package/lib/__templates__/nextjs/package.json +54 -1
  19. package/lib/__templates__/nextjs/pnpm-lock.yaml +7947 -1523
  20. package/lib/__templates__/nextjs/scripts/dev.sh +9 -27
  21. package/lib/__templates__/nextjs/src/app/globals.css +99 -8
  22. package/lib/__templates__/nextjs/src/app/layout.tsx +18 -18
  23. package/lib/__templates__/nextjs/src/components/ui/accordion.tsx +66 -0
  24. package/lib/__templates__/nextjs/src/components/ui/alert-dialog.tsx +157 -0
  25. package/lib/__templates__/nextjs/src/components/ui/alert.tsx +66 -0
  26. package/lib/__templates__/nextjs/src/components/ui/aspect-ratio.tsx +11 -0
  27. package/lib/__templates__/nextjs/src/components/ui/avatar.tsx +53 -0
  28. package/lib/__templates__/nextjs/src/components/ui/badge.tsx +46 -0
  29. package/lib/__templates__/nextjs/src/components/ui/breadcrumb.tsx +109 -0
  30. package/lib/__templates__/nextjs/src/components/ui/button-group.tsx +83 -0
  31. package/lib/__templates__/nextjs/src/components/ui/button.tsx +62 -0
  32. package/lib/__templates__/nextjs/src/components/ui/calendar.tsx +220 -0
  33. package/lib/__templates__/nextjs/src/components/ui/card.tsx +92 -0
  34. package/lib/__templates__/nextjs/src/components/ui/carousel.tsx +241 -0
  35. package/lib/__templates__/nextjs/src/components/ui/chart.tsx +357 -0
  36. package/lib/__templates__/nextjs/src/components/ui/checkbox.tsx +32 -0
  37. package/lib/__templates__/nextjs/src/components/ui/collapsible.tsx +33 -0
  38. package/lib/__templates__/nextjs/src/components/ui/command.tsx +184 -0
  39. package/lib/__templates__/nextjs/src/components/ui/context-menu.tsx +252 -0
  40. package/lib/__templates__/nextjs/src/components/ui/dialog.tsx +143 -0
  41. package/lib/__templates__/nextjs/src/components/ui/drawer.tsx +135 -0
  42. package/lib/__templates__/nextjs/src/components/ui/dropdown-menu.tsx +257 -0
  43. package/lib/__templates__/nextjs/src/components/ui/empty.tsx +104 -0
  44. package/lib/__templates__/nextjs/src/components/ui/field.tsx +248 -0
  45. package/lib/__templates__/nextjs/src/components/ui/form.tsx +167 -0
  46. package/lib/__templates__/nextjs/src/components/ui/hover-card.tsx +44 -0
  47. package/lib/__templates__/nextjs/src/components/ui/input-group.tsx +170 -0
  48. package/lib/__templates__/nextjs/src/components/ui/input-otp.tsx +77 -0
  49. package/lib/__templates__/nextjs/src/components/ui/input.tsx +21 -0
  50. package/lib/__templates__/nextjs/src/components/ui/item.tsx +193 -0
  51. package/lib/__templates__/nextjs/src/components/ui/kbd.tsx +28 -0
  52. package/lib/__templates__/nextjs/src/components/ui/label.tsx +24 -0
  53. package/lib/__templates__/nextjs/src/components/ui/menubar.tsx +276 -0
  54. package/lib/__templates__/nextjs/src/components/ui/navigation-menu.tsx +168 -0
  55. package/lib/__templates__/nextjs/src/components/ui/pagination.tsx +127 -0
  56. package/lib/__templates__/nextjs/src/components/ui/popover.tsx +48 -0
  57. package/lib/__templates__/nextjs/src/components/ui/progress.tsx +31 -0
  58. package/lib/__templates__/nextjs/src/components/ui/radio-group.tsx +45 -0
  59. package/lib/__templates__/nextjs/src/components/ui/resizable.tsx +56 -0
  60. package/lib/__templates__/nextjs/src/components/ui/scroll-area.tsx +58 -0
  61. package/lib/__templates__/nextjs/src/components/ui/select.tsx +190 -0
  62. package/lib/__templates__/nextjs/src/components/ui/separator.tsx +28 -0
  63. package/lib/__templates__/nextjs/src/components/ui/sheet.tsx +139 -0
  64. package/lib/__templates__/nextjs/src/components/ui/sidebar.tsx +726 -0
  65. package/lib/__templates__/nextjs/src/components/ui/skeleton.tsx +13 -0
  66. package/lib/__templates__/nextjs/src/components/ui/slider.tsx +63 -0
  67. package/lib/__templates__/nextjs/src/components/ui/sonner.tsx +40 -0
  68. package/lib/__templates__/nextjs/src/components/ui/spinner.tsx +16 -0
  69. package/lib/__templates__/nextjs/src/components/ui/switch.tsx +31 -0
  70. package/lib/__templates__/nextjs/src/components/ui/table.tsx +116 -0
  71. package/lib/__templates__/nextjs/src/components/ui/tabs.tsx +66 -0
  72. package/lib/__templates__/nextjs/src/components/ui/textarea.tsx +18 -0
  73. package/lib/__templates__/nextjs/src/components/ui/toggle-group.tsx +83 -0
  74. package/lib/__templates__/nextjs/src/components/ui/toggle.tsx +47 -0
  75. package/lib/__templates__/nextjs/src/components/ui/tooltip.tsx +61 -0
  76. package/lib/__templates__/nextjs/src/hooks/use-mobile.ts +19 -0
  77. package/lib/__templates__/nextjs/src/lib/utils.ts +6 -0
  78. package/lib/__templates__/nextjs/template.config.js +2 -2
  79. package/lib/__templates__/templates.json +6 -37
  80. package/lib/__templates__/vite/.coze +3 -3
  81. package/lib/__templates__/vite/README.md +204 -26
  82. package/lib/__templates__/vite/_npmrc +1 -1
  83. package/lib/__templates__/vite/package.json +1 -1
  84. package/lib/__templates__/vite/pnpm-lock.yaml +120 -120
  85. package/lib/__templates__/vite/scripts/dev.sh +7 -26
  86. package/lib/__templates__/vite/template.config.js +11 -2
  87. package/lib/__templates__/vite/vite.config.ts +6 -3
  88. package/lib/cli.js +426 -249
  89. package/package.json +5 -3
  90. package/lib/__templates__/react-rsbuild/.coze +0 -11
  91. package/lib/__templates__/react-rsbuild/.vscode/settings.json +0 -121
  92. package/lib/__templates__/react-rsbuild/README.md +0 -61
  93. package/lib/__templates__/react-rsbuild/_gitignore +0 -97
  94. package/lib/__templates__/react-rsbuild/_npmrc +0 -22
  95. package/lib/__templates__/react-rsbuild/package.json +0 -31
  96. package/lib/__templates__/react-rsbuild/pnpm-lock.yaml +0 -997
  97. package/lib/__templates__/react-rsbuild/rsbuild.config.ts +0 -13
  98. package/lib/__templates__/react-rsbuild/scripts/build.sh +0 -14
  99. package/lib/__templates__/react-rsbuild/scripts/dev.sh +0 -51
  100. package/lib/__templates__/react-rsbuild/scripts/start.sh +0 -15
  101. package/lib/__templates__/react-rsbuild/src/App.tsx +0 -60
  102. package/lib/__templates__/react-rsbuild/src/index.css +0 -21
  103. package/lib/__templates__/react-rsbuild/src/index.html +0 -12
  104. package/lib/__templates__/react-rsbuild/src/index.tsx +0 -16
  105. package/lib/__templates__/react-rsbuild/tailwind.config.js +0 -9
  106. package/lib/__templates__/react-rsbuild/template.config.js +0 -54
  107. package/lib/__templates__/react-rsbuild/tsconfig.json +0 -17
  108. package/lib/__templates__/rsbuild/.coze +0 -11
  109. package/lib/__templates__/rsbuild/.vscode/settings.json +0 -7
  110. package/lib/__templates__/rsbuild/README.md +0 -61
  111. package/lib/__templates__/rsbuild/_gitignore +0 -97
  112. package/lib/__templates__/rsbuild/_npmrc +0 -22
  113. package/lib/__templates__/rsbuild/package.json +0 -24
  114. package/lib/__templates__/rsbuild/pnpm-lock.yaml +0 -888
  115. package/lib/__templates__/rsbuild/rsbuild.config.ts +0 -12
  116. package/lib/__templates__/rsbuild/scripts/build.sh +0 -14
  117. package/lib/__templates__/rsbuild/scripts/dev.sh +0 -51
  118. package/lib/__templates__/rsbuild/scripts/start.sh +0 -15
  119. package/lib/__templates__/rsbuild/src/index.css +0 -21
  120. package/lib/__templates__/rsbuild/src/index.html +0 -12
  121. package/lib/__templates__/rsbuild/src/index.ts +0 -5
  122. package/lib/__templates__/rsbuild/src/main.ts +0 -65
  123. package/lib/__templates__/rsbuild/tailwind.config.js +0 -9
  124. package/lib/__templates__/rsbuild/template.config.js +0 -56
  125. package/lib/__templates__/rsbuild/tsconfig.json +0 -16
@@ -2,6 +2,7 @@
2
2
  if [ -z "${BASH_VERSION:-}" ]; then exec /usr/bin/env bash "$0" "$@"; fi
3
3
  set -euo pipefail
4
4
  ROOT_DIR="$(pwd)"
5
+ PREVIEW_DIR="${COZE_PREVIEW_DIR:-$ROOT_DIR}"
5
6
  LOG_DIR="${COZE_LOG_DIR:-$ROOT_DIR/logs}"
6
7
  LOG_FILE="$LOG_DIR/app.log"
7
8
  mkdir -p "$LOG_DIR"
@@ -29,19 +30,25 @@ check_command() {
29
30
  write_log() {
30
31
  local level="${1:-INFO}"
31
32
  local msg="${2:-}"
32
- python - "$LOG_FILE" "$level" "$msg" <<'PY'
33
- import os,sys,json,time
34
- from datetime import datetime, timezone, timedelta
35
- path, level, msg = sys.argv[1], sys.argv[2].upper(), sys.argv[3]
36
- ts = int(time.time()*1000)
37
- tz = timezone(timedelta(hours=8))
38
- dt_str = datetime.now(tz).strftime('%Y-%m-%d %H:%M:%S')
39
- msg = msg.replace('\\n', '\n')
40
- msg = f"{dt_str} [{level}] {msg}"
41
- with open(path,'a',encoding='utf-8',buffering=1) as f:
42
- f.write(json.dumps({"level":level,"message":msg,"timestamp":ts},ensure_ascii=False)+'\n')
43
- f.flush(); os.fsync(f.fileno())
44
- PY
33
+ node -e '
34
+ const fs=require("fs");
35
+ const path=process.argv[1];
36
+ const level=(process.argv[2]||"").toUpperCase();
37
+ let msg=String(process.argv[3]||"");
38
+ const ts=Date.now();
39
+ const dt=new Date();
40
+ const parts=new Intl.DateTimeFormat("en-GB",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:false}).formatToParts(dt);
41
+ const o={};
42
+ for(const p of parts){o[p.type]=p.value}
43
+ const dt_str=`${o.year}-${o.month}-${o.day} ${o.hour}:${o.minute}:${o.second}`;
44
+ msg=msg.replace(/\\n/g,"\n");
45
+ msg=`${dt_str} [${level}] ${msg}`;
46
+ const record=JSON.stringify({level, message: msg, timestamp: ts},null,0);
47
+ const fd=fs.openSync(path,"a");
48
+ fs.writeSync(fd, record+"\n", null, "utf8");
49
+ fs.fsyncSync(fd);
50
+ fs.closeSync(fd);
51
+ ' "$LOG_FILE" "$level" "$msg"
45
52
 
46
53
  case "$level" in
47
54
  INFO) info "$msg" ;;
@@ -55,16 +62,16 @@ PY
55
62
  write_log "INFO" "==================== 开始构建 ===================="
56
63
 
57
64
  write_log "INFO" "检查根目录 pre_install.py"
58
- if [ -f "$ROOT_DIR/pre_install.py" ]; then
59
- write_log "INFO" "执行:python $ROOT_DIR/pre_install.py"
60
- python "$ROOT_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
65
+ if [ -f "$PREVIEW_DIR/pre_install.py" ]; then
66
+ write_log "INFO" "执行:python $PREVIEW_DIR/pre_install.py"
67
+ python "$PREVIEW_DIR/pre_install.py" || write_log "ERROR" "pre_install.py 执行失败"
61
68
  fi
62
69
 
63
70
  write_log "INFO" "开始执行构建脚本(build_dev.sh)..."
64
71
  write_log "INFO" "正在检查依赖命令是否存在..."
65
72
  # 检查核心命令
66
- check_command "pip"
67
- check_command "python"
73
+ # check_command "pip"
74
+ # check_command "python"
68
75
  check_command "pnpm"
69
76
  check_command "npm"
70
77
 
@@ -4,7 +4,7 @@ LOG_FILE="$LOG_DIR/app.log"
4
4
  mkdir -p "$LOG_DIR"
5
5
 
6
6
  # ==================== 配置项 ====================
7
- # Python 服务配置
7
+ # Server 服务配置
8
8
  SERVER_HOST="0.0.0.0"
9
9
  SERVER_PORT="9091"
10
10
  # Expo 项目配置
@@ -97,19 +97,25 @@ ensure_port() {
97
97
  write_log() {
98
98
  local level="${1:-INFO}"
99
99
  local msg="${2:-}"
100
- python - "$LOG_FILE" "$level" "$msg" <<'PY'
101
- import os,sys,json,time
102
- from datetime import datetime, timezone, timedelta
103
- path, level, msg = sys.argv[1], sys.argv[2].upper(), sys.argv[3]
104
- ts = int(time.time()*1000)
105
- msg = msg.replace('\\n', '\n')
106
- tz = timezone(timedelta(hours=8))
107
- dt_str = datetime.now(tz).strftime('%Y-%m-%d %H:%M:%S')
108
- msg = f"{dt_str} [{level}] {msg}"
109
- with open(path,'a',encoding='utf-8',buffering=1) as f:
110
- f.write(json.dumps({"level":level,"message":msg,"timestamp":ts},ensure_ascii=False)+'\n')
111
- f.flush(); os.fsync(f.fileno())
112
- PY
100
+ node -e '
101
+ const fs=require("fs");
102
+ const path=process.argv[1];
103
+ const level=(process.argv[2]||"").toUpperCase();
104
+ let msg=String(process.argv[3]||"");
105
+ const ts=Date.now();
106
+ msg=msg.replace(/\\n/g,"\n");
107
+ const dt=new Date();
108
+ const parts=new Intl.DateTimeFormat("en-GB",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:false}).formatToParts(dt);
109
+ const o={};
110
+ for(const p of parts){o[p.type]=p.value}
111
+ const dt_str=`${o.year}-${o.month}-${o.day} ${o.hour}:${o.minute}:${o.second}`;
112
+ msg=`${dt_str} [${level}] ${msg}`;
113
+ const record=JSON.stringify({level, message: msg, timestamp: ts},null,0);
114
+ const fd=fs.openSync(path,"a");
115
+ fs.writeSync(fd, record+"\n", null, "utf8");
116
+ fs.fsyncSync(fd);
117
+ fs.closeSync(fd);
118
+ ' "$LOG_FILE" "$level" "$msg"
113
119
  case "$level" in
114
120
  INFO) echo -e "\033[32m[INFO] $msg\033[0m" ;;
115
121
  WARN) echo -e "\033[33m[WARN] $msg\033[0m" ;;
@@ -157,7 +163,7 @@ write_log "INFO" "==================== 开始启动 ===================="
157
163
  write_log "INFO" "开始执行服务启动脚本(start_dev.sh)..."
158
164
  write_log "INFO" "正在检查依赖命令和目录是否存在..."
159
165
  # 检查核心命令
160
- check_command "python"
166
+ # check_command "python"
161
167
  check_command "npm"
162
168
  check_command "pnpm"
163
169
  check_command "lsof"
@@ -169,39 +175,15 @@ mkdir -p logs
169
175
  ensure_port SERVER_PORT "$SERVER_PORT"
170
176
  ensure_port EXPO_PORT "$EXPO_PORT"
171
177
 
172
- # ==================== 步骤 1:启动 Python 服务 ====================
173
-
174
- # ------------环境变量----------------------
175
- export storage_type="s3"
176
- export project_platform="app"
177
-
178
- if [ -n "${COZE_WORKLOAD_IDENTITY_API_KEY:-}" ]; then
179
- export OPENAI_API_KEY="$COZE_WORKLOAD_IDENTITY_API_KEY"
180
- fi
181
- if [ -n "${OPENAI_API_KEY:-}" ]; then
182
- export ARK_API_KEY="$OPENAI_API_KEY"
183
- fi
184
-
185
- if [ -n "${COZE_INTEGRATION_BASE_URL:-}" ]; then
186
- _base="${COZE_INTEGRATION_BASE_URL%/}"
187
- export default_llm_base_url="${_base}/api/v3"
178
+ # ==================== 启动 Server 服务 ====================
179
+ write_log "INFO" "检查 Nginx 端口 (5000)..."
180
+ if is_port_free 5000; then
181
+ write_log "INFO" "端口 5000 未被占用,正在启动 Nginx..."
182
+ service nginx start
188
183
  else
189
- export default_llm_base_url="https://ark.cn-beijing.volces.com/api/v3"
184
+ write_log "INFO" "端口 5000 已被占用,跳过 Nginx 启动"
190
185
  fi
191
186
 
192
- if [ -n "${PGDATABASE_URL:-}" ]; then
193
- _pg="${PGDATABASE_URL}"
194
- case "${_pg}" in
195
- postgresql://*)
196
- _pg="postgresql+asyncpg://${_pg#postgresql://}"
197
- ;;
198
- esac
199
- _pg="${_pg%%\?*}"
200
- export DATABASE_URL="${_pg}"
201
- fi
202
-
203
- # ------------环境变量----------------------
204
-
205
187
  write_log "INFO" "==================== 启动 server 服务 ===================="
206
188
  write_log "INFO" "正在执行:npm run server"
207
189
  PORT="$SERVER_PORT" nohup npm run server > logs/app.log 2>&1 &
@@ -221,7 +203,7 @@ if detect_expo_fetch_failed 8; then
221
203
  : > logs/expo.log
222
204
  EXPO_PID=$(start_expo 1)
223
205
  fi
224
- # 输出以下环境变量,确保 Expo 项目能正确连接到 Python 服务
206
+ # 输出以下环境变量,确保 Expo 项目能正确连接到 Server 服务
225
207
  write_log "INFO" "Expo 环境变量配置:"
226
208
  write_log "INFO" "EXPO_PUBLIC_BACKEND_BASE_URL=${EXPO_PUBLIC_BACKEND_BASE_URL}"
227
209
  write_log "INFO" "EXPO_PACKAGER_PROXY_URL=${EXPO_PACKAGER_PROXY_URL}"
@@ -1,4 +1,4 @@
1
- registry=https://registry.npmjs.org
1
+ registry=https://registry.npmmirror.com
2
2
 
3
3
  strictStorePkgContentCheck=false
4
4
  verifyStoreIntegrity=false
@@ -4,19 +4,15 @@
4
4
  *
5
5
  * 基于固定的 API 接口实现,可复用到其他项目
6
6
  * 其他项目使用时,只需修改 @api 的导入路径指向项目的 api 模块
7
+ *
8
+ * 注意:
9
+ * - 如果需要登录/鉴权场景,请扩展本文件,完善 login/logout、token 管理、用户信息获取与刷新等逻辑
10
+ * - 将示例中的占位实现替换为项目实际的接口调用与状态管理
7
11
  */
8
- import React, {
9
- createContext,
10
- useContext,
11
- useState,
12
- useEffect,
13
- ReactNode,
14
- } from "react";
15
- import AsyncStorage from "@react-native-async-storage/async-storage";
16
- //import { UserOut, UsersService, AuthenticationService } from "@api";
12
+ import React, { createContext, useContext, ReactNode } from "react";
17
13
 
18
14
  interface UserOut {
19
-
15
+
20
16
  }
21
17
 
22
18
  interface AuthContextType {
@@ -31,105 +27,16 @@ interface AuthContextType {
31
27
 
32
28
  const AuthContext = createContext<AuthContextType | undefined>(undefined);
33
29
 
34
- export const AuthProvider: React.FC<{ children: ReactNode }> = ({
35
- children,
36
- }) => {
37
- const [user, setUser] = useState<UserOut | null>(null);
38
- const [token, setToken] = useState<string | null>(null);
39
- const [isLoading, setIsLoading] = useState(true);
40
-
41
- useEffect(() => {
42
- loadAuthData();
43
- }, []);
44
-
45
- const loadAuthData = async () => {
46
- try {
47
- const results = await AsyncStorage.multiGet(["access_token", "user_data"]);
48
- const storedToken = results?.[0]?.[1] ?? null;
49
- const storedUser = results?.[1]?.[1] ?? null;
50
-
51
- if (!storedToken) {
52
- setToken(null);
53
- setUser(null);
54
- await AsyncStorage.multiRemove(["access_token", "user_data"]);
55
- return;
56
- }
57
-
58
- if (storedToken && storedUser) {
59
- setToken(storedToken);
60
- setUser(JSON.parse(storedUser));
61
- } else if (storedToken && !storedUser) {
62
- // 若仅有 token,主动拉取当前用户信息
63
- setToken(storedToken);
64
- try {
65
- // const me = await UsersService.getCurrentUserApiV1UsersMeGet();
66
- //if (me?.success && me.data) {
67
- // setUser(me.data);
68
- // await AsyncStorage.setItem("user_data", JSON.stringify(me.data));
69
- //}
70
- } catch (e) {
71
- // 拉取失败则保持未登录状态
72
- console.error("Failed to fetch current user with stored token:", e);
73
- }
74
- }
75
- } catch (error) {
76
- console.error("Failed to load auth data:", error);
77
- } finally {
78
- setIsLoading(false);
79
- }
80
- };
81
-
82
- const login = async (newToken: string) => {
83
- try {
84
- setToken(newToken);
85
- // 统一写入 access_token,供 OpenAPI 读取并自动携带
86
- await AsyncStorage.setItem("access_token", newToken);
87
- // 登录后拉取当前用户并缓存
88
- try {
89
- const me = await UsersService.getCurrentUserApiV1UsersMeGet();
90
- if (me?.success && me.data) {
91
- setUser(me.data);
92
- await AsyncStorage.setItem("user_data", JSON.stringify(me.data));
93
- }
94
- } catch (e) {
95
- console.error("Fetch current user after login failed:", e);
96
- }
97
- } catch (error) {
98
- console.error("Login failed:", error);
99
- throw error;
100
- }
101
- };
102
-
103
- const logout = async () => {
104
- try {
105
- // await AuthenticationService.logoutApiV1AuthLogoutPost(true);
106
- } catch(error) {
107
- console.warn('Logout failed:', error);
108
- }
109
- // remove token
110
- setToken(null);
111
- setUser(null);
112
- await AsyncStorage.multiRemove(["auth_token", "access_token", "user_data"]);
113
- };
114
-
115
- const updateUser = (userData: Partial<UserOut>) => {
116
- if (user) {
117
- const updatedUser = { ...user, ...userData };
118
- setUser(updatedUser);
119
- AsyncStorage.setItem("user_data", JSON.stringify(updatedUser));
120
- }
121
- };
122
-
30
+ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
123
31
  const value: AuthContextType = {
124
- user,
125
- token,
126
- isAuthenticated: !!token && !!user,
127
- isLoading,
128
- login,
129
- logout,
130
- updateUser,
32
+ user: null,
33
+ token: null,
34
+ isAuthenticated: false,
35
+ isLoading: false,
36
+ login: async (token: string) => {},
37
+ logout: async () => {},
38
+ updateUser: () => {},
131
39
  };
132
-
133
40
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
134
41
  };
135
42
 
@@ -3,10 +3,7 @@ import {
3
3
  View,
4
4
  Text,
5
5
  ScrollView,
6
- TouchableOpacity,
7
6
  RefreshControl,
8
- Image,
9
- ActivityIndicator,
10
7
  } from 'react-native';
11
8
  import { useRouter, useFocusEffect } from 'expo-router';
12
9
  import { FontAwesome6 } from '@expo/vector-icons';
@@ -15,7 +12,7 @@ import { useTheme } from "@/hooks/useTheme";
15
12
 
16
13
  import { Screen } from '@/components/Screen';
17
14
 
18
- import styles from './styles';
15
+ import { styles } from './styles';
19
16
 
20
17
 
21
18
  export default function HomeScreen() {
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet, Platform } from 'react-native';
2
2
 
3
- const styles = StyleSheet.create({
3
+ export const styles = StyleSheet.create({
4
4
  loadingContainer: {
5
5
  flex: 1,
6
6
  justifyContent: 'center',
@@ -22,18 +22,6 @@ const styles = StyleSheet.create({
22
22
  fontSize: 16,
23
23
  color: '#64748B',
24
24
  },
25
- retryButton: {
26
- marginTop: 20,
27
- paddingHorizontal: 24,
28
- paddingVertical: 12,
29
- backgroundColor: '#2563EB',
30
- borderRadius: 8,
31
- },
32
- retryButtonText: {
33
- color: '#FFFFFF',
34
- fontSize: 14,
35
- fontWeight: '600',
36
- },
37
25
  header: {
38
26
  flexDirection: 'row',
39
27
  justifyContent: 'space-between',
@@ -44,11 +32,6 @@ const styles = StyleSheet.create({
44
32
  // borderBottomWidth: 1,
45
33
  borderBottomColor: '#E2E8F0',
46
34
  },
47
- headerLeft: {
48
- flexDirection: 'row',
49
- alignItems: 'center',
50
- gap: 10,
51
- },
52
35
  logoContainer: {
53
36
  width: 32,
54
37
  height: 32,
@@ -74,259 +57,4 @@ const styles = StyleSheet.create({
74
57
  color: '#1E293B',
75
58
  letterSpacing: -0.5,
76
59
  },
77
- userMenuContainer: {
78
- flexDirection: 'row',
79
- alignItems: 'center',
80
- gap: 10,
81
- paddingLeft: 16,
82
- borderLeftWidth: 1,
83
- borderLeftColor: '#E2E8F0',
84
- },
85
- userInfo: {
86
- alignItems: 'flex-end',
87
- },
88
- userName: {
89
- fontSize: 14,
90
- fontWeight: '500',
91
- color: '#1E293B',
92
- },
93
- userRole: {
94
- fontSize: 12,
95
- color: '#64748B',
96
- },
97
- avatar: {
98
- width: 36,
99
- height: 36,
100
- borderRadius: 18,
101
- borderWidth: 2,
102
- borderColor: '#FFFFFF',
103
- ...Platform.select({
104
- ios: {
105
- shadowColor: '#000',
106
- shadowOffset: { width: 0, height: 1 },
107
- shadowOpacity: 0.1,
108
- shadowRadius: 2,
109
- },
110
- android: {
111
- elevation: 2,
112
- },
113
- }),
114
- },
115
- avatarPlaceholder: {
116
- width: 36,
117
- height: 36,
118
- borderRadius: 18,
119
- justifyContent: 'center',
120
- alignItems: 'center',
121
- borderWidth: 2,
122
- borderColor: '#FFFFFF',
123
- backgroundColor: '#3B82F6',
124
- ...Platform.select({
125
- ios: {
126
- shadowColor: '#000',
127
- shadowOffset: { width: 0, height: 1 },
128
- shadowOpacity: 0.1,
129
- shadowRadius: 2,
130
- },
131
- android: {
132
- elevation: 2,
133
- },
134
- }),
135
- },
136
- avatarInitial: {
137
- fontSize: 14,
138
- fontWeight: '700',
139
- color: '#FFFFFF',
140
- },
141
- content: {
142
- paddingHorizontal: 16,
143
- paddingTop: 24,
144
- },
145
- welcomeSection: {
146
- marginBottom: 24,
147
- },
148
- welcomeTitle: {
149
- fontSize: 22,
150
- fontWeight: '700',
151
- color: '#1E293B',
152
- marginBottom: 4,
153
- },
154
- welcomeSubtitle: {
155
- fontSize: 14,
156
- color: '#64748B',
157
- },
158
- statsGrid: {
159
- flexDirection: 'row',
160
- gap: 12,
161
- marginBottom: 24,
162
- },
163
- statCard: {
164
- flex: 1,
165
- backgroundColor: '#FFFFFF',
166
- borderRadius: 12,
167
- padding: 16,
168
- ...Platform.select({
169
- ios: {
170
- shadowColor: '#000',
171
- shadowOffset: { width: 0, height: 1 },
172
- shadowOpacity: 0.05,
173
- shadowRadius: 3,
174
- },
175
- android: {
176
- elevation: 2,
177
- },
178
- }),
179
- },
180
- statCardHeader: {
181
- flexDirection: 'row',
182
- justifyContent: 'space-between',
183
- alignItems: 'flex-start',
184
- marginBottom: 12,
185
- },
186
- statIconContainer: {
187
- width: 40,
188
- height: 40,
189
- borderRadius: 10,
190
- justifyContent: 'center',
191
- alignItems: 'center',
192
- },
193
- statIconBlue: {
194
- backgroundColor: '#EFF6FF',
195
- },
196
- statIconRed: {
197
- backgroundColor: '#FEF2F2',
198
- },
199
- statIconGreen: {
200
- backgroundColor: '#ECFDF5',
201
- },
202
- attentionBadge: {
203
- backgroundColor: '#FEF2F2',
204
- paddingHorizontal: 6,
205
- paddingVertical: 2,
206
- borderRadius: 10,
207
- },
208
- attentionBadgeText: {
209
- fontSize: 10,
210
- fontWeight: '500',
211
- color: '#EF4444',
212
- },
213
- rateBadge: {
214
- backgroundColor: '#ECFDF5',
215
- paddingHorizontal: 6,
216
- paddingVertical: 2,
217
- borderRadius: 10,
218
- },
219
- rateBadgeText: {
220
- fontSize: 10,
221
- fontWeight: '500',
222
- color: '#10B981',
223
- },
224
- statValue: {
225
- fontSize: 28,
226
- fontWeight: '700',
227
- color: '#1E293B',
228
- marginBottom: 2,
229
- },
230
- statLabel: {
231
- fontSize: 13,
232
- color: '#64748B',
233
- },
234
- shortcutsSection: {
235
- gap: 12,
236
- marginBottom: 24,
237
- },
238
- shortcutCard: {
239
- flexDirection: 'row',
240
- justifyContent: 'space-between',
241
- alignItems: 'center',
242
- backgroundColor: '#FFFFFF',
243
- borderRadius: 12,
244
- padding: 16,
245
- ...Platform.select({
246
- ios: {
247
- shadowColor: '#000',
248
- shadowOffset: { width: 0, height: 1 },
249
- shadowOpacity: 0.05,
250
- shadowRadius: 3,
251
- },
252
- android: {
253
- elevation: 2,
254
- },
255
- }),
256
- },
257
- shortcutContent: {
258
- flex: 1,
259
- marginRight: 16,
260
- },
261
- shortcutTitle: {
262
- fontSize: 16,
263
- fontWeight: '600',
264
- color: '#1E293B',
265
- marginBottom: 6,
266
- },
267
- shortcutDescription: {
268
- fontSize: 13,
269
- color: '#64748B',
270
- marginBottom: 10,
271
- lineHeight: 18,
272
- },
273
- shortcutAction: {
274
- flexDirection: 'row',
275
- alignItems: 'center',
276
- gap: 6,
277
- },
278
- shortcutActionText: {
279
- fontSize: 13,
280
- fontWeight: '500',
281
- color: '#2563EB',
282
- },
283
- shortcutIconContainer: {
284
- width: 56,
285
- height: 56,
286
- borderRadius: 28,
287
- justifyContent: 'center',
288
- alignItems: 'center',
289
- },
290
- shortcutIconBlue: {
291
- backgroundColor: '#EFF6FF',
292
- },
293
- shortcutIconGreen: {
294
- backgroundColor: '#ECFDF5',
295
- },
296
- bannerContainer: {
297
- height: 160,
298
- borderRadius: 12,
299
- overflow: 'hidden',
300
- backgroundColor: '#1E3A8A',
301
- },
302
- bannerOverlay: {
303
- flex: 1,
304
- justifyContent: 'center',
305
- paddingHorizontal: 20,
306
- },
307
- bannerTitle: {
308
- fontSize: 18,
309
- fontWeight: '700',
310
- color: '#FFFFFF',
311
- marginBottom: 6,
312
- },
313
- bannerSubtitle: {
314
- fontSize: 13,
315
- color: '#BFDBFE',
316
- marginBottom: 16,
317
- },
318
- bannerButton: {
319
- alignSelf: 'flex-start',
320
- backgroundColor: '#FFFFFF',
321
- paddingHorizontal: 20,
322
- paddingVertical: 10,
323
- borderRadius: 8,
324
- },
325
- bannerButtonText: {
326
- fontSize: 13,
327
- fontWeight: '500',
328
- color: '#2563EB',
329
- },
330
60
  });
331
-
332
- export default styles;