@farmzone/fz-template-react 1.0.6 → 1.0.7

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 (64) hide show
  1. package/README.md +102 -102
  2. package/bin/create.js +108 -108
  3. package/package.json +24 -24
  4. package/template/.env.example +5 -5
  5. package/template/.prettierrc +9 -9
  6. package/template/eslint.config.js +26 -26
  7. package/template/index.css +32 -32
  8. package/template/index.html +19 -19
  9. package/template/package.json +54 -54
  10. package/template/pnpm-lock.yaml +4214 -4214
  11. package/template/public/mockServiceWorker.js +349 -349
  12. package/template/src/app/App.tsx +26 -26
  13. package/template/src/app/api/api.ts +178 -178
  14. package/template/src/app/api/queries.ts +335 -335
  15. package/template/src/app/api/queryKey.ts +7 -7
  16. package/template/src/app/api/token.ts +8 -7
  17. package/template/src/app/layout/Layout.tsx +33 -33
  18. package/template/src/app/layout/ListContents.tsx +9 -9
  19. package/template/src/app/layout/ListHeader.tsx +41 -41
  20. package/template/src/app/layout/MultiTabNav.tsx +106 -101
  21. package/template/src/app/layout/Sidebar.tsx +33 -33
  22. package/template/src/app/layout/UserInfo.tsx +95 -94
  23. package/template/src/app/layout/menu.ts +79 -55
  24. package/template/src/app/layout/tabSwitchStore.ts +11 -11
  25. package/template/src/app/router/Router.tsx +56 -56
  26. package/template/src/app/store/index.ts +26 -26
  27. package/template/src/index.tsx +21 -21
  28. package/template/src/mocks/browser.ts +17 -17
  29. package/template/src/mocks/handlers.ts +43 -43
  30. package/template/src/mocks/scenarios.ts +57 -57
  31. package/template/src/pages/dashboard/index.tsx +541 -541
  32. package/template/src/pages/error/Error.tsx +29 -29
  33. package/template/src/pages/error/NotFound.tsx +27 -27
  34. package/template/src/pages/login/index.tsx +317 -317
  35. package/template/src/pages/post/PostFormModal.tsx +128 -128
  36. package/template/src/pages/post/detail/index.tsx +545 -545
  37. package/template/src/pages/post/index.tsx +266 -266
  38. package/template/src/pages/sample/SampleFormModal.tsx +188 -188
  39. package/template/src/pages/sample/detail/index.tsx +551 -517
  40. package/template/src/pages/sample/index.tsx +298 -298
  41. package/template/src/pages/sample/modal/index.tsx +308 -308
  42. package/template/src/pages/system/log/index.tsx +173 -173
  43. package/template/src/pages/user/config/columns.tsx +102 -102
  44. package/template/src/pages/user/config/schema.ts +54 -54
  45. package/template/src/pages/user/index.tsx +704 -650
  46. package/template/src/shared/components/CommentInput.tsx +243 -243
  47. package/template/src/shared/components/FilePreviewCard.tsx +71 -71
  48. package/template/src/shared/config/text.ts +27 -27
  49. package/template/src/shared/config/type.ts +40 -40
  50. package/template/src/shared/utils/format.ts +11 -11
  51. package/template/src/types/auth.ts +10 -10
  52. package/template/src/types/comment.ts +33 -33
  53. package/template/src/types/common.ts +19 -19
  54. package/template/src/types/dashboard.ts +53 -53
  55. package/template/src/types/index.ts +16 -16
  56. package/template/src/types/log.ts +21 -21
  57. package/template/src/types/post.ts +32 -32
  58. package/template/src/types/sample.ts +33 -33
  59. package/template/src/types/user.ts +51 -51
  60. package/template/src/vite-env.d.ts +10 -10
  61. package/template/tsconfig.app.json +32 -32
  62. package/template/tsconfig.json +7 -7
  63. package/template/tsconfig.node.json +26 -26
  64. package/template/vite.config.ts +13 -13
