generator-kodly-react-app 1.0.7 → 1.0.11
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/generators/app/index.js +63 -18
- package/generators/app/templates/.env.dev +4 -0
- package/generators/app/templates/.env.sandbox +4 -0
- package/generators/app/templates/STRUCTURE.md +661 -0
- package/generators/app/templates/components.json +22 -0
- package/generators/app/templates/gitignore.template +78 -2
- package/generators/app/templates/index.html +14 -6
- package/generators/app/templates/openapi-ts.config.ts +29 -0
- package/generators/app/templates/package.json +40 -26
- package/generators/app/templates/public/favicon.svg +4 -0
- package/generators/app/templates/src/app.tsx +8 -8
- package/generators/app/templates/src/components/layout/language-switcher.tsx +40 -0
- package/generators/app/templates/src/components/layout/theme-switcher.tsx +37 -0
- package/generators/app/templates/src/components/theme/theme-provider.tsx +22 -28
- package/generators/app/templates/src/components/ui/button.tsx +34 -32
- package/generators/app/templates/src/components/ui/card.tsx +76 -0
- package/generators/app/templates/src/components/ui/field.tsx +242 -0
- package/generators/app/templates/src/components/ui/form.tsx +129 -0
- package/generators/app/templates/src/components/ui/input-group.tsx +170 -0
- package/generators/app/templates/src/components/ui/input.tsx +19 -21
- package/generators/app/templates/src/components/ui/label.tsx +24 -0
- package/generators/app/templates/src/components/ui/select.tsx +184 -0
- package/generators/app/templates/src/components/ui/separator.tsx +31 -0
- package/generators/app/templates/src/components/ui/textarea.tsx +22 -0
- package/generators/app/templates/src/index.css +83 -26
- package/generators/app/templates/src/lib/i18n.ts +31 -16
- package/generators/app/templates/src/lib/routes.ts +14 -0
- package/generators/app/templates/src/lib/utils.ts +3 -4
- package/generators/app/templates/src/locales/en/common.json +5 -0
- package/generators/app/templates/src/locales/en/theme.json +5 -0
- package/generators/app/templates/src/locales/index.ts +31 -0
- package/generators/app/templates/src/locales/ja/common.json +5 -0
- package/generators/app/templates/src/locales/ja/theme.json +6 -0
- package/generators/app/templates/src/main.tsx +19 -15
- package/generators/app/templates/src/modules/app/layouts/app-layout.tsx +37 -0
- package/generators/app/templates/src/modules/app/locales/app-en.json +9 -0
- package/generators/app/templates/src/modules/app/locales/app-ja.json +9 -0
- package/generators/app/templates/src/modules/auth/components/forgot-password-form.tsx +74 -0
- package/generators/app/templates/src/modules/auth/components/login-form.tsx +95 -0
- package/generators/app/templates/src/modules/auth/components/reset-password-form.tsx +112 -0
- package/generators/app/templates/src/modules/auth/components/signup-form.tsx +92 -0
- package/generators/app/templates/src/modules/auth/{auth-context.tsx → contexts/auth-context.tsx} +3 -3
- package/generators/app/templates/src/modules/auth/hooks/use-auth-hook.ts +180 -0
- package/generators/app/templates/src/modules/auth/layouts/auth-layout.tsx +28 -0
- package/generators/app/templates/src/modules/auth/locales/auth-en.json +105 -0
- package/generators/app/templates/src/modules/auth/locales/auth-ja.json +105 -0
- package/generators/app/templates/src/modules/auth/schemas/form-schemas.ts +26 -0
- package/generators/app/templates/src/modules/landing/components/auth-hero.tsx +34 -0
- package/generators/app/templates/src/modules/landing/components/welcome-hero.tsx +24 -0
- package/generators/app/templates/src/modules/landing/landing-page-layout.tsx +24 -0
- package/generators/app/templates/src/modules/landing/landing-page.tsx +17 -0
- package/generators/app/templates/src/modules/landing/layouts/landing-page-layout.tsx +24 -0
- package/generators/app/templates/src/modules/landing/locales/landing-en.json +12 -0
- package/generators/app/templates/src/modules/landing/locales/landing-ja.json +11 -0
- package/generators/app/templates/src/openapi-client-config.ts +6 -0
- package/generators/app/templates/src/routeTree.gen.ts +268 -3
- package/generators/app/templates/src/router.tsx +2 -2
- package/generators/app/templates/src/routes/__root.tsx +2 -2
- package/generators/app/templates/src/routes/_landing/index.tsx +10 -0
- package/generators/app/templates/src/routes/_landing/route.tsx +14 -0
- package/generators/app/templates/src/routes/app/index.tsx +4 -21
- package/generators/app/templates/src/routes/app/route.tsx +12 -8
- package/generators/app/templates/src/routes/auth/forgot-password.tsx +10 -0
- package/generators/app/templates/src/routes/auth/login.tsx +6 -7
- package/generators/app/templates/src/routes/auth/reset-password.tsx +15 -0
- package/generators/app/templates/src/routes/auth/route.tsx +23 -6
- package/generators/app/templates/src/routes/auth/signup.tsx +11 -0
- package/generators/app/templates/src/sdk/@tanstack/react-query.gen.ts +91 -0
- package/generators/app/templates/src/sdk/client/client.gen.ts +167 -0
- package/generators/app/templates/src/sdk/client/index.ts +23 -0
- package/generators/app/templates/src/sdk/client/types.gen.ts +197 -0
- package/generators/app/templates/src/sdk/client/utils.gen.ts +213 -0
- package/generators/app/templates/src/sdk/client.gen.ts +18 -0
- package/generators/app/templates/src/sdk/core/auth.gen.ts +42 -0
- package/generators/app/templates/src/sdk/core/bodySerializer.gen.ts +100 -0
- package/generators/app/templates/src/sdk/core/params.gen.ts +176 -0
- package/generators/app/templates/src/sdk/core/pathSerializer.gen.ts +181 -0
- package/generators/app/templates/src/sdk/core/queryKeySerializer.gen.ts +136 -0
- package/generators/app/templates/src/sdk/core/serverSentEvents.gen.ts +266 -0
- package/generators/app/templates/src/sdk/core/types.gen.ts +118 -0
- package/generators/app/templates/src/sdk/core/utils.gen.ts +143 -0
- package/generators/app/templates/src/sdk/index.ts +4 -0
- package/generators/app/templates/src/sdk/schemas.gen.ts +195 -0
- package/generators/app/templates/src/sdk/sdk.gen.ts +80 -0
- package/generators/app/templates/src/sdk/types.gen.ts +158 -0
- package/generators/app/templates/src/sdk/zod.gen.ts +148 -0
- package/generators/app/templates/src/vite-env.d.ts +2 -1
- package/generators/app/templates/tsconfig.json +1 -1
- package/generators/app/templates/vite.config.js +35 -21
- package/generators/constants.js +1 -1
- package/package.json +3 -2
- package/generators/app/templates/.env.example +0 -5
- package/generators/app/templates/README.md +0 -62
- package/generators/app/templates/src/lib/api/client.ts +0 -35
- package/generators/app/templates/src/locales/en.json +0 -18
- package/generators/app/templates/src/modules/auth/auth-types.ts +0 -24
- package/generators/app/templates/src/modules/auth/login/login-form.tsx +0 -49
- package/generators/app/templates/src/modules/auth/login/login-page.tsx +0 -12
- package/generators/app/templates/src/modules/auth/use-auth-hook.ts +0 -88
- package/generators/app/templates/src/routes/index.tsx +0 -12
- package/generators/app/templates/types.d.ts +0 -3
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "Login",
|
|
4
|
+
"email": "Email",
|
|
5
|
+
"emailPlaceholder": "Enter your email",
|
|
6
|
+
"password": "Password",
|
|
7
|
+
"passwordPlaceholder": "Enter your password",
|
|
8
|
+
"submit": "Sign In",
|
|
9
|
+
"forgotPasswordLink": "Forgot password?",
|
|
10
|
+
"signupLink": "Don't have an account? Sign up",
|
|
11
|
+
"validation": {
|
|
12
|
+
"email": {
|
|
13
|
+
"required": "Email is required",
|
|
14
|
+
"invalid": "Please enter a valid email address",
|
|
15
|
+
"minLength": "Email must be at least {{minLength}} characters",
|
|
16
|
+
"maxLength": "Email must be at most {{maxLength}} characters"
|
|
17
|
+
},
|
|
18
|
+
"password": {
|
|
19
|
+
"required": "Password is required",
|
|
20
|
+
"minLength": "Password must be at least {{minLength}} characters",
|
|
21
|
+
"maxLength": "Password must be at most {{maxLength}} characters"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"signup": {
|
|
26
|
+
"title": "Sign Up",
|
|
27
|
+
"email": "Email",
|
|
28
|
+
"emailPlaceholder": "Enter your email",
|
|
29
|
+
"password": "Password",
|
|
30
|
+
"passwordPlaceholder": "Enter your password",
|
|
31
|
+
"name": "Name",
|
|
32
|
+
"namePlaceholder": "Enter your name (optional)",
|
|
33
|
+
"submit": "Sign Up",
|
|
34
|
+
"loginLink": "Already have an account? Sign in",
|
|
35
|
+
"validation": {
|
|
36
|
+
"email": {
|
|
37
|
+
"required": "Email is required",
|
|
38
|
+
"invalid": "Please enter a valid email address",
|
|
39
|
+
"minLength": "Email must be at least {{minLength}} characters",
|
|
40
|
+
"maxLength": "Email must be at most {{maxLength}} characters"
|
|
41
|
+
},
|
|
42
|
+
"password": {
|
|
43
|
+
"required": "Password is required",
|
|
44
|
+
"minLength": "Password must be at least {{minLength}} characters",
|
|
45
|
+
"maxLength": "Password must be at most {{maxLength}} characters"
|
|
46
|
+
},
|
|
47
|
+
"name": {
|
|
48
|
+
"minLength": "Name must be at least {{minLength}} characters",
|
|
49
|
+
"maxLength": "Name must be at most {{maxLength}} characters"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"forgotPassword": {
|
|
54
|
+
"title": "Forgot Password",
|
|
55
|
+
"email": "Email",
|
|
56
|
+
"emailPlaceholder": "Enter your email",
|
|
57
|
+
"submit": "Send OTP",
|
|
58
|
+
"loginLink": "Back to sign in",
|
|
59
|
+
"validation": {
|
|
60
|
+
"email": {
|
|
61
|
+
"required": "Email is required",
|
|
62
|
+
"invalid": "Please enter a valid email address",
|
|
63
|
+
"minLength": "Email must be at least {{minLength}} characters",
|
|
64
|
+
"maxLength": "Email must be at most {{maxLength}} characters"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"resetPassword": {
|
|
69
|
+
"title": "Reset Password",
|
|
70
|
+
"email": "Email",
|
|
71
|
+
"emailPlaceholder": "Enter your email",
|
|
72
|
+
"otp": "OTP",
|
|
73
|
+
"otpPlaceholder": "Enter the OTP code",
|
|
74
|
+
"password": "Password",
|
|
75
|
+
"passwordPlaceholder": "Enter your new password",
|
|
76
|
+
"submit": "Reset Password",
|
|
77
|
+
"validation": {
|
|
78
|
+
"email": {
|
|
79
|
+
"required": "Email is required",
|
|
80
|
+
"invalid": "Please enter a valid email address",
|
|
81
|
+
"minLength": "Email must be at least {{minLength}} characters",
|
|
82
|
+
"maxLength": "Email must be at most {{maxLength}} characters"
|
|
83
|
+
},
|
|
84
|
+
"otp": {
|
|
85
|
+
"required": "OTP is required",
|
|
86
|
+
"minLength": "OTP must be at least {{minLength}} characters",
|
|
87
|
+
"maxLength": "OTP must be at most {{maxLength}} characters"
|
|
88
|
+
},
|
|
89
|
+
"password": {
|
|
90
|
+
"required": "Password is required",
|
|
91
|
+
"minLength": "Password must be at least {{minLength}} characters",
|
|
92
|
+
"maxLength": "Password must be at most {{maxLength}} characters"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"messages": {
|
|
97
|
+
"loginFailed": "Login failed",
|
|
98
|
+
"signupFailed": "Signup failed",
|
|
99
|
+
"otpSentSuccess": "OTP sent successfully",
|
|
100
|
+
"otpSendFailed": "Failed to send OTP",
|
|
101
|
+
"passwordResetSuccess": "Password reset successfully",
|
|
102
|
+
"passwordResetFailed": "Failed to reset password"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"title": "ログイン",
|
|
4
|
+
"email": "メールアドレス",
|
|
5
|
+
"emailPlaceholder": "メールアドレスを入力してください",
|
|
6
|
+
"password": "パスワード",
|
|
7
|
+
"passwordPlaceholder": "パスワードを入力してください",
|
|
8
|
+
"submit": "サインイン",
|
|
9
|
+
"forgotPasswordLink": "パスワードをお忘れですか?",
|
|
10
|
+
"signupLink": "アカウントをお持ちでない方は、サインアップしてください",
|
|
11
|
+
"validation": {
|
|
12
|
+
"email": {
|
|
13
|
+
"required": "メールアドレスは必須です",
|
|
14
|
+
"invalid": "有効なメールアドレスを入力してください",
|
|
15
|
+
"minLength": "メールアドレスは少なくとも{{minLength}}文字である必要があります",
|
|
16
|
+
"maxLength": "メールアドレスは最大{{maxLength}}文字である必要があります"
|
|
17
|
+
},
|
|
18
|
+
"password": {
|
|
19
|
+
"required": "パスワードは必須です",
|
|
20
|
+
"minLength": "パスワードは少なくとも{{minLength}}文字である必要があります",
|
|
21
|
+
"maxLength": "パスワードは最大{{maxLength}}文字である必要があります"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"signup": {
|
|
26
|
+
"title": "サインアップ",
|
|
27
|
+
"email": "メールアドレス",
|
|
28
|
+
"emailPlaceholder": "メールアドレスを入力してください",
|
|
29
|
+
"password": "パスワード",
|
|
30
|
+
"passwordPlaceholder": "パスワードを入力してください",
|
|
31
|
+
"name": "名前",
|
|
32
|
+
"namePlaceholder": "名前を入力してください(任意)",
|
|
33
|
+
"submit": "サインアップ",
|
|
34
|
+
"loginLink": "すでにアカウントをお持ちの方は、サインインしてください",
|
|
35
|
+
"validation": {
|
|
36
|
+
"email": {
|
|
37
|
+
"required": "メールアドレスは必須です",
|
|
38
|
+
"invalid": "有効なメールアドレスを入力してください",
|
|
39
|
+
"minLength": "メールアドレスは少なくとも{{minLength}}文字である必要があります",
|
|
40
|
+
"maxLength": "メールアドレスは最大{{maxLength}}文字である必要があります"
|
|
41
|
+
},
|
|
42
|
+
"password": {
|
|
43
|
+
"required": "パスワードは必須です",
|
|
44
|
+
"minLength": "パスワードは少なくとも{{minLength}}文字である必要があります",
|
|
45
|
+
"maxLength": "パスワードは最大{{maxLength}}文字である必要があります"
|
|
46
|
+
},
|
|
47
|
+
"name": {
|
|
48
|
+
"minLength": "名前は少なくとも{{minLength}}文字である必要があります",
|
|
49
|
+
"maxLength": "名前は最大{{maxLength}}文字である必要があります"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"forgotPassword": {
|
|
54
|
+
"title": "パスワードを忘れた場合",
|
|
55
|
+
"email": "メールアドレス",
|
|
56
|
+
"emailPlaceholder": "メールアドレスを入力してください",
|
|
57
|
+
"submit": "OTPを送信",
|
|
58
|
+
"loginLink": "サインインに戻る",
|
|
59
|
+
"validation": {
|
|
60
|
+
"email": {
|
|
61
|
+
"required": "メールアドレスは必須です",
|
|
62
|
+
"invalid": "有効なメールアドレスを入力してください",
|
|
63
|
+
"minLength": "メールアドレスは少なくとも{{minLength}}文字である必要があります",
|
|
64
|
+
"maxLength": "メールアドレスは最大{{maxLength}}文字である必要があります"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"resetPassword": {
|
|
69
|
+
"title": "パスワードをリセット",
|
|
70
|
+
"email": "メールアドレス",
|
|
71
|
+
"emailPlaceholder": "メールアドレスを入力してください",
|
|
72
|
+
"otp": "OTP",
|
|
73
|
+
"otpPlaceholder": "OTPコードを入力してください",
|
|
74
|
+
"password": "パスワード",
|
|
75
|
+
"passwordPlaceholder": "新しいパスワードを入力してください",
|
|
76
|
+
"submit": "パスワードをリセット",
|
|
77
|
+
"validation": {
|
|
78
|
+
"email": {
|
|
79
|
+
"required": "メールアドレスは必須です",
|
|
80
|
+
"invalid": "有効なメールアドレスを入力してください",
|
|
81
|
+
"minLength": "メールアドレスは少なくとも{{minLength}}文字である必要があります",
|
|
82
|
+
"maxLength": "メールアドレスは最大{{maxLength}}文字である必要があります"
|
|
83
|
+
},
|
|
84
|
+
"otp": {
|
|
85
|
+
"required": "OTPは必須です",
|
|
86
|
+
"minLength": "OTPは少なくとも{{minLength}}文字である必要があります",
|
|
87
|
+
"maxLength": "OTPは最大{{maxLength}}文字である必要があります"
|
|
88
|
+
},
|
|
89
|
+
"password": {
|
|
90
|
+
"required": "パスワードは必須です",
|
|
91
|
+
"minLength": "パスワードは少なくとも{{minLength}}文字である必要があります",
|
|
92
|
+
"maxLength": "パスワードは最大{{maxLength}}文字である必要があります"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"messages": {
|
|
97
|
+
"loginFailed": "ログインに失敗しました",
|
|
98
|
+
"signupFailed": "サインアップに失敗しました",
|
|
99
|
+
"otpSentSuccess": "OTPが正常に送信されました",
|
|
100
|
+
"otpSendFailed": "OTPの送信に失敗しました",
|
|
101
|
+
"passwordResetSuccess": "パスワードが正常にリセットされました",
|
|
102
|
+
"passwordResetFailed": "パスワードのリセットに失敗しました"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import { zUserLoginDto, zUserSignupDto, zUserResetPasswordDto } from '@/sdk/zod.gen';
|
|
3
|
+
|
|
4
|
+
type LoginFormData = z.infer<typeof zUserLoginDto>;
|
|
5
|
+
type SignupFormData = z.infer<typeof zUserSignupDto>;
|
|
6
|
+
type ResetPasswordFormData = z.infer<typeof zUserResetPasswordDto>;
|
|
7
|
+
|
|
8
|
+
export const loginFormDefaults: LoginFormData = {
|
|
9
|
+
email: '',
|
|
10
|
+
password: '',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const signupFormDefaults: SignupFormData = {
|
|
14
|
+
email: '',
|
|
15
|
+
password: '',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const forgotPasswordFormDefaults = {
|
|
19
|
+
email: '',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const resetPasswordFormDefaults: ResetPasswordFormData = {
|
|
23
|
+
email: '',
|
|
24
|
+
password: '',
|
|
25
|
+
otp: '',
|
|
26
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Link } from '@tanstack/react-router';
|
|
2
|
+
import { Button } from '@/components/ui/button';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Route as LoginRoute } from '@/routes/auth/login';
|
|
5
|
+
import { Route as SignupRoute } from '@/routes/auth/signup';
|
|
6
|
+
|
|
7
|
+
export function AuthHero() {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<h1 className='text-4xl md:text-5xl lg:text-6xl font-bold mb-6'>{t('landing.hero.title')}</h1>
|
|
13
|
+
<p className='text-xl md:text-2xl text-muted-foreground mb-12 max-w-2xl mx-auto'>{t('landing.hero.description')}</p>
|
|
14
|
+
<div className='flex flex-col sm:flex-row gap-4 justify-center items-center'>
|
|
15
|
+
<Link to={LoginRoute.to}>
|
|
16
|
+
<Button
|
|
17
|
+
size='lg'
|
|
18
|
+
className='w-full sm:w-auto min-w-[150px]'>
|
|
19
|
+
{t('landing.hero.loginButton')}
|
|
20
|
+
</Button>
|
|
21
|
+
</Link>
|
|
22
|
+
<Link to={SignupRoute.to}>
|
|
23
|
+
<Button
|
|
24
|
+
size='lg'
|
|
25
|
+
variant='outline'
|
|
26
|
+
className='w-full sm:w-auto min-w-[150px]'>
|
|
27
|
+
{t('landing.hero.signupButton')}
|
|
28
|
+
</Button>
|
|
29
|
+
</Link>
|
|
30
|
+
</div>
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Link } from '@tanstack/react-router';
|
|
2
|
+
import { Button } from '@/components/ui/button';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { DEFAULT_LOGGED_IN_ROUTE } from '@/lib/routes';
|
|
5
|
+
|
|
6
|
+
export function WelcomeHero() {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
<h1 className='text-4xl md:text-5xl lg:text-6xl font-bold mb-6'>{t('landing.hero.welcomeTitle')}</h1>
|
|
12
|
+
<p className='text-xl md:text-2xl text-muted-foreground mb-12 max-w-2xl mx-auto'>{t('landing.hero.welcomeDescription')}</p>
|
|
13
|
+
<div className='flex justify-center items-center'>
|
|
14
|
+
<Link to={DEFAULT_LOGGED_IN_ROUTE}>
|
|
15
|
+
<Button
|
|
16
|
+
size='lg'
|
|
17
|
+
className='w-full sm:w-auto min-w-[150px]'>
|
|
18
|
+
{t('landing.hero.getStartedButton')}
|
|
19
|
+
</Button>
|
|
20
|
+
</Link>
|
|
21
|
+
</div>
|
|
22
|
+
</>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { LanguageSwitcher } from '@/components/layout/language-switcher';
|
|
2
|
+
import { ThemeSwitcher } from '@/components/layout/theme-switcher';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
export function LandingPageLayout({ children }: { children: React.ReactNode }) {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className='min-h-screen bg-background'>
|
|
10
|
+
<header className='border-b'>
|
|
11
|
+
<div className='container mx-auto flex h-16 items-center justify-between px-4'>
|
|
12
|
+
<div className='flex items-center gap-4'>
|
|
13
|
+
<h1 className='text-xl font-semibold'>{t('app.title')}</h1>
|
|
14
|
+
</div>
|
|
15
|
+
<div className='flex items-center gap-4'>
|
|
16
|
+
<ThemeSwitcher />
|
|
17
|
+
<LanguageSwitcher />
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</header>
|
|
21
|
+
<main>{children}</main>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useAtomValue } from 'jotai';
|
|
2
|
+
import { authTokenAtom, currentUserDetailsAtom } from '@/modules/auth/hooks/use-auth-hook';
|
|
3
|
+
import { WelcomeHero } from './components/welcome-hero';
|
|
4
|
+
import { AuthHero } from './components/auth-hero';
|
|
5
|
+
|
|
6
|
+
export function LandingPage() {
|
|
7
|
+
const token = useAtomValue(authTokenAtom);
|
|
8
|
+
const userData = useAtomValue(currentUserDetailsAtom);
|
|
9
|
+
|
|
10
|
+
const isAuthenticated = token && userData;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className='container mx-auto px-4 py-16'>
|
|
14
|
+
<div className='max-w-4xl mx-auto text-center'>{isAuthenticated ? <WelcomeHero /> : <AuthHero />}</div>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { LanguageSwitcher } from '@/components/layout/language-switcher';
|
|
2
|
+
import { ThemeSwitcher } from '@/components/layout/theme-switcher';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
export function LandingPageLayout({ children }: { children: React.ReactNode }) {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className='min-h-screen bg-background'>
|
|
10
|
+
<header className='border-b'>
|
|
11
|
+
<div className='container mx-auto flex h-16 items-center justify-between px-4'>
|
|
12
|
+
<div className='flex items-center gap-4'>
|
|
13
|
+
<h1 className='text-xl font-semibold'>{t('app.title')}</h1>
|
|
14
|
+
</div>
|
|
15
|
+
<div className='flex items-center gap-4'>
|
|
16
|
+
<ThemeSwitcher />
|
|
17
|
+
<LanguageSwitcher />
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</header>
|
|
21
|
+
<main>{children}</main>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hero": {
|
|
3
|
+
"title": "Welcome to Our App",
|
|
4
|
+
"description": "Get started by logging in or creating a new account",
|
|
5
|
+
"loginButton": "Login",
|
|
6
|
+
"signupButton": "Sign Up",
|
|
7
|
+
"welcomeTitle": "Welcome back!",
|
|
8
|
+
"welcomeDescription": "Ready to get started?",
|
|
9
|
+
"getStartedButton": "Get Started"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
@@ -1,10 +1,275 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
+
|
|
2
3
|
// @ts-nocheck
|
|
3
4
|
|
|
4
|
-
//
|
|
5
|
-
|
|
5
|
+
// noinspection JSUnusedGlobalSymbols
|
|
6
|
+
|
|
7
|
+
// This file was automatically generated by TanStack Router.
|
|
8
|
+
// You should NOT make any changes in this file as it will be overwritten.
|
|
9
|
+
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
|
6
10
|
|
|
7
11
|
import { Route as rootRouteImport } from './routes/__root'
|
|
12
|
+
import { Route as SplatRouteImport } from './routes/$'
|
|
13
|
+
import { Route as AuthRouteRouteImport } from './routes/auth/route'
|
|
14
|
+
import { Route as AppRouteRouteImport } from './routes/app/route'
|
|
15
|
+
import { Route as LandingRouteRouteImport } from './routes/_landing/route'
|
|
16
|
+
import { Route as AppIndexRouteImport } from './routes/app/index'
|
|
17
|
+
import { Route as LandingIndexRouteImport } from './routes/_landing/index'
|
|
18
|
+
import { Route as AuthSignupRouteImport } from './routes/auth/signup'
|
|
19
|
+
import { Route as AuthResetPasswordRouteImport } from './routes/auth/reset-password'
|
|
20
|
+
import { Route as AuthLoginRouteImport } from './routes/auth/login'
|
|
21
|
+
import { Route as AuthForgotPasswordRouteImport } from './routes/auth/forgot-password'
|
|
8
22
|
|
|
9
|
-
|
|
23
|
+
const SplatRoute = SplatRouteImport.update({
|
|
24
|
+
id: '/$',
|
|
25
|
+
path: '/$',
|
|
26
|
+
getParentRoute: () => rootRouteImport,
|
|
27
|
+
} as any)
|
|
28
|
+
const AuthRouteRoute = AuthRouteRouteImport.update({
|
|
29
|
+
id: '/auth',
|
|
30
|
+
path: '/auth',
|
|
31
|
+
getParentRoute: () => rootRouteImport,
|
|
32
|
+
} as any)
|
|
33
|
+
const AppRouteRoute = AppRouteRouteImport.update({
|
|
34
|
+
id: '/app',
|
|
35
|
+
path: '/app',
|
|
36
|
+
getParentRoute: () => rootRouteImport,
|
|
37
|
+
} as any)
|
|
38
|
+
const LandingRouteRoute = LandingRouteRouteImport.update({
|
|
39
|
+
id: '/_landing',
|
|
40
|
+
getParentRoute: () => rootRouteImport,
|
|
41
|
+
} as any)
|
|
42
|
+
const AppIndexRoute = AppIndexRouteImport.update({
|
|
43
|
+
id: '/',
|
|
44
|
+
path: '/',
|
|
45
|
+
getParentRoute: () => AppRouteRoute,
|
|
46
|
+
} as any)
|
|
47
|
+
const LandingIndexRoute = LandingIndexRouteImport.update({
|
|
48
|
+
id: '/',
|
|
49
|
+
path: '/',
|
|
50
|
+
getParentRoute: () => LandingRouteRoute,
|
|
51
|
+
} as any)
|
|
52
|
+
const AuthSignupRoute = AuthSignupRouteImport.update({
|
|
53
|
+
id: '/signup',
|
|
54
|
+
path: '/signup',
|
|
55
|
+
getParentRoute: () => AuthRouteRoute,
|
|
56
|
+
} as any)
|
|
57
|
+
const AuthResetPasswordRoute = AuthResetPasswordRouteImport.update({
|
|
58
|
+
id: '/reset-password',
|
|
59
|
+
path: '/reset-password',
|
|
60
|
+
getParentRoute: () => AuthRouteRoute,
|
|
61
|
+
} as any)
|
|
62
|
+
const AuthLoginRoute = AuthLoginRouteImport.update({
|
|
63
|
+
id: '/login',
|
|
64
|
+
path: '/login',
|
|
65
|
+
getParentRoute: () => AuthRouteRoute,
|
|
66
|
+
} as any)
|
|
67
|
+
const AuthForgotPasswordRoute = AuthForgotPasswordRouteImport.update({
|
|
68
|
+
id: '/forgot-password',
|
|
69
|
+
path: '/forgot-password',
|
|
70
|
+
getParentRoute: () => AuthRouteRoute,
|
|
71
|
+
} as any)
|
|
72
|
+
|
|
73
|
+
export interface FileRoutesByFullPath {
|
|
74
|
+
'/app': typeof AppRouteRouteWithChildren
|
|
75
|
+
'/auth': typeof AuthRouteRouteWithChildren
|
|
76
|
+
'/$': typeof SplatRoute
|
|
77
|
+
'/auth/forgot-password': typeof AuthForgotPasswordRoute
|
|
78
|
+
'/auth/login': typeof AuthLoginRoute
|
|
79
|
+
'/auth/reset-password': typeof AuthResetPasswordRoute
|
|
80
|
+
'/auth/signup': typeof AuthSignupRoute
|
|
81
|
+
'/': typeof LandingIndexRoute
|
|
82
|
+
'/app/': typeof AppIndexRoute
|
|
83
|
+
}
|
|
84
|
+
export interface FileRoutesByTo {
|
|
85
|
+
'/auth': typeof AuthRouteRouteWithChildren
|
|
86
|
+
'/$': typeof SplatRoute
|
|
87
|
+
'/auth/forgot-password': typeof AuthForgotPasswordRoute
|
|
88
|
+
'/auth/login': typeof AuthLoginRoute
|
|
89
|
+
'/auth/reset-password': typeof AuthResetPasswordRoute
|
|
90
|
+
'/auth/signup': typeof AuthSignupRoute
|
|
91
|
+
'/': typeof LandingIndexRoute
|
|
92
|
+
'/app': typeof AppIndexRoute
|
|
93
|
+
}
|
|
94
|
+
export interface FileRoutesById {
|
|
95
|
+
__root__: typeof rootRouteImport
|
|
96
|
+
'/_landing': typeof LandingRouteRouteWithChildren
|
|
97
|
+
'/app': typeof AppRouteRouteWithChildren
|
|
98
|
+
'/auth': typeof AuthRouteRouteWithChildren
|
|
99
|
+
'/$': typeof SplatRoute
|
|
100
|
+
'/auth/forgot-password': typeof AuthForgotPasswordRoute
|
|
101
|
+
'/auth/login': typeof AuthLoginRoute
|
|
102
|
+
'/auth/reset-password': typeof AuthResetPasswordRoute
|
|
103
|
+
'/auth/signup': typeof AuthSignupRoute
|
|
104
|
+
'/_landing/': typeof LandingIndexRoute
|
|
105
|
+
'/app/': typeof AppIndexRoute
|
|
106
|
+
}
|
|
107
|
+
export interface FileRouteTypes {
|
|
108
|
+
fileRoutesByFullPath: FileRoutesByFullPath
|
|
109
|
+
fullPaths:
|
|
110
|
+
| '/app'
|
|
111
|
+
| '/auth'
|
|
112
|
+
| '/$'
|
|
113
|
+
| '/auth/forgot-password'
|
|
114
|
+
| '/auth/login'
|
|
115
|
+
| '/auth/reset-password'
|
|
116
|
+
| '/auth/signup'
|
|
117
|
+
| '/'
|
|
118
|
+
| '/app/'
|
|
119
|
+
fileRoutesByTo: FileRoutesByTo
|
|
120
|
+
to:
|
|
121
|
+
| '/auth'
|
|
122
|
+
| '/$'
|
|
123
|
+
| '/auth/forgot-password'
|
|
124
|
+
| '/auth/login'
|
|
125
|
+
| '/auth/reset-password'
|
|
126
|
+
| '/auth/signup'
|
|
127
|
+
| '/'
|
|
128
|
+
| '/app'
|
|
129
|
+
id:
|
|
130
|
+
| '__root__'
|
|
131
|
+
| '/_landing'
|
|
132
|
+
| '/app'
|
|
133
|
+
| '/auth'
|
|
134
|
+
| '/$'
|
|
135
|
+
| '/auth/forgot-password'
|
|
136
|
+
| '/auth/login'
|
|
137
|
+
| '/auth/reset-password'
|
|
138
|
+
| '/auth/signup'
|
|
139
|
+
| '/_landing/'
|
|
140
|
+
| '/app/'
|
|
141
|
+
fileRoutesById: FileRoutesById
|
|
142
|
+
}
|
|
143
|
+
export interface RootRouteChildren {
|
|
144
|
+
LandingRouteRoute: typeof LandingRouteRouteWithChildren
|
|
145
|
+
AppRouteRoute: typeof AppRouteRouteWithChildren
|
|
146
|
+
AuthRouteRoute: typeof AuthRouteRouteWithChildren
|
|
147
|
+
SplatRoute: typeof SplatRoute
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
declare module '@tanstack/react-router' {
|
|
151
|
+
interface FileRoutesByPath {
|
|
152
|
+
'/$': {
|
|
153
|
+
id: '/$'
|
|
154
|
+
path: '/$'
|
|
155
|
+
fullPath: '/$'
|
|
156
|
+
preLoaderRoute: typeof SplatRouteImport
|
|
157
|
+
parentRoute: typeof rootRouteImport
|
|
158
|
+
}
|
|
159
|
+
'/auth': {
|
|
160
|
+
id: '/auth'
|
|
161
|
+
path: '/auth'
|
|
162
|
+
fullPath: '/auth'
|
|
163
|
+
preLoaderRoute: typeof AuthRouteRouteImport
|
|
164
|
+
parentRoute: typeof rootRouteImport
|
|
165
|
+
}
|
|
166
|
+
'/app': {
|
|
167
|
+
id: '/app'
|
|
168
|
+
path: '/app'
|
|
169
|
+
fullPath: '/app'
|
|
170
|
+
preLoaderRoute: typeof AppRouteRouteImport
|
|
171
|
+
parentRoute: typeof rootRouteImport
|
|
172
|
+
}
|
|
173
|
+
'/_landing': {
|
|
174
|
+
id: '/_landing'
|
|
175
|
+
path: ''
|
|
176
|
+
fullPath: ''
|
|
177
|
+
preLoaderRoute: typeof LandingRouteRouteImport
|
|
178
|
+
parentRoute: typeof rootRouteImport
|
|
179
|
+
}
|
|
180
|
+
'/app/': {
|
|
181
|
+
id: '/app/'
|
|
182
|
+
path: '/'
|
|
183
|
+
fullPath: '/app/'
|
|
184
|
+
preLoaderRoute: typeof AppIndexRouteImport
|
|
185
|
+
parentRoute: typeof AppRouteRoute
|
|
186
|
+
}
|
|
187
|
+
'/_landing/': {
|
|
188
|
+
id: '/_landing/'
|
|
189
|
+
path: '/'
|
|
190
|
+
fullPath: '/'
|
|
191
|
+
preLoaderRoute: typeof LandingIndexRouteImport
|
|
192
|
+
parentRoute: typeof LandingRouteRoute
|
|
193
|
+
}
|
|
194
|
+
'/auth/signup': {
|
|
195
|
+
id: '/auth/signup'
|
|
196
|
+
path: '/signup'
|
|
197
|
+
fullPath: '/auth/signup'
|
|
198
|
+
preLoaderRoute: typeof AuthSignupRouteImport
|
|
199
|
+
parentRoute: typeof AuthRouteRoute
|
|
200
|
+
}
|
|
201
|
+
'/auth/reset-password': {
|
|
202
|
+
id: '/auth/reset-password'
|
|
203
|
+
path: '/reset-password'
|
|
204
|
+
fullPath: '/auth/reset-password'
|
|
205
|
+
preLoaderRoute: typeof AuthResetPasswordRouteImport
|
|
206
|
+
parentRoute: typeof AuthRouteRoute
|
|
207
|
+
}
|
|
208
|
+
'/auth/login': {
|
|
209
|
+
id: '/auth/login'
|
|
210
|
+
path: '/login'
|
|
211
|
+
fullPath: '/auth/login'
|
|
212
|
+
preLoaderRoute: typeof AuthLoginRouteImport
|
|
213
|
+
parentRoute: typeof AuthRouteRoute
|
|
214
|
+
}
|
|
215
|
+
'/auth/forgot-password': {
|
|
216
|
+
id: '/auth/forgot-password'
|
|
217
|
+
path: '/forgot-password'
|
|
218
|
+
fullPath: '/auth/forgot-password'
|
|
219
|
+
preLoaderRoute: typeof AuthForgotPasswordRouteImport
|
|
220
|
+
parentRoute: typeof AuthRouteRoute
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
interface LandingRouteRouteChildren {
|
|
226
|
+
LandingIndexRoute: typeof LandingIndexRoute
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const LandingRouteRouteChildren: LandingRouteRouteChildren = {
|
|
230
|
+
LandingIndexRoute: LandingIndexRoute,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const LandingRouteRouteWithChildren = LandingRouteRoute._addFileChildren(
|
|
234
|
+
LandingRouteRouteChildren,
|
|
235
|
+
)
|
|
10
236
|
|
|
237
|
+
interface AppRouteRouteChildren {
|
|
238
|
+
AppIndexRoute: typeof AppIndexRoute
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const AppRouteRouteChildren: AppRouteRouteChildren = {
|
|
242
|
+
AppIndexRoute: AppIndexRoute,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const AppRouteRouteWithChildren = AppRouteRoute._addFileChildren(
|
|
246
|
+
AppRouteRouteChildren,
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
interface AuthRouteRouteChildren {
|
|
250
|
+
AuthForgotPasswordRoute: typeof AuthForgotPasswordRoute
|
|
251
|
+
AuthLoginRoute: typeof AuthLoginRoute
|
|
252
|
+
AuthResetPasswordRoute: typeof AuthResetPasswordRoute
|
|
253
|
+
AuthSignupRoute: typeof AuthSignupRoute
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const AuthRouteRouteChildren: AuthRouteRouteChildren = {
|
|
257
|
+
AuthForgotPasswordRoute: AuthForgotPasswordRoute,
|
|
258
|
+
AuthLoginRoute: AuthLoginRoute,
|
|
259
|
+
AuthResetPasswordRoute: AuthResetPasswordRoute,
|
|
260
|
+
AuthSignupRoute: AuthSignupRoute,
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const AuthRouteRouteWithChildren = AuthRouteRoute._addFileChildren(
|
|
264
|
+
AuthRouteRouteChildren,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
const rootRouteChildren: RootRouteChildren = {
|
|
268
|
+
LandingRouteRoute: LandingRouteRouteWithChildren,
|
|
269
|
+
AppRouteRoute: AppRouteRouteWithChildren,
|
|
270
|
+
AuthRouteRoute: AuthRouteRouteWithChildren,
|
|
271
|
+
SplatRoute: SplatRoute,
|
|
272
|
+
}
|
|
273
|
+
export const routeTree = rootRouteImport
|
|
274
|
+
._addFileChildren(rootRouteChildren)
|
|
275
|
+
._addFileTypes<FileRouteTypes>()
|