@qlover/create-app 0.7.5 → 0.7.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.
- package/CHANGELOG.md +257 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/.env.template +22 -0
- package/dist/templates/next-app/.prettierignore +58 -0
- package/dist/templates/next-app/README.md +36 -0
- package/dist/templates/next-app/build/generateLocales.ts +25 -0
- package/dist/templates/next-app/config/IOCIdentifier.ts +45 -0
- package/dist/templates/next-app/config/Identifier/common.error.ts +34 -0
- package/dist/templates/next-app/config/Identifier/common.ts +62 -0
- package/dist/templates/next-app/config/Identifier/index.ts +10 -0
- package/dist/templates/next-app/config/Identifier/page.about.ts +181 -0
- package/dist/templates/next-app/config/Identifier/page.executor.ts +272 -0
- package/dist/templates/next-app/config/Identifier/page.home.ts +63 -0
- package/dist/templates/next-app/config/Identifier/page.identifiter.ts +39 -0
- package/dist/templates/next-app/config/Identifier/page.jsonStorage.ts +72 -0
- package/dist/templates/next-app/config/Identifier/page.login.ts +165 -0
- package/dist/templates/next-app/config/Identifier/page.register.ts +147 -0
- package/dist/templates/next-app/config/Identifier/page.request.ts +182 -0
- package/dist/templates/next-app/config/common.ts +34 -0
- package/dist/templates/next-app/config/i18n/PageI18nInterface.ts +51 -0
- package/dist/templates/next-app/config/i18n/i18nConfig.ts +12 -0
- package/dist/templates/next-app/config/i18n/index.ts +3 -0
- package/dist/templates/next-app/config/i18n/loginI18n.ts +42 -0
- package/dist/templates/next-app/config/theme.ts +23 -0
- package/dist/templates/next-app/docs/env.md +94 -0
- package/dist/templates/next-app/eslint.config.mjs +181 -0
- package/dist/templates/next-app/next.config.ts +21 -0
- package/dist/templates/next-app/package.json +58 -0
- package/dist/templates/next-app/plugins/eslint-plugin-testid.mjs +94 -0
- package/dist/templates/next-app/plugins/generateLocalesPlugin.ts +33 -0
- package/dist/templates/next-app/postcss.config.mjs +5 -0
- package/dist/templates/next-app/public/file.svg +1 -0
- package/dist/templates/next-app/public/globe.svg +1 -0
- package/dist/templates/next-app/public/locales/en/common.json +183 -0
- package/dist/templates/next-app/public/locales/zh/common.json +183 -0
- package/dist/templates/next-app/public/next.svg +1 -0
- package/dist/templates/next-app/public/vercel.svg +1 -0
- package/dist/templates/next-app/public/window.svg +1 -0
- package/dist/templates/next-app/src/app/[locale]/favicon.ico +0 -0
- package/dist/templates/next-app/src/app/[locale]/layout.tsx +44 -0
- package/dist/templates/next-app/src/app/[locale]/login/FeatureItem.tsx +13 -0
- package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +115 -0
- package/dist/templates/next-app/src/app/[locale]/login/page.tsx +73 -0
- package/dist/templates/next-app/src/app/[locale]/not-found.tsx +24 -0
- package/dist/templates/next-app/src/app/[locale]/page.tsx +106 -0
- package/dist/templates/next-app/src/base/cases/AppConfig.ts +15 -0
- package/dist/templates/next-app/src/base/cases/InversifyContainer.ts +33 -0
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +25 -0
- package/dist/templates/next-app/src/base/port/UserServiceInterface.ts +11 -0
- package/dist/templates/next-app/src/base/services/I18nService.ts +115 -0
- package/dist/templates/next-app/src/base/services/UserService.ts +23 -0
- package/dist/templates/next-app/src/core/IOC.ts +58 -0
- package/dist/templates/next-app/src/core/IocRegisterImpl.ts +100 -0
- package/dist/templates/next-app/src/core/bootstraps/BootstrapClient.ts +98 -0
- package/dist/templates/next-app/src/core/bootstraps/BootstrapsRegistry.ts +47 -0
- package/dist/templates/next-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
- package/dist/templates/next-app/src/core/bootstraps/PrintBootstrap.ts +18 -0
- package/dist/templates/next-app/src/core/globals.ts +21 -0
- package/dist/templates/next-app/src/i18n/request.ts +22 -0
- package/dist/templates/next-app/src/i18n/routing.ts +30 -0
- package/dist/templates/next-app/src/middleware.ts +22 -0
- package/dist/templates/next-app/src/server/getServerI18n.ts +26 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/_default.css +239 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/dark.css +178 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/index.css +3 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/no-context.css +34 -0
- package/dist/templates/next-app/src/styles/css/antd-themes/pink.css +204 -0
- package/dist/templates/next-app/src/styles/css/index.css +6 -0
- package/dist/templates/next-app/src/styles/css/page.css +19 -0
- package/dist/templates/next-app/src/styles/css/tailwind.css +5 -0
- package/dist/templates/next-app/src/styles/css/themes/_default.css +29 -0
- package/dist/templates/next-app/src/styles/css/themes/dark.css +29 -0
- package/dist/templates/next-app/src/styles/css/themes/index.css +3 -0
- package/dist/templates/next-app/src/styles/css/themes/pink.css +29 -0
- package/dist/templates/next-app/src/styles/css/zIndex.css +9 -0
- package/dist/templates/next-app/src/uikit/components/BaseHeader.tsx +42 -0
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +25 -0
- package/dist/templates/next-app/src/uikit/components/ComboProvider.tsx +45 -0
- package/dist/templates/next-app/src/uikit/components/LanguageSwitcher.tsx +52 -0
- package/dist/templates/next-app/src/uikit/components/LocaleLink.tsx +51 -0
- package/dist/templates/next-app/src/uikit/components/NextIntlProvider.tsx +21 -0
- package/dist/templates/next-app/src/uikit/components/ThemeSwitcher.tsx +86 -0
- package/dist/templates/next-app/src/uikit/context/IOCContext.ts +6 -0
- package/dist/templates/next-app/src/uikit/hook/useI18nInterface.ts +28 -0
- package/dist/templates/next-app/src/uikit/hook/useIOC.ts +37 -0
- package/dist/templates/next-app/src/uikit/hook/useMountedClient.ts +11 -0
- package/dist/templates/next-app/src/uikit/hook/useStore.ts +15 -0
- package/dist/templates/next-app/tailwind.config.ts +8 -0
- package/dist/templates/next-app/tsconfig.json +36 -0
- package/dist/templates/react-app/.env.template +0 -2
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +1 -1
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +6 -31
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +1 -1
- package/dist/templates/react-app/config/IOCIdentifier.ts +77 -5
- package/dist/templates/react-app/config/app.router.ts +2 -2
- package/dist/templates/react-app/package.json +4 -7
- package/dist/templates/react-app/public/locales/en/common.json +1 -1
- package/dist/templates/react-app/public/locales/zh/common.json +1 -1
- package/dist/templates/react-app/src/App.tsx +9 -4
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +4 -0
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +16 -13
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +4 -3
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +2 -2
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +39 -0
- package/dist/templates/react-app/src/base/cases/RequestState.ts +20 -0
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +8 -2
- package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +7 -0
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +24 -0
- package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +10 -0
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +20 -0
- package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +20 -0
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +23 -0
- package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +5 -0
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +27 -0
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +12 -0
- package/dist/templates/react-app/src/base/services/I18nService.ts +10 -6
- package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +23 -5
- package/dist/templates/react-app/src/base/services/RouteService.ts +25 -54
- package/dist/templates/react-app/src/base/services/UserService.ts +10 -20
- package/dist/templates/react-app/src/core/IOC.ts +1 -26
- package/dist/templates/react-app/src/core/IocRegisterImpl.ts +125 -0
- package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +4 -6
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +8 -6
- package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +2 -2
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -6
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +8 -7
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +8 -19
- package/dist/templates/react-app/src/pages/base/{ErrorIdentifierPage.tsx → IdentifierPage.tsx} +1 -1
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +11 -15
- package/dist/templates/react-app/src/pages/base/Layout.tsx +1 -1
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +2 -2
- package/dist/templates/react-app/src/pages/base/RequestPage.tsx +34 -46
- package/dist/templates/react-app/src/styles/css/antd-themes/_default.css +2 -2
- package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +2 -2
- package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +2 -2
- package/dist/templates/react-app/src/styles/css/index.css +1 -0
- package/dist/templates/react-app/src/styles/css/page.css +8 -0
- package/dist/templates/react-app/src/styles/css/zIndex.css +9 -0
- package/dist/templates/react-app/src/uikit/{controllers/ExecutorController.ts → bridges/ExecutorPageBridge.ts} +13 -36
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +41 -0
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +16 -0
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +136 -0
- package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +3 -2
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +2 -2
- package/dist/templates/react-app/src/uikit/{providers → components}/ProcessExecutorProvider.tsx +4 -4
- package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +1 -1
- package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +3 -5
- package/dist/templates/react-app/src/uikit/{providers → components}/UserAuthProvider.tsx +3 -3
- package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +5 -2
- package/dist/templates/react-app/src/uikit/hooks/{userRouterService.ts → useNavigateBridge.ts} +3 -3
- package/dist/templates/react-app/src/uikit/hooks/useStore.ts +5 -2
- package/dist/templates/react-app/tsconfig.json +1 -4
- package/package.json +1 -1
- package/dist/templates/react-app/src/base/port/InteractionHubInterface.ts +0 -94
- package/dist/templates/react-app/src/base/port/UIDependenciesInterface.ts +0 -37
- package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +0 -25
- package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +0 -74
- package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +0 -26
- package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +0 -30
- package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +0 -49
- package/dist/templates/react-app/src/uikit/controllers/RequestController.ts +0 -158
- /package/dist/templates/react-app/src/uikit/{providers → components}/BaseRouteProvider.tsx +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
{
|
|
2
|
+
"err__local__no__user__token": "Local no user token",
|
|
3
|
+
"err__global__no__window": "Global no window",
|
|
4
|
+
"err__within__page__provider": "Must be used in PageProvider",
|
|
5
|
+
"err__response__no__token": "Response not token value",
|
|
6
|
+
"err__not__found__component": "Not found component",
|
|
7
|
+
"header__theme__default": "Default Theme",
|
|
8
|
+
"header__theme__dark": "Dark Theme",
|
|
9
|
+
"header__theme__pink": "Pink Theme",
|
|
10
|
+
"auth__logout__dialog__title": "Logout",
|
|
11
|
+
"auth__logout__dialog__content": "Are you sure you want to logout?",
|
|
12
|
+
"page__404__title": "404 Page Not Found",
|
|
13
|
+
"page__404__description": "404 Page Description",
|
|
14
|
+
"page__500__title": "500 Page Error",
|
|
15
|
+
"page__500__description": "500 Page Description",
|
|
16
|
+
"page__about__title": "About",
|
|
17
|
+
"page__about__description": "Learn more about our project and team information",
|
|
18
|
+
"about__message__test": "This is a test message",
|
|
19
|
+
"about__notification__title": "Notification Title",
|
|
20
|
+
"about__notification__description": "This is a test notification",
|
|
21
|
+
"about__button__message": "Show Message",
|
|
22
|
+
"about__button__message2": "Static Message",
|
|
23
|
+
"about__button__notification": "Show Notification",
|
|
24
|
+
"about__button__notification2": "Static Notification",
|
|
25
|
+
"about__tooltip__text": "This is a tooltip text",
|
|
26
|
+
"about__button__tooltip": "Hover to show Tooltip",
|
|
27
|
+
"about__modal__title": "Modal Example",
|
|
28
|
+
"about__modal__content": "This is modal content",
|
|
29
|
+
"about__button__modal": "Show Modal",
|
|
30
|
+
"about__drawer__title": "Drawer Example",
|
|
31
|
+
"about__drawer__content": "This is drawer content",
|
|
32
|
+
"about__button__drawer": "Show Drawer",
|
|
33
|
+
"about__popover__content": "This is a popover card",
|
|
34
|
+
"about__popover__title": "Popover Title",
|
|
35
|
+
"about__button__popover": "Show Popover",
|
|
36
|
+
"about__popconfirm__title": "Confirmation",
|
|
37
|
+
"about__popconfirm__description": "Are you sure you want to perform this action?",
|
|
38
|
+
"about__button__popconfirm": "Show Popconfirm",
|
|
39
|
+
"about__alert__message": "This is a warning alert",
|
|
40
|
+
"about__ok__text": "OK",
|
|
41
|
+
"about__cancel__text": "Cancel",
|
|
42
|
+
"page__executor__title": "Executor Examples",
|
|
43
|
+
"page__executor__description": "A powerful task executor supporting multiple task types and state management",
|
|
44
|
+
"page__error_identifier__title": "Error Identifier",
|
|
45
|
+
"page__executor__main_title": "Executor",
|
|
46
|
+
"page__executor__test_plugin__title": "Test Plugin",
|
|
47
|
+
"page__executor__task__status__pending": "Pending",
|
|
48
|
+
"page__executor__task__status__running": "Running",
|
|
49
|
+
"page__executor__task__status__completed": "Completed",
|
|
50
|
+
"page__executor__task__status__failed": "Failed",
|
|
51
|
+
"page__executor__task__type__data_sync": "Data Sync",
|
|
52
|
+
"page__executor__task__type__report": "Report Generation",
|
|
53
|
+
"page__executor__task__type__maintenance": "System Maintenance",
|
|
54
|
+
"page__executor__task__type__backup": "Backup",
|
|
55
|
+
"page__executor__task__duration__unit": "minutes",
|
|
56
|
+
"page__executor__task__start": "Start",
|
|
57
|
+
"page__executor__task__stop": "Stop",
|
|
58
|
+
"page__executor__task__success": "Task %{name} executed successfully",
|
|
59
|
+
"page__executor__task__failure": "Task %{name} execution failed",
|
|
60
|
+
"page__executor__plugin__test__success": "Plugin test successful",
|
|
61
|
+
"page__executor__plugin__test__failure": "Plugin test failed",
|
|
62
|
+
"page__executor__custom_task__url_required": "Please enter URL",
|
|
63
|
+
"page__executor__custom_task__name": "Custom Task %{method} %{url}",
|
|
64
|
+
"page__executor__create_task__title": "Create Custom Task",
|
|
65
|
+
"page__executor__create_button": "Create",
|
|
66
|
+
"page__executor__enter_url": "Enter URL",
|
|
67
|
+
"page__executor__task_list__title": "Task List",
|
|
68
|
+
"page__executor__task_stats__total": "Total Tasks",
|
|
69
|
+
"page__executor__task_stats__running": "Running",
|
|
70
|
+
"page__executor__task_stats__completed": "Completed",
|
|
71
|
+
"page__executor__task_stats__failed": "Failed",
|
|
72
|
+
"page__executor__task_history__title": "Execution History",
|
|
73
|
+
"page__executor__help__title": "Need Help?",
|
|
74
|
+
"page__executor__help__description": "Having issues? Check our task execution guide or contact support",
|
|
75
|
+
"page__executor__view_guide": "View Guide",
|
|
76
|
+
"page__executor__contact_support": "Contact Support",
|
|
77
|
+
"page__executor__request__timeout": "Request Timeout",
|
|
78
|
+
"page__home__title": "Home",
|
|
79
|
+
"page__home__description": "A modern frontend utility library collection providing various practical tools and components",
|
|
80
|
+
"home__welcome": "Welcome to the home page",
|
|
81
|
+
"home__description": "A modern frontend utility library collection providing various practical tools and components",
|
|
82
|
+
"page__error__identifier__description": "Error identifier usage and examples",
|
|
83
|
+
"home__explore": "Explore",
|
|
84
|
+
"home__get_started__title": "Ready to Get Started?",
|
|
85
|
+
"home__get_started__description": "Join us and discover the power of our utilities",
|
|
86
|
+
"home__get_started__button": "Get Started Now",
|
|
87
|
+
"page__error__identifier__main_title": "Error Identifier",
|
|
88
|
+
"page__error__identifier__source_description": "Identifier From: '@config/Identifier/error'",
|
|
89
|
+
"page__error__identifier__help__title": "Need Help?",
|
|
90
|
+
"page__error__identifier__help__description": "If you encounter any issues while using error identifiers, please contact our support team",
|
|
91
|
+
"page__error__identifier__contact_support": "Contact Support",
|
|
92
|
+
"page__jsonstorage__title": "JSONStorage Page",
|
|
93
|
+
"page__jsonstorage__description": "Use JSONStorage for data storage and management",
|
|
94
|
+
"page__jsonstorage__main_title": "JSONStorage Demo",
|
|
95
|
+
"page__jsonstorage__permanent_title": "Permanent Storage Test",
|
|
96
|
+
"page__jsonstorage__expire_title": "Expire Time Test",
|
|
97
|
+
"page__jsonstorage__timeout_title": "Request Timeout Setting",
|
|
98
|
+
"page__jsonstorage__format_title": "Test key: ${key}, Random value range: ${min}~${max}",
|
|
99
|
+
"page__jsonstorage__set_random": "Set Random Value",
|
|
100
|
+
"page__jsonstorage__current_value": "Current Value",
|
|
101
|
+
"page__jsonstorage__set_expire": "Set Random Value (with expire time)",
|
|
102
|
+
"page__jsonstorage__ms": "ms",
|
|
103
|
+
"page__login__title": "Login",
|
|
104
|
+
"page__login__description": "Login Page Description",
|
|
105
|
+
"login__title": "Login",
|
|
106
|
+
"login__email": "Email",
|
|
107
|
+
"login__username": "Username",
|
|
108
|
+
"login__password": "Password",
|
|
109
|
+
"login__login": "Login",
|
|
110
|
+
"login__welcome": "Welcome to the future of learning",
|
|
111
|
+
"login__subtitle": "Unlock personalized AI-powered learning experiences designed to accelerate your knowledge journey__",
|
|
112
|
+
"login__forgot_password": "Forgot your password?",
|
|
113
|
+
"login__continue_with": "or continue with",
|
|
114
|
+
"login__with_google": "Sign in with Google",
|
|
115
|
+
"login__no_account": "Don't have an account?",
|
|
116
|
+
"login__create_account": "Create one here",
|
|
117
|
+
"login__email_required": "Please input your email!",
|
|
118
|
+
"login__password_required": "Please input your password!",
|
|
119
|
+
"login__feature__ai_paths": "AI-powered personalized learning paths",
|
|
120
|
+
"login__feature__smart_recommendations": "Smart content recommendations",
|
|
121
|
+
"login__feature__progress_tracking": "Real-time progress tracking",
|
|
122
|
+
"login__email__title": "Enter email",
|
|
123
|
+
"login__password__title": "Enter password",
|
|
124
|
+
"login__forgot_password__title": "Reset password",
|
|
125
|
+
"login__button__title": "Sign in to account",
|
|
126
|
+
"login__with_google__title": "Sign in with Google account",
|
|
127
|
+
"login__create_account__title": "Create new account",
|
|
128
|
+
"page__register__title": "Create Account",
|
|
129
|
+
"page__register__description": "Create Account Page Description",
|
|
130
|
+
"register__title": "Create Account",
|
|
131
|
+
"register__subtitle": "Start your learning journey",
|
|
132
|
+
"register__username": "Username",
|
|
133
|
+
"register__username_required": "Please input your username!",
|
|
134
|
+
"register__email": "Email",
|
|
135
|
+
"register__email_required": "Please input your email!",
|
|
136
|
+
"register__password": "Password",
|
|
137
|
+
"register__password_required": "Please input your password!",
|
|
138
|
+
"register__confirm_password": "Confirm Password",
|
|
139
|
+
"register__confirm_password_required": "Please confirm your password!",
|
|
140
|
+
"register__password_mismatch": "The passwords you entered don't match!",
|
|
141
|
+
"register__button": "Register",
|
|
142
|
+
"register__terms_prefix": "By registering, you agree to our",
|
|
143
|
+
"register__terms_link": "Terms of Service",
|
|
144
|
+
"register__terms_and": "and",
|
|
145
|
+
"register__privacy_link": "Privacy Policy",
|
|
146
|
+
"register__have_account": "Already have an account?",
|
|
147
|
+
"register__login_link": "Sign in",
|
|
148
|
+
"register__feature__personalized": "Personalized Learning Experience",
|
|
149
|
+
"register__feature__support": "Expert Support and Guidance",
|
|
150
|
+
"register__feature__community": "Active Learning Community",
|
|
151
|
+
"register__terms_required": "Please agree to the Terms of Service and Privacy Policy",
|
|
152
|
+
"page__request__title": "Request Examples",
|
|
153
|
+
"page__request__description": "Demonstrate various request examples and usage",
|
|
154
|
+
"request__requestTimeout": "Request Timeout",
|
|
155
|
+
"request__helloResult": "Hello result is",
|
|
156
|
+
"request__helloError": "Hello error is",
|
|
157
|
+
"request__ipInfoResult": "IpInfo result is",
|
|
158
|
+
"request__ipInfo": "IpInfo",
|
|
159
|
+
"request__randomUser": "RandomUser",
|
|
160
|
+
"request__loading": "Loading______",
|
|
161
|
+
"request__randomUserResult": "RandomUser result is",
|
|
162
|
+
"request__randomUserError": "RandomUser error is",
|
|
163
|
+
"request__triggerAbortRequest": "Trigger Abort Request",
|
|
164
|
+
"request__stopAbortRequest": "Stop Abort Request",
|
|
165
|
+
"request__abortRequestResult": "Abort Request Result",
|
|
166
|
+
"request__abortRequestError": "Abort Request Error",
|
|
167
|
+
"page__request__timeout": "Request Timeout",
|
|
168
|
+
"page__request__hello__title": "AI API: Hello",
|
|
169
|
+
"page__request__hello__description": "Functional API using FetchURLPlugin, RequestCommonPlugin, ApiMockPlugin, RequestLogger plugins",
|
|
170
|
+
"page__request__hello__button": "Hello",
|
|
171
|
+
"page__request__ip_info__title": "FeApi: IP Information",
|
|
172
|
+
"page__request__ip_info__description": "RequestScheduler class API using FetchURLPlugin, RequestCommonPlugin, RequestLogger, ApiPickDataPlugin plugins, where ApiPickDataPlugin can flatten return types to data field",
|
|
173
|
+
"page__request__random_user__title": "UserApi: Random User",
|
|
174
|
+
"page__request__random_user__description": "RequestTransaction class API using FetchURLPlugin, RequestCommonPlugin, ApiMockPlugin, FetchAbortPlugin, RequestLogger, ApiCatchPlugin plugins, where FetchAbortPlugin can abort requests, ApiCatchPlugin can unify caught errors to apiCatchResult field",
|
|
175
|
+
"page__request__api_catch__title": "UserApi: Api Catch Result",
|
|
176
|
+
"page__request__abort__title": "UserApi: Abort Request",
|
|
177
|
+
"page__request__trigger_abort": "Trigger Abort Request",
|
|
178
|
+
"page__request__stop_abort": "Stop Abort Request",
|
|
179
|
+
"page__request__trigger_api_catch": "Trigger API Catch Result",
|
|
180
|
+
"page__request__stop_api_catch": "Stop API Catch Result",
|
|
181
|
+
"page__login__content": "Login Page Content",
|
|
182
|
+
"page__login__keywords": "Login Page Keywords"
|
|
183
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
{
|
|
2
|
+
"err__local__no__user__token": "本地未找到 user token",
|
|
3
|
+
"err__global__no__window": "全局未找到 window",
|
|
4
|
+
"err__within__page__provider": "必须在 PageProvider 中使用",
|
|
5
|
+
"err__response__no__token": "响应内容没有 token 值",
|
|
6
|
+
"err__not__found__component": "未找到组件",
|
|
7
|
+
"header__theme__default": "默认主题",
|
|
8
|
+
"header__theme__dark": "暗色主题",
|
|
9
|
+
"header__theme__pink": "粉色主题",
|
|
10
|
+
"auth__logout__dialog__title": "登出",
|
|
11
|
+
"auth__logout__dialog__content": "确定要登出吗?",
|
|
12
|
+
"page__404__title": "404 页面未找到",
|
|
13
|
+
"page__404__description": "404 页面描述",
|
|
14
|
+
"page__500__title": "500 页面错误",
|
|
15
|
+
"page__500__description": "500 页面描述",
|
|
16
|
+
"page__about__title": "关于我们",
|
|
17
|
+
"page__about__description": "了解更多关于我们的项目和团队信息",
|
|
18
|
+
"about__message__test": "这是一条测试消息",
|
|
19
|
+
"about__notification__title": "通知标题",
|
|
20
|
+
"about__notification__description": "这是一条测试通知",
|
|
21
|
+
"about__button__message": "显示 Message",
|
|
22
|
+
"about__button__message2": "静态消息",
|
|
23
|
+
"about__button__notification": "显示 Notification",
|
|
24
|
+
"about__button__notification2": "静态通知",
|
|
25
|
+
"about__tooltip__text": "这是一个提示文本",
|
|
26
|
+
"about__button__tooltip": "悬停显示 Tooltip",
|
|
27
|
+
"about__modal__title": "模态框示例",
|
|
28
|
+
"about__modal__content": "这是一个模态框的内容",
|
|
29
|
+
"about__button__modal": "显示 Modal",
|
|
30
|
+
"about__drawer__title": "抽屉示例",
|
|
31
|
+
"about__drawer__content": "这是一个抽屉的内容",
|
|
32
|
+
"about__button__drawer": "显示 Drawer",
|
|
33
|
+
"about__popover__content": "这是一个气泡卡片",
|
|
34
|
+
"about__popover__title": "Popover 标题",
|
|
35
|
+
"about__button__popover": "显示 Popover",
|
|
36
|
+
"about__popconfirm__title": "确认提示",
|
|
37
|
+
"about__popconfirm__description": "您确定要执行此操作吗?",
|
|
38
|
+
"about__button__popconfirm": "显示 Popconfirm",
|
|
39
|
+
"about__alert__message": "这是一个警告提示",
|
|
40
|
+
"about__ok__text": "确定",
|
|
41
|
+
"about__cancel__text": "取消",
|
|
42
|
+
"page__executor__title": "执行器示例",
|
|
43
|
+
"page__executor__description": "一个强大的任务执行器,支持多种任务类型和状态管理",
|
|
44
|
+
"page__error_identifier__title": "错误标识符",
|
|
45
|
+
"page__executor__main_title": "执行器",
|
|
46
|
+
"page__executor__test_plugin__title": "测试插件",
|
|
47
|
+
"page__executor__task__status__pending": "等待中",
|
|
48
|
+
"page__executor__task__status__running": "运行中",
|
|
49
|
+
"page__executor__task__status__completed": "已完成",
|
|
50
|
+
"page__executor__task__status__failed": "失败",
|
|
51
|
+
"page__executor__task__type__data_sync": "数据同步",
|
|
52
|
+
"page__executor__task__type__report": "报告生成",
|
|
53
|
+
"page__executor__task__type__maintenance": "系统维护",
|
|
54
|
+
"page__executor__task__type__backup": "数据备份",
|
|
55
|
+
"page__executor__task__duration__unit": "分钟",
|
|
56
|
+
"page__executor__task__start": "开始",
|
|
57
|
+
"page__executor__task__stop": "停止",
|
|
58
|
+
"page__executor__task__success": "任务 %{name} 执行成功",
|
|
59
|
+
"page__executor__task__failure": "任务 %{name} 执行失败",
|
|
60
|
+
"page__executor__plugin__test__success": "插件测试成功",
|
|
61
|
+
"page__executor__plugin__test__failure": "插件测试失败",
|
|
62
|
+
"page__executor__custom_task__url_required": "请输入URL",
|
|
63
|
+
"page__executor__custom_task__name": "自定义任务 %{method} %{url}",
|
|
64
|
+
"page__executor__create_task__title": "创建自定义任务",
|
|
65
|
+
"page__executor__create_button": "创建",
|
|
66
|
+
"page__executor__enter_url": "输入URL",
|
|
67
|
+
"page__executor__task_list__title": "任务列表",
|
|
68
|
+
"page__executor__task_stats__total": "总任务数",
|
|
69
|
+
"page__executor__task_stats__running": "运行中",
|
|
70
|
+
"page__executor__task_stats__completed": "已完成",
|
|
71
|
+
"page__executor__task_stats__failed": "失败",
|
|
72
|
+
"page__executor__task_history__title": "执行历史",
|
|
73
|
+
"page__executor__help__title": "需要帮助?",
|
|
74
|
+
"page__executor__help__description": "遇到问题?查看我们的任务执行指南或联系支持团队",
|
|
75
|
+
"page__executor__view_guide": "查看指南",
|
|
76
|
+
"page__executor__contact_support": "联系支持",
|
|
77
|
+
"page__executor__request__timeout": "请求超时时间",
|
|
78
|
+
"page__home__title": "首页",
|
|
79
|
+
"page__home__description": "一个现代前端实用库集合,提供各种实用工具和组件",
|
|
80
|
+
"home__welcome": "欢迎来到主页",
|
|
81
|
+
"home__description": "一个现代前端实用库集合,提供各种实用工具和组件",
|
|
82
|
+
"page__error__identifier__description": "错误标识符的使用和示例",
|
|
83
|
+
"home__explore": "探索",
|
|
84
|
+
"home__get_started__title": "准备开始使用?",
|
|
85
|
+
"home__get_started__description": "加入我们,探索实用工具的力量",
|
|
86
|
+
"home__get_started__button": "立即开始",
|
|
87
|
+
"page__error__identifier__main_title": "错误标识符",
|
|
88
|
+
"page__error__identifier__source_description": "来自 '@config/Identifier/error' 的标识符",
|
|
89
|
+
"page__error__identifier__help__title": "需要帮助?",
|
|
90
|
+
"page__error__identifier__help__description": "如果您在使用错误标识符时遇到问题,请联系我们的支持团队",
|
|
91
|
+
"page__error__identifier__contact_support": "联系支持",
|
|
92
|
+
"page__jsonstorage__title": "JSONStorage 页面",
|
|
93
|
+
"page__jsonstorage__description": "使用 JSONStorage 进行数据存储和管理",
|
|
94
|
+
"page__jsonstorage__main_title": "JSONStorage 演示",
|
|
95
|
+
"page__jsonstorage__permanent_title": "永久存储测试",
|
|
96
|
+
"page__jsonstorage__expire_title": "过期时间测试",
|
|
97
|
+
"page__jsonstorage__timeout_title": "请求超时时间设置",
|
|
98
|
+
"page__jsonstorage__format_title": "测试 key: ${key}, 随机值范围: ${min}~${max}",
|
|
99
|
+
"page__jsonstorage__set_random": "设置随机值",
|
|
100
|
+
"page__jsonstorage__current_value": "当前值",
|
|
101
|
+
"page__jsonstorage__set_expire": "设置随机值(带过期时间)",
|
|
102
|
+
"page__jsonstorage__ms": "毫秒",
|
|
103
|
+
"page__login__title": "登录",
|
|
104
|
+
"page__login__description": "登录页面描述",
|
|
105
|
+
"login__title": "登录",
|
|
106
|
+
"login__email": "邮箱",
|
|
107
|
+
"login__username": "用户名",
|
|
108
|
+
"login__password": "密码",
|
|
109
|
+
"login__login": "登录",
|
|
110
|
+
"login__welcome": "欢迎来到未来学习",
|
|
111
|
+
"login__subtitle": "解锁个性化 AI 驱动的学习体验,加速您的知识旅程。",
|
|
112
|
+
"login__forgot_password": "忘记密码?",
|
|
113
|
+
"login__continue_with": "或继续使用",
|
|
114
|
+
"login__with_google": "使用 Google 登录",
|
|
115
|
+
"login__no_account": "还没有账号?",
|
|
116
|
+
"login__create_account": "在此创建",
|
|
117
|
+
"login__email_required": "请输入您的邮箱!",
|
|
118
|
+
"login__password_required": "请输入您的密码!",
|
|
119
|
+
"login__feature__ai_paths": "AI驱动的个性化学习路径",
|
|
120
|
+
"login__feature__smart_recommendations": "智能内容推荐",
|
|
121
|
+
"login__feature__progress_tracking": "实时进度追踪",
|
|
122
|
+
"login__email__title": "输入邮箱",
|
|
123
|
+
"login__password__title": "输入密码",
|
|
124
|
+
"login__forgot_password__title": "重置密码",
|
|
125
|
+
"login__button__title": "登录账号",
|
|
126
|
+
"login__with_google__title": "使用Google账号登录",
|
|
127
|
+
"login__create_account__title": "创建新账号",
|
|
128
|
+
"page__register__title": "创建账号",
|
|
129
|
+
"page__register__description": "创建账号页面描述",
|
|
130
|
+
"register__title": "创建账号",
|
|
131
|
+
"register__subtitle": "开始您的学习之旅",
|
|
132
|
+
"register__username": "用户名",
|
|
133
|
+
"register__username_required": "请输入用户名!",
|
|
134
|
+
"register__email": "邮箱",
|
|
135
|
+
"register__email_required": "请输入邮箱!",
|
|
136
|
+
"register__password": "密码",
|
|
137
|
+
"register__password_required": "请输入密码!",
|
|
138
|
+
"register__confirm_password": "确认密码",
|
|
139
|
+
"register__confirm_password_required": "请确认密码!",
|
|
140
|
+
"register__password_mismatch": "两次输入的密码不匹配!",
|
|
141
|
+
"register__button": "注册",
|
|
142
|
+
"register__terms_prefix": "注册即表示您同意我们的",
|
|
143
|
+
"register__terms_link": "服务条款",
|
|
144
|
+
"register__terms_and": "和",
|
|
145
|
+
"register__privacy_link": "隐私政策",
|
|
146
|
+
"register__have_account": "已有账号?",
|
|
147
|
+
"register__login_link": "登录",
|
|
148
|
+
"register__feature__personalized": "个性化学习体验",
|
|
149
|
+
"register__feature__support": "专家支持和指导",
|
|
150
|
+
"register__feature__community": "活跃的学习社区",
|
|
151
|
+
"register__terms_required": "请同意服务条款和隐私政策",
|
|
152
|
+
"page__request__title": "请求示例",
|
|
153
|
+
"page__request__description": "展示各种请求示例和用法",
|
|
154
|
+
"request__requestTimeout": "请求超时",
|
|
155
|
+
"request__helloResult": "Hello 结果是",
|
|
156
|
+
"request__helloError": "Hello 错误是",
|
|
157
|
+
"request__ipInfoResult": "IpInfo 结果是",
|
|
158
|
+
"request__ipInfo": "IpInfo",
|
|
159
|
+
"request__randomUser": "随机用户",
|
|
160
|
+
"request__loading": "加载中______",
|
|
161
|
+
"request__randomUserResult": "随机用户 结果是",
|
|
162
|
+
"request__randomUserError": "随机用户 错误是",
|
|
163
|
+
"request__triggerAbortRequest": "触发中止请求",
|
|
164
|
+
"request__stopAbortRequest": "停止中止请求",
|
|
165
|
+
"request__abortRequestResult": "中止请求 结果是",
|
|
166
|
+
"request__abortRequestError": "中止请求 错误是",
|
|
167
|
+
"page__request__timeout": "请求超时时间",
|
|
168
|
+
"page__request__hello__title": "AI API: Hello",
|
|
169
|
+
"page__request__hello__description": "函数式 api, 使用了 FetchURLPlugin, RequestCommonPlugin, ApiMockPlugin, RequestLogger 插件",
|
|
170
|
+
"page__request__hello__button": "Hello",
|
|
171
|
+
"page__request__ip_info__title": "FeApi: IP Information",
|
|
172
|
+
"page__request__ip_info__description": "RequestScheduler 类式 api, 使用了 FetchURLPlugin, RequestCommonPlugin, RequestLogger, ApiPickDataPlugin 插件, 其中 ApiPickDataPlugin 插件可以将返回类型统一扁平到 data 字段",
|
|
173
|
+
"page__request__random_user__title": "UserApi: Random User",
|
|
174
|
+
"page__request__random_user__description": "RequestTransaction 类式 api, 使用了 FetchURLPlugin, RequestCommonPlugin, ApiMockPlugin, FetchAbortPlugin, RequestLogger, ApiCatchPlugin 插件, 其中 FetchAbortPlugin 可以中止请求, ApiCatchPlugin 可以将捕获的错误统一到 apiCatchResult 字段",
|
|
175
|
+
"page__request__api_catch__title": "UserApi: Api Catch Result",
|
|
176
|
+
"page__request__abort__title": "UserApi: Abort Request",
|
|
177
|
+
"page__request__trigger_abort": "触发中止请求",
|
|
178
|
+
"page__request__stop_abort": "停止中止请求",
|
|
179
|
+
"page__request__trigger_api_catch": "触发 API 捕获结果",
|
|
180
|
+
"page__request__stop_api_catch": "停止 API 捕获结果",
|
|
181
|
+
"page__login__content": "登录页面内容",
|
|
182
|
+
"page__login__keywords": "登录页面关键词"
|
|
183
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { notFound } from 'next/navigation';
|
|
2
|
+
import { NextIntlClientProvider } from 'next-intl';
|
|
3
|
+
import { getMessages } from 'next-intl/server';
|
|
4
|
+
import { i18nConfig } from '@config/i18n';
|
|
5
|
+
import { themeConfig } from '@config/theme';
|
|
6
|
+
import { BaseHeader } from '@/uikit/components/BaseHeader';
|
|
7
|
+
import { ComboProvider } from '@/uikit/components/ComboProvider';
|
|
8
|
+
import type { LocaleType } from '@config/i18n';
|
|
9
|
+
import '@/styles/css/index.css';
|
|
10
|
+
|
|
11
|
+
export default async function RootLayout({
|
|
12
|
+
children,
|
|
13
|
+
params
|
|
14
|
+
}: {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
params: Promise<{ locale: string }>;
|
|
17
|
+
}) {
|
|
18
|
+
// Extract the locale from the route params (async for Next.js App Router)
|
|
19
|
+
const { locale } = await params;
|
|
20
|
+
|
|
21
|
+
// Validate that the requested locale is supported
|
|
22
|
+
if (!i18nConfig.supportedLngs.includes(locale as LocaleType)) {
|
|
23
|
+
notFound();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Load the translation messages for the selected locale
|
|
27
|
+
const messages = await getMessages({ locale });
|
|
28
|
+
|
|
29
|
+
// TODO: suppressHydrationWarning 暂时解决 hydration 问题
|
|
30
|
+
return (
|
|
31
|
+
<html data-testid="RootLayout" lang={locale} suppressHydrationWarning>
|
|
32
|
+
<body>
|
|
33
|
+
<NextIntlClientProvider messages={messages}>
|
|
34
|
+
<ComboProvider themeConfig={themeConfig}>
|
|
35
|
+
<div className="flex flex-col min-h-screen">
|
|
36
|
+
<BaseHeader />
|
|
37
|
+
<div className="flex flex-col">{children}</div>
|
|
38
|
+
</div>
|
|
39
|
+
</ComboProvider>
|
|
40
|
+
</NextIntlClientProvider>
|
|
41
|
+
</body>
|
|
42
|
+
</html>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface FeatureItemProps {
|
|
2
|
+
icon: string;
|
|
3
|
+
text: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function FeatureItem({ icon, text }: FeatureItemProps) {
|
|
7
|
+
return (
|
|
8
|
+
<div data-testid="FeatureItem" className="flex items-start gap-4">
|
|
9
|
+
<div className="text-2xl">{icon}</div>
|
|
10
|
+
<p className="text-text-secondary">{text}</p>
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { UserOutlined, LockOutlined, GoogleOutlined } from '@ant-design/icons';
|
|
4
|
+
import { Form, Input, Button } from 'antd';
|
|
5
|
+
import { useState } from 'react';
|
|
6
|
+
import { UserService } from '@/base/services/UserService';
|
|
7
|
+
import { IOC } from '@/core/IOC';
|
|
8
|
+
import { LocaleLink } from '@/uikit/components/LocaleLink';
|
|
9
|
+
import type { LoginI18nInterface } from '@config/i18n/loginI18n';
|
|
10
|
+
|
|
11
|
+
interface LoginFormData {
|
|
12
|
+
email: string;
|
|
13
|
+
password: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function LoginForm(props: { tt: LoginI18nInterface }) {
|
|
17
|
+
const { tt } = props;
|
|
18
|
+
const userService = IOC(UserService);
|
|
19
|
+
const [loading, setLoading] = useState(false);
|
|
20
|
+
|
|
21
|
+
const handleLogin = async (values: LoginFormData) => {
|
|
22
|
+
try {
|
|
23
|
+
setLoading(true);
|
|
24
|
+
await userService.login({
|
|
25
|
+
email: values.email,
|
|
26
|
+
password: values.password
|
|
27
|
+
});
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error('Login error:', error);
|
|
30
|
+
} finally {
|
|
31
|
+
setLoading(false);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Form
|
|
37
|
+
data-testid="LoginForm"
|
|
38
|
+
name="login"
|
|
39
|
+
onFinish={handleLogin}
|
|
40
|
+
layout="vertical"
|
|
41
|
+
className="space-y-4"
|
|
42
|
+
>
|
|
43
|
+
<Form.Item
|
|
44
|
+
name="email"
|
|
45
|
+
rules={[{ required: true, message: tt.emailRequired }]}
|
|
46
|
+
>
|
|
47
|
+
<Input
|
|
48
|
+
prefix={<UserOutlined className="text-text-tertiary" />}
|
|
49
|
+
placeholder={tt.email}
|
|
50
|
+
title={tt.emailTitle}
|
|
51
|
+
className="h-12 text-base bg-secondary border-border"
|
|
52
|
+
autoComplete="off"
|
|
53
|
+
/>
|
|
54
|
+
</Form.Item>
|
|
55
|
+
|
|
56
|
+
<Form.Item
|
|
57
|
+
name="password"
|
|
58
|
+
rules={[{ required: true, message: tt.passwordRequired }]}
|
|
59
|
+
>
|
|
60
|
+
<Input.Password
|
|
61
|
+
prefix={<LockOutlined />}
|
|
62
|
+
placeholder={tt.password}
|
|
63
|
+
title={tt.passwordTitle}
|
|
64
|
+
className="h-12 text-base"
|
|
65
|
+
autoComplete="new-password"
|
|
66
|
+
/>
|
|
67
|
+
</Form.Item>
|
|
68
|
+
|
|
69
|
+
<div className="flex justify-end">
|
|
70
|
+
<LocaleLink
|
|
71
|
+
href="#"
|
|
72
|
+
className="text-brand hover:text-brand-hover"
|
|
73
|
+
title={tt.forgotPasswordTitle}
|
|
74
|
+
>
|
|
75
|
+
{tt.forgotPassword}
|
|
76
|
+
</LocaleLink>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<Form.Item>
|
|
80
|
+
<Button
|
|
81
|
+
type="primary"
|
|
82
|
+
htmlType="submit"
|
|
83
|
+
loading={loading}
|
|
84
|
+
title={tt.buttonTitle}
|
|
85
|
+
className="w-full h-12 text-base"
|
|
86
|
+
>
|
|
87
|
+
{tt.button}
|
|
88
|
+
</Button>
|
|
89
|
+
</Form.Item>
|
|
90
|
+
|
|
91
|
+
<div className="text-center text-text-tertiary my-4">
|
|
92
|
+
{tt.continueWith}
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<Button
|
|
96
|
+
icon={<GoogleOutlined />}
|
|
97
|
+
className="w-full h-12 text-base"
|
|
98
|
+
title={tt.withGoogleTitle}
|
|
99
|
+
>
|
|
100
|
+
{tt.withGoogle}
|
|
101
|
+
</Button>
|
|
102
|
+
|
|
103
|
+
<div className="text-center mt-6">
|
|
104
|
+
<span className="text-text-tertiary">{tt.noAccount} </span>
|
|
105
|
+
<LocaleLink
|
|
106
|
+
href="/register"
|
|
107
|
+
className="text-brand hover:text-brand-hover"
|
|
108
|
+
title={tt.createAccountTitle}
|
|
109
|
+
>
|
|
110
|
+
{tt.createAccount}
|
|
111
|
+
</LocaleLink>
|
|
112
|
+
</div>
|
|
113
|
+
</Form>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { loginI18n, i18nConfig } from '@config/i18n';
|
|
2
|
+
import { getServerI18n } from '@/server/getServerI18n';
|
|
3
|
+
import { useI18nInterface } from '@/uikit/hook/useI18nInterface';
|
|
4
|
+
import { FeatureItem } from './FeatureItem';
|
|
5
|
+
import { LoginForm } from './LoginForm';
|
|
6
|
+
import type { Metadata } from 'next';
|
|
7
|
+
|
|
8
|
+
// Generate static params for all supported locales (used for SSG)
|
|
9
|
+
export async function generateStaticParams() {
|
|
10
|
+
// Return one entry for each supported locale
|
|
11
|
+
return i18nConfig.supportedLngs.map((locale) => ({ locale }));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Allow Next.js to statically generate this page if possible (default behavior)
|
|
15
|
+
export const dynamic = 'auto'; // Enable static generation when possible, fallback to dynamic if needed
|
|
16
|
+
|
|
17
|
+
// Optional: Use revalidate if you want ISR (Incremental Static Regeneration)
|
|
18
|
+
// export const revalidate = 3600; // Rebuild every hour (optional)
|
|
19
|
+
|
|
20
|
+
// Generate localized SEO metadata per locale (Next.js 15+ best practice)
|
|
21
|
+
export async function generateMetadata({
|
|
22
|
+
params
|
|
23
|
+
}: {
|
|
24
|
+
params: Promise<{ locale: string }>;
|
|
25
|
+
}): Promise<Metadata> {
|
|
26
|
+
const { locale } = await params;
|
|
27
|
+
|
|
28
|
+
const tt = await getServerI18n({
|
|
29
|
+
locale,
|
|
30
|
+
i18nInterface: loginI18n
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Return localized SEO metadata
|
|
34
|
+
return tt;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default function LoginPage() {
|
|
38
|
+
const tt = useI18nInterface(loginI18n);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
data-testid="LoginPage"
|
|
43
|
+
className="flex text-xs1 bg-primary min-h-screen"
|
|
44
|
+
>
|
|
45
|
+
{/* Left side - Brand section */}
|
|
46
|
+
<div className="hidden lg:flex bg-secondary lg:w-1/2 p-12 flex-col">
|
|
47
|
+
<div className="flex items-center gap-3 mb-12">
|
|
48
|
+
<div className="w-10 h-10 bg-brand rounded-lg"></div>
|
|
49
|
+
<span className="text-2xl font-semibold text-text">
|
|
50
|
+
{'AppConfig.appName'}
|
|
51
|
+
</span>
|
|
52
|
+
</div>
|
|
53
|
+
<h1 className="text-4xl font-bold text-text mb-4">{tt.welcome}</h1>
|
|
54
|
+
<p className="text-text-secondary text-lg mb-8">{tt.subtitle}</p>
|
|
55
|
+
<div className="space-y-4">
|
|
56
|
+
<FeatureItem icon="🎯" text={tt.feature_ai_paths} />
|
|
57
|
+
<FeatureItem icon="🎯" text={tt.feature_smart_recommendations} />
|
|
58
|
+
<FeatureItem icon="📊" text={tt.feature_progress_tracking} />
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
{/* Right side - Login form */}
|
|
63
|
+
<div className="w-full lg:w-1/2 p-8 sm:p-12 flex items-center justify-center">
|
|
64
|
+
<div className="w-full max-w-[420px]">
|
|
65
|
+
<h2 className="text-2xl font-semibold mb-2 text-text">{tt.title}</h2>
|
|
66
|
+
<p className="text-text-secondary mb-8">{tt.subtitle}</p>
|
|
67
|
+
|
|
68
|
+
<LoginForm tt={tt} />
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// import { useTranslations } from 'next-intl'; // Client-side translation hook
|
|
2
|
+
import { identity as t } from 'lodash';
|
|
3
|
+
import { Link } from '@/i18n/routing'; // i18n-aware Link component
|
|
4
|
+
|
|
5
|
+
export default function NotFound() {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-testid="NotFound"
|
|
9
|
+
className="space-y-6 py-24 flex flex-col items-center"
|
|
10
|
+
>
|
|
11
|
+
{/* Large translated 404 headline */}
|
|
12
|
+
<h1 className="text-4xl font-bold text-center">{'title'}</h1>
|
|
13
|
+
{/* Description text, translated */}
|
|
14
|
+
<p className="text-lg text-gray-600 text-center">{t('description')}</p>
|
|
15
|
+
{/* Link back to home page, translated label */}
|
|
16
|
+
<Link
|
|
17
|
+
href="/"
|
|
18
|
+
className="inline-block rounded-xl bg-gray-900 text-white font-medium px-6 py-3 hover:bg-gray-800 transition"
|
|
19
|
+
>
|
|
20
|
+
{t('backToHome')}
|
|
21
|
+
</Link>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|