@@ -1,43 +1,43 @@
1
- import { HttpResponse, delay, http, passthrough } from "msw";
2
-
3
- import { getScenario, getTargetPath } from "./scenarios";
4
-
5
- const BASE_URL = `${import.meta.env.VITE_APP_API_HOST}/api/${import.meta.env.VITE_APP_API_VERSION}`;
6
-
7
- const ERROR_RESPONSES: Record<string, () => Response> = {
8
- "500": () => HttpResponse.json({ message: "Internal Server Error" }, { status: 500 }),
9
- "503": () => HttpResponse.json({ message: "Service Unavailable" }, { status: 503 }),
10
- "408": () => HttpResponse.json({ message: "Request Timeout" }, { status: 408 }),
11
- "401": () => HttpResponse.json({ message: "Unauthorized" }, { status: 401 }),
12
- "403": () => HttpResponse.json({ message: "Forbidden" }, { status: 403 }),
13
- "404": () => HttpResponse.json({ message: "Not Found" }, { status: 404 }),
14
- "400": () => HttpResponse.json({ message: "Bad Request" }, { status: 400 }),
15
- network: () => HttpResponse.error(),
16
- };
17
-
18
- const timeoutInterceptor = async () => {
19
- await delay(3_000); // 3초 지연 후 408 반환 (타임아웃 시뮬레이션)
20
- return HttpResponse.json({ message: "Request Timeout" }, { status: 408 });
21
- };
22
-
23
- const errorInterceptor = async ({ request }: { request: Request }) => {
24
- const scenario = getScenario();
25
-
26
- if (scenario === "none") return passthrough();
27
-
28
- const targetPath = getTargetPath();
29
- if (targetPath && !request.url.includes(targetPath)) return passthrough();
30
-
31
- if (scenario === "timeout") return timeoutInterceptor();
32
-
33
- const handler = ERROR_RESPONSES[scenario];
34
- return handler ? handler() : passthrough();
35
- };
36
-
37
- export const handlers = [
38
- http.get(`${BASE_URL}/*`, errorInterceptor),
39
- http.post(`${BASE_URL}/*`, errorInterceptor),
40
- http.put(`${BASE_URL}/*`, errorInterceptor),
41
- http.patch(`${BASE_URL}/*`, errorInterceptor),
42
- http.delete(`${BASE_URL}/*`, errorInterceptor),
43
- ];
1
+ import { HttpResponse, delay, http, passthrough } from "msw";
2
+
3
+ import { getScenario, getTargetPath } from "./scenarios";
4
+
5
+ const BASE_URL = `${import.meta.env.VITE_APP_API_HOST}/api/${import.meta.env.VITE_APP_API_VERSION}`;
6
+
7
+ const ERROR_RESPONSES: Record<string, () => Response> = {
8
+ "500": () => HttpResponse.json({ message: "Internal Server Error" }, { status: 500 }),
9
+ "503": () => HttpResponse.json({ message: "Service Unavailable" }, { status: 503 }),
10
+ "408": () => HttpResponse.json({ message: "Request Timeout" }, { status: 408 }),
11
+ "401": () => HttpResponse.json({ message: "Unauthorized" }, { status: 401 }),
12
+ "403": () => HttpResponse.json({ message: "Forbidden" }, { status: 403 }),
13
+ "404": () => HttpResponse.json({ message: "Not Found" }, { status: 404 }),
14
+ "400": () => HttpResponse.json({ message: "Bad Request" }, { status: 400 }),
15
+ network: () => HttpResponse.error(),
16
+ };
17
+
18
+ const timeoutInterceptor = async () => {
19
+ await delay(3_000); // 3초 지연 후 408 반환 (타임아웃 시뮬레이션)
20
+ return HttpResponse.json({ message: "Request Timeout" }, { status: 408 });
21
+ };
22
+
23
+ const errorInterceptor = async ({ request }: { request: Request }) => {
24
+ const scenario = getScenario();
25
+
26
+ if (scenario === "none") return passthrough();
27
+
28
+ const targetPath = getTargetPath();
29
+ if (targetPath && !request.url.includes(targetPath)) return passthrough();
30
+
31
+ if (scenario === "timeout") return timeoutInterceptor();
32
+
33
+ const handler = ERROR_RESPONSES[scenario];
34
+ return handler ? handler() : passthrough();
35
+ };
36
+
37
+ export const handlers = [
38
+ http.get(`${BASE_URL}/*`, errorInterceptor),
39
+ http.post(`${BASE_URL}/*`, errorInterceptor),
40
+ http.put(`${BASE_URL}/*`, errorInterceptor),
41
+ http.patch(`${BASE_URL}/*`, errorInterceptor),
42
+ http.delete(`${BASE_URL}/*`, errorInterceptor),
43
+ ];
@@ -1,57 +1,57 @@
1
- // 브라우저 콘솔에서 에러 시나리오 변경:
2
- // window.__setMswErrorScenario('500') → 모든 API 서버 내부 오류
3
- // window.__setMswErrorScenario('500', 'users') → /users 포함 URL만 500, 나머지 정상
4
- // window.__setMswErrorScenario('503') → 서비스 일시 불능 (1회 재시도)
5
- // window.__setMswErrorScenario('408') → 타임아웃 (1회 재시도)
6
- // window.__setMswErrorScenario('401') → 인증 오류
7
- // window.__setMswErrorScenario('403') → 권한 오류
8
- // window.__setMswErrorScenario('404') → 존재하지 않는 리소스
9
- // window.__setMswErrorScenario('400') → 잘못된 요청
10
- // window.__setMswErrorScenario('timeout') → 타임아웃 (3초 지연 후 408 반환 → 1회 재시도)
11
- // window.__setMswErrorScenario('network') → 네트워크 장애 (1회 재시도)
12
- // window.__setMswErrorScenario('none') → 모킹 해제
13
-
14
- export type MswScenario =
15
- | "500"
16
- | "503"
17
- | "408"
18
- | "401"
19
- | "403"
20
- | "404"
21
- | "400"
22
- | "network"
23
- | "timeout"
24
- | "none";
25
-
26
- const SCENARIO_KEY = "msw-scenario";
27
- const TARGET_KEY = "msw-target-path";
28
-
29
- export const getScenario = (): MswScenario => (localStorage.getItem(SCENARIO_KEY) as MswScenario) ?? "none";
30
-
31
- export const getTargetPath = (): string | null => localStorage.getItem(TARGET_KEY);
32
-
33
- export const setErrorScenario = (scenario: MswScenario, targetPath?: string) => {
34
- localStorage.setItem(SCENARIO_KEY, scenario);
35
-
36
- if (targetPath) {
37
- localStorage.setItem(TARGET_KEY, targetPath);
38
- } else {
39
- localStorage.removeItem(TARGET_KEY);
40
- }
41
-
42
- const flags = [targetPath ? `대상: *${targetPath}*` : null].filter(Boolean).join(", ");
43
-
44
- console.log(`[MSW] 시나리오 변경: ${scenario}${flags ? ` (${flags})` : ""} (새로고침 후 적용)`);
45
- };
46
-
47
- export const getScenarioGuide = () => {
48
- console.log(`
49
- [브라우저 콘솔에서 에러 시나리오 변경 Guide]
50
-
51
- (1) API 500 에러
52
- window.__setMswErrorScenario('500')
53
-
54
- (2) users API만 500 에러
55
- window.__setMswErrorScenario('500', 'users')
56
- `);
57
- };
1
+ // 브라우저 콘솔에서 에러 시나리오 변경:
2
+ // window.__setMswErrorScenario('500') → 모든 API 서버 내부 오류
3
+ // window.__setMswErrorScenario('500', 'users') → /users 포함 URL만 500, 나머지 정상
4
+ // window.__setMswErrorScenario('503') → 서비스 일시 불능 (1회 재시도)
5
+ // window.__setMswErrorScenario('408') → 타임아웃 (1회 재시도)
6
+ // window.__setMswErrorScenario('401') → 인증 오류
7
+ // window.__setMswErrorScenario('403') → 권한 오류
8
+ // window.__setMswErrorScenario('404') → 존재하지 않는 리소스
9
+ // window.__setMswErrorScenario('400') → 잘못된 요청
10
+ // window.__setMswErrorScenario('timeout') → 타임아웃 (3초 지연 후 408 반환 → 1회 재시도)
11
+ // window.__setMswErrorScenario('network') → 네트워크 장애 (1회 재시도)
12
+ // window.__setMswErrorScenario('none') → 모킹 해제
13
+
14
+ export type MswScenario =
15
+ | "500"
16
+ | "503"
17
+ | "408"
18
+ | "401"
19
+ | "403"
20
+ | "404"
21
+ | "400"
22
+ | "network"
23
+ | "timeout"
24
+ | "none";
25
+
26
+ const SCENARIO_KEY = "msw-scenario";
27
+ const TARGET_KEY = "msw-target-path";
28
+
29
+ export const getScenario = (): MswScenario => (localStorage.getItem(SCENARIO_KEY) as MswScenario) ?? "none";
30
+
31
+ export const getTargetPath = (): string | null => localStorage.getItem(TARGET_KEY);
32
+
33
+ export const setErrorScenario = (scenario: MswScenario, targetPath?: string) => {
34
+ localStorage.setItem(SCENARIO_KEY, scenario);
35
+
36
+ if (targetPath) {
37
+ localStorage.setItem(TARGET_KEY, targetPath);
38
+ } else {
39
+ localStorage.removeItem(TARGET_KEY);
40
+ }
41
+
42
+ const flags = [targetPath ? `대상: *${targetPath}*` : null].filter(Boolean).join(", ");
43
+
44
+ console.log(`[MSW] 시나리오 변경: ${scenario}${flags ? ` (${flags})` : ""} (새로고침 후 적용)`);
45
+ };
46
+
47
+ export const getScenarioGuide = () => {
48
+ console.log(`
49
+ [브라우저 콘솔에서 에러 시나리오 변경 Guide]
50
+
51
+ (1) API 500 에러
52
+ window.__setMswErrorScenario('500')
53
+
54
+ (2) users API만 500 에러
55
+ window.__setMswErrorScenario('500', 'users')
56
+ `);
57
+ };