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
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# <%= appNameTitleCase %>
|
|
2
|
-
|
|
3
|
-
A React application built with Vite, TanStack Router, and TypeScript.
|
|
4
|
-
|
|
5
|
-
## Getting Started
|
|
6
|
-
|
|
7
|
-
1. Install dependencies:
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
2. Create a `.env` file from `.env.example`:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
cp .env.example .env
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
3. Update the `.env` file with your API base URL.
|
|
20
|
-
|
|
21
|
-
4. Start the development server:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm run dev
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Environment Variables
|
|
28
|
-
|
|
29
|
-
- `VITE_API_BASE_URL` - Base URL for your API backend (default: `http://localhost:8181/api/v1`)
|
|
30
|
-
- `PORT` - Port for the development server (default: `3000`)
|
|
31
|
-
|
|
32
|
-
### Setting Environment Variables
|
|
33
|
-
|
|
34
|
-
You can set environment variables in several ways:
|
|
35
|
-
|
|
36
|
-
**Option 1: Using a `.env` file (recommended)**
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
# Create .env file
|
|
40
|
-
echo "VITE_API_BASE_URL=http://localhost:8080/api/v1" > .env
|
|
41
|
-
echo "PORT=3001" >> .env
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Option 2: Using environment variables when running commands**
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
VITE_API_BASE_URL=http://localhost:8080/api/v1 PORT=3001 npm run dev
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
**Option 3: Using cross-env (works on all platforms)**
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
cross-env VITE_API_BASE_URL=http://localhost:8080/api/v1 PORT=3001 npm run dev
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## Project Structure
|
|
57
|
-
|
|
58
|
-
- `src/routes/` - File-based routing with TanStack Router
|
|
59
|
-
- `src/modules/auth/` - Authentication module
|
|
60
|
-
- `src/components/` - Reusable UI components
|
|
61
|
-
- `src/lib/` - Utility functions and configurations
|
|
62
|
-
- `src/locales/` - i18n translation files
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosResponse } from 'axios';
|
|
2
|
-
import { handleBackendError } from '../utils/error-handler';
|
|
3
|
-
|
|
4
|
-
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8181/api/v1';
|
|
5
|
-
|
|
6
|
-
export const client = axios.create({
|
|
7
|
-
baseURL: apiBaseUrl,
|
|
8
|
-
headers: {
|
|
9
|
-
'Content-Type': 'application/json',
|
|
10
|
-
},
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
// Add response interceptor to handle non-2xx responses and network errors
|
|
14
|
-
client.interceptors.response.use(
|
|
15
|
-
(response: AxiosResponse) => response,
|
|
16
|
-
(error: unknown) => {
|
|
17
|
-
// Handle all errors: non-2xx responses and network errors
|
|
18
|
-
if (error && typeof error === 'object' && 'response' in error) {
|
|
19
|
-
const axiosError = error as { response?: { status?: number }; code?: string };
|
|
20
|
-
if (axiosError.response && axiosError.response.status && axiosError.response.status >= 300) {
|
|
21
|
-
// Backend returned an error response
|
|
22
|
-
handleBackendError(error);
|
|
23
|
-
} else if (axiosError.code === 'ERR_NETWORK' || !axiosError.response) {
|
|
24
|
-
// Network error or no response (connection refused, timeout, etc.)
|
|
25
|
-
handleBackendError(error);
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
// Handle non-axios errors
|
|
29
|
-
handleBackendError(error);
|
|
30
|
-
}
|
|
31
|
-
return Promise.reject(error);
|
|
32
|
-
}
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
export default client;
|
|
@@ -1,18 +0,0 @@
|
|
|
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
|
-
},
|
|
10
|
-
"welcome": {
|
|
11
|
-
"title": "Welcome",
|
|
12
|
-
"message": "You have successfully logged in!",
|
|
13
|
-
"logout": "Logout"
|
|
14
|
-
},
|
|
15
|
-
"notFound": {
|
|
16
|
-
"message": "Page not found"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export interface UserData {
|
|
2
|
-
id: string;
|
|
3
|
-
slug: string;
|
|
4
|
-
email: string;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface ModulePermission {
|
|
8
|
-
module: string;
|
|
9
|
-
permissions: string[];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface AuthData {
|
|
13
|
-
token: string;
|
|
14
|
-
data: UserData;
|
|
15
|
-
roleName: string;
|
|
16
|
-
modulePermissions: ModulePermission[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface AuthResponse {
|
|
20
|
-
message: string | null;
|
|
21
|
-
status: boolean;
|
|
22
|
-
data: AuthData;
|
|
23
|
-
}
|
|
24
|
-
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Button } from "@/components/ui/button";
|
|
2
|
-
import { Input } from "@/components/ui/input";
|
|
3
|
-
import { useLogin } from "../use-auth-hook";
|
|
4
|
-
import { useState } from "react";
|
|
5
|
-
import { useTranslation } from "react-i18next";
|
|
6
|
-
|
|
7
|
-
export function LoginForm() {
|
|
8
|
-
const { t } = useTranslation();
|
|
9
|
-
const { mutate, isPending } = useLogin();
|
|
10
|
-
const [email, setEmail] = useState("");
|
|
11
|
-
const [password, setPassword] = useState("");
|
|
12
|
-
|
|
13
|
-
const handleSubmit = (e: React.FormEvent) => {
|
|
14
|
-
e.preventDefault();
|
|
15
|
-
mutate({ email, password });
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<div className="flex flex-col gap-6">
|
|
20
|
-
<h1 className="text-2xl font-semibold">{t("login.title")}</h1>
|
|
21
|
-
<form className="flex flex-col gap-4" onSubmit={handleSubmit}>
|
|
22
|
-
<div className="flex flex-col gap-2">
|
|
23
|
-
<label className="text-sm font-medium">{t("login.email")}</label>
|
|
24
|
-
<Input
|
|
25
|
-
type="email"
|
|
26
|
-
value={email}
|
|
27
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
28
|
-
placeholder={t("login.emailPlaceholder")}
|
|
29
|
-
required
|
|
30
|
-
/>
|
|
31
|
-
</div>
|
|
32
|
-
<div className="flex flex-col gap-2">
|
|
33
|
-
<label className="text-sm font-medium">{t("login.password")}</label>
|
|
34
|
-
<Input
|
|
35
|
-
type="password"
|
|
36
|
-
value={password}
|
|
37
|
-
onChange={(e) => setPassword(e.target.value)}
|
|
38
|
-
placeholder={t("login.passwordPlaceholder")}
|
|
39
|
-
required
|
|
40
|
-
/>
|
|
41
|
-
</div>
|
|
42
|
-
<Button type="submit" disabled={isPending}>
|
|
43
|
-
{t("login.submit")}
|
|
44
|
-
</Button>
|
|
45
|
-
</form>
|
|
46
|
-
</div>
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { Route as LoginRoute } from '@/routes/auth/login';
|
|
2
|
-
import { Route as AppRoute } from '@/routes/index';
|
|
3
|
-
import { useMutation } from '@tanstack/react-query';
|
|
4
|
-
import { useNavigate } from '@tanstack/react-router';
|
|
5
|
-
import { atom, useAtomValue, useSetAtom } from 'jotai';
|
|
6
|
-
import { atomWithStorage } from 'jotai/utils';
|
|
7
|
-
import { client } from '@/lib/api/client';
|
|
8
|
-
import { AuthData, AuthResponse } from './auth-types';
|
|
9
|
-
|
|
10
|
-
export const authTokenAtom = atomWithStorage<string>('authTokenAtom', '', undefined, {
|
|
11
|
-
getOnInit: true,
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
export const currentUserDetailsAtom = atom<AuthData | undefined>();
|
|
15
|
-
|
|
16
|
-
export const setTokenInAxios = (token?: string | null) => {
|
|
17
|
-
if (token) {
|
|
18
|
-
client.defaults.headers.common['x-auth-token'] = token;
|
|
19
|
-
} else {
|
|
20
|
-
delete client.defaults.headers.common['x-auth-token'];
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const setLocaleInAxios = (locale: 'en') => {
|
|
25
|
-
client.defaults.headers.common['Accept-Language'] = locale;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export const useLogin = () => {
|
|
29
|
-
const setAuthToken = useSetAtom(authTokenAtom);
|
|
30
|
-
const setCurrentUser = useSetAtom(currentUserDetailsAtom);
|
|
31
|
-
const navigate = useNavigate();
|
|
32
|
-
return useMutation({
|
|
33
|
-
mutationFn: async (data: { email: string; password: string }): Promise<AuthResponse> => {
|
|
34
|
-
const response = await client.post<AuthResponse>('/auth/user/login', data);
|
|
35
|
-
return response.data;
|
|
36
|
-
},
|
|
37
|
-
onSuccess: (authData: AuthResponse) => {
|
|
38
|
-
const token = authData?.data?.token || '';
|
|
39
|
-
setAuthToken(token);
|
|
40
|
-
setCurrentUser(authData.data);
|
|
41
|
-
setTokenInAxios(token);
|
|
42
|
-
navigate({ to: AppRoute.to });
|
|
43
|
-
},
|
|
44
|
-
onError: (err: unknown) => {
|
|
45
|
-
// Error is already handled by axios interceptor
|
|
46
|
-
console.error('Login failed:', err);
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const useValidateToken = () => {
|
|
52
|
-
const setCurrentUser = useSetAtom(currentUserDetailsAtom);
|
|
53
|
-
const setAuthToken = useSetAtom(authTokenAtom);
|
|
54
|
-
const authToken = useAtomValue(authTokenAtom);
|
|
55
|
-
setTokenInAxios(authToken);
|
|
56
|
-
return useMutation({
|
|
57
|
-
mutationFn: async (): Promise<AuthResponse> => {
|
|
58
|
-
const response = await client.post<AuthResponse>('/auth/user/validate-token');
|
|
59
|
-
return response.data;
|
|
60
|
-
},
|
|
61
|
-
retry: false,
|
|
62
|
-
onSuccess: (data: AuthResponse) => {
|
|
63
|
-
setCurrentUser(data.data);
|
|
64
|
-
},
|
|
65
|
-
onError: () => {
|
|
66
|
-
setCurrentUser(undefined);
|
|
67
|
-
setAuthToken('');
|
|
68
|
-
setTokenInAxios();
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export const useLogout = () => {
|
|
74
|
-
const setAuthToken = useSetAtom(authTokenAtom);
|
|
75
|
-
const setCurrentUser = useSetAtom(currentUserDetailsAtom);
|
|
76
|
-
const navigate = useNavigate();
|
|
77
|
-
return useMutation({
|
|
78
|
-
mutationFn: async () => {
|
|
79
|
-
await client.post('/auth/user/logout');
|
|
80
|
-
},
|
|
81
|
-
onSuccess: () => {
|
|
82
|
-
setAuthToken('');
|
|
83
|
-
setCurrentUser(undefined);
|
|
84
|
-
setTokenInAxios();
|
|
85
|
-
navigate({ to: LoginRoute.to });
|
|
86
|
-
},
|
|
87
|
-
});
|
|
88
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { createFileRoute, redirect } from "@tanstack/react-router";
|
|
2
|
-
import { Route as AppRoute } from "./app";
|
|
3
|
-
|
|
4
|
-
export const Route = createFileRoute("/")({
|
|
5
|
-
beforeLoad: () => {
|
|
6
|
-
throw redirect({
|
|
7
|
-
to: AppRoute.to,
|
|
8
|
-
replace: true,
|
|
9
|
-
});
|
|
10
|
-
},
|
|
11
|
-
});
|
|
12
|
-
|