@pplancq/react-template 1.0.0
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/.babelrc.js +1 -0
- package/.commitlintrc.js +1 -0
- package/.editorconfig +4 -0
- package/.env +36 -0
- package/.eslintrc.js +1 -0
- package/.gitattributes +1 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.lintstagedrc.js +5 -0
- package/.postcssrc.js +1 -0
- package/.prettierrc.js +1 -0
- package/.stylelintrc.js +1 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +221 -0
- package/_gitignore +26 -0
- package/package.json +84 -0
- package/public/favicon.ico +0 -0
- package/public/index.html +17 -0
- package/src/api/README.md +64 -0
- package/src/api/demoApi.ts +44 -0
- package/src/assets/README.md +51 -0
- package/src/assets/css/index.ts +2 -0
- package/src/assets/css/mainBody.css +4 -0
- package/src/assets/css/reset.css +131 -0
- package/src/assets/images/logo.png +0 -0
- package/src/assets/images/templatePlugins.png +0 -0
- package/src/bootstrap.tsx +26 -0
- package/src/components/App/App.tsx +18 -0
- package/src/components/App/index.ts +1 -0
- package/src/components/Footer/Footer.module.css +4 -0
- package/src/components/Footer/Footer.tsx +16 -0
- package/src/components/Footer/__tests__/Footer.test.tsx +15 -0
- package/src/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +21 -0
- package/src/components/Footer/index.ts +1 -0
- package/src/components/Header/Header.module.css +7 -0
- package/src/components/Header/Header.tsx +17 -0
- package/src/components/Header/__tests__/Header.test.tsx +15 -0
- package/src/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +35 -0
- package/src/components/Header/index.ts +1 -0
- package/src/components/README.md +34 -0
- package/src/components/TextInput/TextInput.tsx +24 -0
- package/src/components/TextInput/index.ts +1 -0
- package/src/config/README.md +61 -0
- package/src/config/index.ts +1 -0
- package/src/config/queryClientConfig.ts +3 -0
- package/src/forms/ProfileForm/ProfileForm.module.scss +10 -0
- package/src/forms/ProfileForm/ProfileForm.tsx +51 -0
- package/src/forms/ProfileForm/index.ts +1 -0
- package/src/forms/README.md +131 -0
- package/src/hooks/README.md +87 -0
- package/src/hooks/api/queryKey.ts +1 -0
- package/src/hooks/api/useDemoApi.ts +16 -0
- package/src/main.ts +3 -0
- package/src/pages/Demo/Demo.module.scss +184 -0
- package/src/pages/Demo/Demo.tsx +237 -0
- package/src/pages/Demo/ReactHookFormDemo/ReactHookFormDemo.module.css +32 -0
- package/src/pages/Demo/ReactHookFormDemo/ReactHookFormDemo.tsx +48 -0
- package/src/pages/Demo/ReactHookFormDemo/index.ts +1 -0
- package/src/pages/Demo/ReactHookFormDemo/routes.tsx +7 -0
- package/src/pages/Demo/ReactQueryDemo/ReactQueryDemo.module.scss +38 -0
- package/src/pages/Demo/ReactQueryDemo/ReactQueryDemo.tsx +55 -0
- package/src/pages/Demo/ReactQueryDemo/index.ts +1 -0
- package/src/pages/Demo/ReactQueryDemo/routes.tsx +7 -0
- package/src/pages/Demo/__tests__/Demo.test.tsx +15 -0
- package/src/pages/Demo/__tests__/__snapshots__/Demo.test.tsx.snap +555 -0
- package/src/pages/Demo/index.ts +1 -0
- package/src/pages/Demo/routes.tsx +8 -0
- package/src/pages/Error/Error.module.css +8 -0
- package/src/pages/Error/Error.tsx +22 -0
- package/src/pages/Error/index.ts +1 -0
- package/src/pages/Layout/Layout.tsx +12 -0
- package/src/pages/Layout/index.ts +1 -0
- package/src/pages/README.md +88 -0
- package/src/providers/QueryClientProvider/QueryClientProvider.tsx +16 -0
- package/src/providers/QueryClientProvider/index.ts +1 -0
- package/src/providers/README.md +115 -0
- package/src/providers/index.ts +1 -0
- package/src/providers/withProviders/index.ts +1 -0
- package/src/providers/withProviders/withProviders.tsx +18 -0
- package/src/react-app-env.d.ts +3 -0
- package/src/routing/README.md +80 -0
- package/src/routing/appRoutes.ts +5 -0
- package/src/routing/routerFactory.ts +10 -0
- package/src/routing/routes.tsx +13 -0
- package/src/types/README.md +61 -0
- package/src/types/demoApi.ts +9 -0
- package/src/types/profileTypes.ts +5 -0
- package/src/ui/README.md +141 -0
- package/src/ui/atoms/Input/Input.module.scss +32 -0
- package/src/ui/atoms/Input/Input.tsx +27 -0
- package/src/ui/atoms/Input/index.ts +1 -0
- package/src/ui/atoms/Logo/Logo.module.css +3 -0
- package/src/ui/atoms/Logo/Logo.tsx +11 -0
- package/src/ui/atoms/Logo/index.ts +1 -0
- package/src/ui/atoms/NavLink/NavLink.tsx +8 -0
- package/src/ui/atoms/NavLink/index.ts +1 -0
- package/src/ui/molecules/Navigation/Navigation.module.css +22 -0
- package/src/ui/molecules/Navigation/Navigation.tsx +25 -0
- package/src/ui/molecules/Navigation/index.ts +1 -0
- package/src/ui/organisms/Footer/Footer.module.css +10 -0
- package/src/ui/organisms/Footer/Footer.tsx +10 -0
- package/src/ui/organisms/Footer/index.ts +1 -0
- package/src/ui/organisms/Header/Header.module.css +17 -0
- package/src/ui/organisms/Header/Header.tsx +16 -0
- package/src/ui/organisms/Header/index.ts +1 -0
- package/src/ui/organisms/MainContent/MainContent.module.css +3 -0
- package/src/ui/organisms/MainContent/MainContent.tsx +6 -0
- package/src/ui/organisms/MainContent/index.ts +1 -0
- package/src/ui/templates/MainTemplate/MainTemplate.module.css +5 -0
- package/src/ui/templates/MainTemplate/MainTemplate.tsx +26 -0
- package/src/ui/templates/MainTemplate/index.ts +1 -0
- package/src/utils/README.md +68 -0
- package/tsconfig.json +32 -0
- package/vitest.config.mts +49 -0
- package/vitest.setup.ts +1 -0
- package/webpack.config.js +22 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# 📁 pages
|
|
2
|
+
|
|
3
|
+
The "pages" folder is designed to contain all the pages of our application. This structure facilitates organization, management, and navigation between the different views of our application. Additionally, if a page contains components related to its structure, we can create sub-folders to maintain order.
|
|
4
|
+
|
|
5
|
+
## 📑 Table of Contents
|
|
6
|
+
- [Why Use a "pages" Folder](#folder-organization)
|
|
7
|
+
- [Typical Structure of a "pages" Folder](#structure)
|
|
8
|
+
- [Usage Example](#usage)
|
|
9
|
+
- [Best Practice](#best-practice)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## <span id="folder-organization">Why Use a "pages" Folder?</span>
|
|
13
|
+
|
|
14
|
+
1. **Clear Organization** : By grouping all our pages in a single folder, we maintain a clear organization of our application, making it easy to find specific pages.
|
|
15
|
+
|
|
16
|
+
2. **Ease of Navigation** : A well-organized "pages" folder structure makes navigation between the views of our application easier.
|
|
17
|
+
|
|
18
|
+
3. **Reusability** : Components specific to a page can be reused in other pages, promoting code modularity.
|
|
19
|
+
|
|
20
|
+
## <span id="structure">Typical Structure of a "pages" Folder</span>
|
|
21
|
+
|
|
22
|
+
The structure of a "pages" folder can vary depending on the size of your application, but here is a typical structure you might adopt:
|
|
23
|
+
```
|
|
24
|
+
📁 Pages
|
|
25
|
+
├── 📁 Home
|
|
26
|
+
├── 📁 User
|
|
27
|
+
│ ├── 📁 UserProfile
|
|
28
|
+
├── 📁 Posts
|
|
29
|
+
│ ├── 📁 Article
|
|
30
|
+
├── 📁 Admin
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
In this structure, each page, such as "Home" or "User," is typically defined in its own file. If a page is complex and requires related components, you can create a sub-folder to maintain order related to the URL, as with "UserProfile" or "Article" in this example.
|
|
34
|
+
|
|
35
|
+
## <span id="usage">🧑🏻💻 Usage Example</span>
|
|
36
|
+
|
|
37
|
+
Suppose we have a "UserProfile" page with a complex structure:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
📁 UserProfile
|
|
41
|
+
├── 📄 index.ts
|
|
42
|
+
├── 📄 UserProfile.tsx
|
|
43
|
+
├── 📄 routes.tsx
|
|
44
|
+
```
|
|
45
|
+
```javascript
|
|
46
|
+
// index.ts
|
|
47
|
+
export { userProfileRoutes } from './routes';
|
|
48
|
+
|
|
49
|
+
// routes.tsx (react-router-dom v6)
|
|
50
|
+
import { RouteObject } from 'react-router-dom';
|
|
51
|
+
import { UserProfile } from './UserProfile';
|
|
52
|
+
|
|
53
|
+
export const userProfileRoutes: RouteObject = {
|
|
54
|
+
path: 'user-profile',
|
|
55
|
+
element: <UserProfile />,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// UserProfile.tsx
|
|
59
|
+
export const UserProfile = () => {
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
UserProfile
|
|
63
|
+
{/* Content of the UserProfile page */}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
By using a "pages" folder and the ability to create sub-folders, we effectively organize our pages and their related components for better management of our application.
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
## <span id="best-practice">🎖️ Best Practice</span>
|
|
73
|
+
When working with page components, it is advisable to follow these best practices to maintain a clean and organized code structure:
|
|
74
|
+
|
|
75
|
+
#### - Minimize Business Logic
|
|
76
|
+
|
|
77
|
+
Limit the inclusion of business logic within page components.
|
|
78
|
+
|
|
79
|
+
Instead, delegate complex business logic to separate utility functions, services, or hooks. This keeps your page components focused on rendering and layout.
|
|
80
|
+
|
|
81
|
+
#### - Data Presence Control
|
|
82
|
+
|
|
83
|
+
Keep the logic within page components to a minimum, focusing primarily on controlling the presence of data.
|
|
84
|
+
|
|
85
|
+
If data is not available or meets certain conditions, consider redirecting to a dedicated error or not-found page.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
***By adopting these practices, you create page components that are focused on their primary responsibilities, leading to cleaner and more maintainable code.***
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PropsWithChildren } from 'react';
|
|
2
|
+
import { type QueryClient, QueryClientProvider as ReactQueryClientProvider } from 'react-query';
|
|
3
|
+
import { ReactQueryDevtools } from 'react-query/devtools';
|
|
4
|
+
|
|
5
|
+
type ClientProviderProps = {
|
|
6
|
+
client: QueryClient;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const QueryClientProvider = ({ children, client }: PropsWithChildren<ClientProviderProps>) => {
|
|
10
|
+
return (
|
|
11
|
+
<ReactQueryClientProvider client={client}>
|
|
12
|
+
{children}
|
|
13
|
+
<ReactQueryDevtools initialIsOpen={false} />
|
|
14
|
+
</ReactQueryClientProvider>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { QueryClientProvider } from './QueryClientProvider';
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# 📁 providers
|
|
2
|
+
|
|
3
|
+
The "providers" folder is designed to expose service handlers and custom contexts that provide shared functionality across our entire application. It serves as a centralized way to manage services such as authentication, authorization, translation management, and many others.
|
|
4
|
+
|
|
5
|
+
## 📑 Table of Contents
|
|
6
|
+
- [Why Use a "providers" Folder?](#folder-organization)
|
|
7
|
+
- [Structure of a "providers" Folder](#structure)
|
|
8
|
+
- [Usage Example](#usage)
|
|
9
|
+
- [Best Practice](#best-practice)
|
|
10
|
+
|
|
11
|
+
## <span id="folder-organization">Why Use a "providers" Folder?</span>
|
|
12
|
+
|
|
13
|
+
1. **Centralization** : By grouping all our service handlers in a "providers" folder, we centralize the management of these services, making configuration and usage simpler.
|
|
14
|
+
|
|
15
|
+
2. **Reusability** : Service handlers and custom contexts exposed in this folder can be reused across different components of our application, promoting code reuse.
|
|
16
|
+
|
|
17
|
+
3. **Better Separation of Concerns** : By separating services from the user interface, we improve code readability and adhere to the separation of concerns principle.
|
|
18
|
+
|
|
19
|
+
## <span id="structure">Structure of a "providers" Folder</span>
|
|
20
|
+
|
|
21
|
+
The structure of a "providers" folder can vary based on your project's needs, but here is a typical structure you might adopt :
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
📁 providers
|
|
25
|
+
├── 📁 AuthProvider
|
|
26
|
+
├── 📁 AuthorizationProvider
|
|
27
|
+
├── 📁 TranslationProvider
|
|
28
|
+
├── 📁 CustomRouterProvider
|
|
29
|
+
├── 📁 CustomContextProvider
|
|
30
|
+
├── 📁 ...
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Each file, such as "AuthProvider.ts" or "TranslationProvider.ts," contains a service handler or custom context intended to be used throughout your application.
|
|
34
|
+
|
|
35
|
+
## <span id="usage">🧑🏻💻Usage Example </span>
|
|
36
|
+
|
|
37
|
+
Suppose we have an authentication service handler "AuthProvider" in our "providers" folder:
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
// AuthProvider.js
|
|
41
|
+
import { createContext, useState } from 'react';
|
|
42
|
+
|
|
43
|
+
export const AuthContext = createContext();
|
|
44
|
+
|
|
45
|
+
export const AuthProvider = ({ children }) => {
|
|
46
|
+
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
47
|
+
|
|
48
|
+
const login = () => {
|
|
49
|
+
setIsAuthenticated(true);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const logout = () => {
|
|
53
|
+
setIsAuthenticated(false);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
|
|
58
|
+
{children}
|
|
59
|
+
</AuthContext.Provider>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
We can then use this authentication service provider in our components by wrapping our components in the provided context:
|
|
64
|
+
```javascript
|
|
65
|
+
import { AuthProvider } from '@Front/Providers/AuthProvider';
|
|
66
|
+
|
|
67
|
+
export const App = () => {
|
|
68
|
+
return (
|
|
69
|
+
<AuthProvider>
|
|
70
|
+
{/* Vos composants React ici */}
|
|
71
|
+
</AuthProvider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
## <span id="best-practice">🎖️ Best Practice</span>
|
|
76
|
+
|
|
77
|
+
A good practice is to set up a Higher Order Component (HOC) "withProvider" that allows injecting all providers at
|
|
78
|
+
once.
|
|
79
|
+
|
|
80
|
+
Example:
|
|
81
|
+
```typescript
|
|
82
|
+
import { ComponentType } from 'react';
|
|
83
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
84
|
+
import { AuthProvider } from '@Front/Providers/AuthProvider';
|
|
85
|
+
import { QueryClientProvider } from '@Front/Providers/QueryClientProvider ';
|
|
86
|
+
|
|
87
|
+
export interface WithRootProps {
|
|
88
|
+
queryClient: QueryClient;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const withProvider = <P extends object>(Component: ComponentType<P>) => {
|
|
92
|
+
const WithProvider = ({ queryClient, ...props }: P & WithRootProps) => (
|
|
93
|
+
<QueryClientProvider client={queryClient}>
|
|
94
|
+
<AuthProvider>
|
|
95
|
+
<Component {...props as P} />
|
|
96
|
+
</AuthProvider>
|
|
97
|
+
</QueryClientProvider>
|
|
98
|
+
);
|
|
99
|
+
WithProvider.displayName = `withProvider(${Component.displayName || Component.name})`
|
|
100
|
+
|
|
101
|
+
return WithProvider
|
|
102
|
+
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
import { withProvider } from '@Front/Providers/withProvider';
|
|
108
|
+
import { App } from '@Front/components/App';
|
|
109
|
+
|
|
110
|
+
const Root = withProvider(App);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
----------
|
|
114
|
+
|
|
115
|
+
***By using a "providers" folder, we centralize the management of services and custom contexts, enhancing code reuse and ease of maintenance.***
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { withProvider } from './withProviders';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { withProvider } from './withProviders';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { QueryClientProvider } from '@Front/providers/QueryClientProvider';
|
|
2
|
+
import type { ComponentProps, ComponentType } from 'react';
|
|
3
|
+
|
|
4
|
+
type WithRootProps = {
|
|
5
|
+
queryClient: ComponentProps<typeof QueryClientProvider>['client'];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const withProvider = <P extends object>(Component: ComponentType<P>) => {
|
|
9
|
+
const WithProvider = ({ queryClient, ...props }: P & WithRootProps) => (
|
|
10
|
+
<QueryClientProvider client={queryClient}>
|
|
11
|
+
<Component {...(props as P)} />
|
|
12
|
+
</QueryClientProvider>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
WithProvider.displayName = `withProvider(${Component.displayName || Component.name})`;
|
|
16
|
+
|
|
17
|
+
return WithProvider;
|
|
18
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# 📁routing
|
|
2
|
+
|
|
3
|
+
The "routing" folder is responsible for managing navigation within the application. We use the `react-router-dom` library to facilitate route creation and navigation between different views of our application.
|
|
4
|
+
|
|
5
|
+
## 📑 Table of Contents
|
|
6
|
+
- [Folder Organization](#folder-organization)
|
|
7
|
+
- [Using `react-router-dom`](#react-router-dom)
|
|
8
|
+
- [Using `appRoutes.ts`](#using-appRoutes)
|
|
9
|
+
- [Learn More](#learn-more)
|
|
10
|
+
|
|
11
|
+
## <span id="folder-organization">Folder Organization</span>
|
|
12
|
+
|
|
13
|
+
In the "routing" folder, you can find the following files and components:
|
|
14
|
+
|
|
15
|
+
1. **`routesObject.tsx`** : This file contains the configuration of our main router. It declares the various routes of the application and defines the components associated with each route.
|
|
16
|
+
|
|
17
|
+
2. **`routerFactory.ts`** : The `routerFactory.ts` file can contain functions or reusable components related to routing. You can place routing utilities or custom components to facilitate navigation management in our application.
|
|
18
|
+
|
|
19
|
+
3. **`appRoutes.ts`** It contains a simple structure to define the paths of our application.
|
|
20
|
+
|
|
21
|
+
## <span id="react-router-dom">🧑🏻💻 Using `react-router-dom` </span>
|
|
22
|
+
|
|
23
|
+
`react-router-dom` is a library that makes it easy to create routes in a React application. You can import it into the appropriate files to define routes and manage navigation between views. Here's a simple example of its usage:
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import { createRoot } from "react-dom/client";
|
|
27
|
+
import {
|
|
28
|
+
createBrowserRouter,
|
|
29
|
+
RouterProvider,
|
|
30
|
+
} from "react-router-dom";
|
|
31
|
+
|
|
32
|
+
const router = createBrowserRouter([
|
|
33
|
+
{
|
|
34
|
+
path: "/",
|
|
35
|
+
element: (
|
|
36
|
+
<div>
|
|
37
|
+
<h1>Hello World</h1>
|
|
38
|
+
<Link to="about">About Us</Link>
|
|
39
|
+
</div>
|
|
40
|
+
),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
path: "about",
|
|
44
|
+
element: <div>About</div>,
|
|
45
|
+
},
|
|
46
|
+
]);
|
|
47
|
+
|
|
48
|
+
createRoot(document.getElementById("root")).render(
|
|
49
|
+
<RouterProvider router={router} />
|
|
50
|
+
);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## <span id="using-appRoutes">Using `appRoutes.ts`</span>
|
|
54
|
+
How to define a router with parameters ?
|
|
55
|
+
|
|
56
|
+
The simplest way is to write it with the parameters as `react-router` requires, and when using it in a `NavLink` call the `generatPath` function from `react-router`.
|
|
57
|
+
|
|
58
|
+
For example:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
// appRoutes.ts
|
|
62
|
+
export const appRoutes = {
|
|
63
|
+
home: '/',
|
|
64
|
+
post: '/post',
|
|
65
|
+
article: '/post/:id',
|
|
66
|
+
}
|
|
67
|
+
// component.tsx
|
|
68
|
+
import { NavLink, generatePath } from 'react-router-dom';
|
|
69
|
+
import { appRoutes } from '@Front/routing/appRoutes';
|
|
70
|
+
export const ComponentName = () => {
|
|
71
|
+
return (
|
|
72
|
+
<NavLink to={generatePath(appRoutes .article, { id: 1 })}>link to article 1</NavLink>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
With the `generatePath` function, it is possible to generate URIs with dynamic parameters.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## <span id="learn-more">🙇 Learn More</span>
|
|
80
|
+
- [React Router](https://reactrouter.com/en/main/start/overview)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createBrowserRouter } from 'react-router-dom';
|
|
2
|
+
import { routeObject } from './routes';
|
|
3
|
+
|
|
4
|
+
interface CreateRouterProps {
|
|
5
|
+
basename?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const createRouter = ({ basename }: CreateRouterProps = {}) => {
|
|
9
|
+
return createBrowserRouter(routeObject, { basename });
|
|
10
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { demoRoutes } from '@Front/pages/Demo';
|
|
2
|
+
import { Error } from '@Front/pages/Error';
|
|
3
|
+
import { Layout } from '@Front/pages/Layout';
|
|
4
|
+
import type { RouteObject } from 'react-router-dom';
|
|
5
|
+
|
|
6
|
+
export const routeObject: RouteObject[] = [
|
|
7
|
+
{
|
|
8
|
+
path: '/',
|
|
9
|
+
element: <Layout />,
|
|
10
|
+
children: [demoRoutes],
|
|
11
|
+
errorElement: <Error />,
|
|
12
|
+
},
|
|
13
|
+
];
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# 📁 types
|
|
2
|
+
|
|
3
|
+
The "types" folder: since we are using TypeScript, this folder is intended to contain custom type definition files that enhance type checking and auto-completion in your code.
|
|
4
|
+
|
|
5
|
+
## 📑 Table of Contents
|
|
6
|
+
- [Why use a "types" folder?](#folder-organization)
|
|
7
|
+
- [Structure of a "types" folder](#structure)
|
|
8
|
+
- [Example of usage](#usage)
|
|
9
|
+
|
|
10
|
+
## <span id="folder-organization">Why use a "types" folder?</span>
|
|
11
|
+
|
|
12
|
+
1. **Type Checking** : By defining custom types for our application, we improve type checking, making it easier to detect and prevent typing errors.
|
|
13
|
+
|
|
14
|
+
2. **Better Auto-Completion** : Custom type definition files allow code editors to provide more accurate auto-completion when working with objects, functions, and components.
|
|
15
|
+
|
|
16
|
+
3. **Integrated Documentation** : By creating explicit types, you effectively document your code, making it easier for other developers to understand your components, functions, and data.
|
|
17
|
+
|
|
18
|
+
## <span id="structure">Structure of a "types" folder</span>
|
|
19
|
+
|
|
20
|
+
The structure of a "types" folder can vary based on need, but here's a typical structure you might adopt :
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
📁 src
|
|
24
|
+
📁 types
|
|
25
|
+
├── 📄 customTypes.ts
|
|
26
|
+
├── 📄 apiTypes.ts
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
In this structure, each file, such as "customTypes.ts" or "apiTypes.ts," contains type definitions specific to your application. For example, you might define types for API data, business objects, or component props.
|
|
30
|
+
|
|
31
|
+
## <span id="usage">🧑🏻💻 Example of usage</span>
|
|
32
|
+
|
|
33
|
+
Suppose you have defined a custom type in "customTypes.ts":
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// customTypes.ts
|
|
37
|
+
export type User = {
|
|
38
|
+
id: number;
|
|
39
|
+
name: string;
|
|
40
|
+
email?: string;
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
You can then use this type in your React components to define props or states, enhancing type checking:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { User } from '@Front/types/customTypes';
|
|
48
|
+
|
|
49
|
+
type UserProfileProps = {
|
|
50
|
+
user: User;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const UserProfile = ({ user }: UserProfileProps) => {
|
|
54
|
+
return (
|
|
55
|
+
<div id={user.id}>
|
|
56
|
+
<h1>{user.name}</h1>
|
|
57
|
+
{user.email && <p>Email: {user.email}</p>}
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
```
|
package/src/ui/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# 📁 ui
|
|
2
|
+
The "ui" folder is a directory designed to group and organize reusable components.
|
|
3
|
+
|
|
4
|
+
We follow the concept of Atomic design to structure our components into "atoms," "molecules," "organisms," and "templates," ensuring consistent design and maximum reusability.
|
|
5
|
+
|
|
6
|
+
## 📑 Table of Contents
|
|
7
|
+
- [Why use a "ui" folder with Atomic Design](#folder-organization)
|
|
8
|
+
- [Structure of a "ui" folder according to Atomic Design](#structure)
|
|
9
|
+
- [Usage Example](#usage)
|
|
10
|
+
- [Best Practice](#best-practice)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## <span id="folder-organization">Why use a "ui" folder with Atomic Design?</span>
|
|
14
|
+
|
|
15
|
+
1. **Modularity** : Atomic Design divides components into levels of increasing complexity, making it easy to create reusable components at different levels.
|
|
16
|
+
|
|
17
|
+
2. **Visual Consistency** : By following the concept of Atomic Design, we can maintain visual consistency across our entire application by reusing atoms, molecules, and organisms.
|
|
18
|
+
|
|
19
|
+
3. **Productivity** : Creating prefab components in a "ui" folder speeds up development by reducing code duplication.
|
|
20
|
+
|
|
21
|
+
## <span id="structure">Structure of a "ui" folder according to Atomic Design</span>
|
|
22
|
+
|
|
23
|
+
The structure of a "ui" folder can follow the hierarchy of Atomic Design:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
📁 ui
|
|
27
|
+
├── 📁 atoms
|
|
28
|
+
│ ├──📁 Button
|
|
29
|
+
│ ├──📁 Input
|
|
30
|
+
│ ├── ...
|
|
31
|
+
├── 📁 molecules
|
|
32
|
+
│ ├── 📁 FormField
|
|
33
|
+
│ ├── 📁 SearchBar
|
|
34
|
+
│ ├── ...
|
|
35
|
+
├── 📁 organisms
|
|
36
|
+
│ ├── 📁 Header
|
|
37
|
+
│ ├── 📁 Footer
|
|
38
|
+
│ ├── ...
|
|
39
|
+
├── 📁 templates
|
|
40
|
+
│ ├── 📁 PageTemplate
|
|
41
|
+
│ ├── ...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Each level (atoms, molecules, organisms, templates) groups components based on their complexity. You can create subfolders to better organize the components.
|
|
45
|
+
|
|
46
|
+
## <span id="usage">🧑🏻💻Example of usage</span>
|
|
47
|
+
|
|
48
|
+
## Using components from Atomic Design
|
|
49
|
+
|
|
50
|
+
In our project, we use Atomic Design to organize our reusable components into levels ranging from "atoms" to "templates." Here's a concrete example of using these components in our application.
|
|
51
|
+
|
|
52
|
+
### Atom - "Button" Component
|
|
53
|
+
|
|
54
|
+
"Atoms" are basic components that don't depend on other components. In our "ui/atoms" folder, we have the "Button" component. It's a simple UI element that we can use as follows:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import { Button } from '@Front/ui/atoms/Button';
|
|
58
|
+
|
|
59
|
+
export const MyComponent = () => {
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
<Button label="Cliquez-moi" />
|
|
63
|
+
{/* ... other elements of the application */}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Molecule - "SearchBar" Component
|
|
70
|
+
"Molecules" are more complex components that group atoms to form a functional set. In our "ui/molecules" folder, we have the "SearchBar" component that uses the atomic "Button":
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
import { SearchBar } from '@Front/ui/molecules/SearchBar';
|
|
75
|
+
|
|
76
|
+
export const MyComponent = () => {
|
|
77
|
+
return (
|
|
78
|
+
<div>
|
|
79
|
+
<SearchBar placeholder="Rechercher..." />
|
|
80
|
+
{/* ... other elements of the application */}
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
The "SearchBar" component is a molecule because it combines the "Button" atom with other atoms.
|
|
86
|
+
|
|
87
|
+
### Organism - "Header" Component
|
|
88
|
+
"Organisms" are even more complex components that combine molecules and atoms to create self-contained parts of the UI. In our "ui/organisms" folder, we have the "Header" component that might include the molecular "SearchBar":
|
|
89
|
+
|
|
90
|
+
```javascript
|
|
91
|
+
import Header from '@Front/ui/organisms/Header';
|
|
92
|
+
|
|
93
|
+
export const MyComponent = () => {
|
|
94
|
+
return (
|
|
95
|
+
<div>
|
|
96
|
+
<Header />
|
|
97
|
+
{/* ... other elements of the application */}
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
The "Header" component is an organism because it combines the molecular "SearchBar" with other elements to form a self-contained part of the interface.
|
|
103
|
+
|
|
104
|
+
### Templates - "PageTemplate" Component
|
|
105
|
+
"Templates" are "skeleton" components that define the placement of elements using React's composition ability.
|
|
106
|
+
|
|
107
|
+
In our "ui/templates" folder, we have the "PageTemplate" component that defines the placement of the "topBar," "body," and "footer" to create a complete page:
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
import PageTemplate from '@Front/ui/templates/PageTemplate';
|
|
111
|
+
|
|
112
|
+
export const MyComponent = () => {
|
|
113
|
+
return (
|
|
114
|
+
<PageTemplate
|
|
115
|
+
topBar={<div>TopBar</div>}
|
|
116
|
+
body={<div>Boby</div>}
|
|
117
|
+
footer={<div>Footer</div>}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
The "PageTemplate" component is a template because it incorporates the "Header" organism and other elements to create a complete page.
|
|
123
|
+
|
|
124
|
+
## <span id="best-practice">🎖️ Best Practice</span>
|
|
125
|
+
When incorporating external component libraries, it is recommended to adhere to the following best practices for the organization of UI components:
|
|
126
|
+
|
|
127
|
+
#### - Export Components via the `ui` Directory
|
|
128
|
+
|
|
129
|
+
Always export UI components from the `ui` directory, even if they are sourced from an external component library.
|
|
130
|
+
|
|
131
|
+
This practice serves as a central point for managing component exports and facilitates handling bugs or breaking changes.
|
|
132
|
+
|
|
133
|
+
#### - Centralized Component Management
|
|
134
|
+
By exporting components through the ui directory, you establish a centralized location for managing changes or addressing issues related to external components.
|
|
135
|
+
|
|
136
|
+
In the event of a bug or breaking change, modifications can be made at a single location, preventing the need to update multiple parts of the codebase.
|
|
137
|
+
|
|
138
|
+
This approach contributes to better maintainability and ensures that updates to external components are efficiently managed.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
***By adopting this practice, you create a clear separation between your custom components and external components, simplifying maintenance and reducing the impact of changes from external dependencies.***
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.inputContainerStyle {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: space-between;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
%inputStyle {
|
|
9
|
+
margin: 10px;
|
|
10
|
+
padding: 10px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.inputStyle {
|
|
14
|
+
@extend %inputStyle;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.hasInputError {
|
|
18
|
+
@extend %inputStyle;
|
|
19
|
+
|
|
20
|
+
border: 1px solid red;
|
|
21
|
+
border-radius: 2px;
|
|
22
|
+
|
|
23
|
+
&:focus {
|
|
24
|
+
border: 2px solid red;
|
|
25
|
+
outline: none !important;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.errorsStyle {
|
|
30
|
+
font-size: x-small;
|
|
31
|
+
color: red;
|
|
32
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { forwardRef, InputHTMLAttributes, useId } from 'react';
|
|
2
|
+
import classes from './Input.module.scss';
|
|
3
|
+
|
|
4
|
+
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
5
|
+
label: string;
|
|
6
|
+
hasError?: boolean;
|
|
7
|
+
helperText?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const Input = forwardRef<HTMLInputElement, InputProps>(({ label, hasError, helperText, ...rest }, ref) => {
|
|
11
|
+
const id = useId();
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<div className={classes.inputContainerStyle}>
|
|
15
|
+
<label htmlFor={id}>{label} </label>
|
|
16
|
+
<input id={id} ref={ref} {...rest} className={hasError ? classes.hasInputError : classes.inputStyle} />
|
|
17
|
+
</div>
|
|
18
|
+
{hasError && (
|
|
19
|
+
<p role="alert" className={classes.errorsStyle}>
|
|
20
|
+
{helperText}
|
|
21
|
+
</p>
|
|
22
|
+
)}
|
|
23
|
+
</>
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
Input.displayName = 'Input';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Input } from './Input';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import classes from './Logo.module.css';
|
|
2
|
+
|
|
3
|
+
type LogoProps = {
|
|
4
|
+
src: string;
|
|
5
|
+
alt: string;
|
|
6
|
+
size?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const Logo = ({ src, alt, size = '80px' }: LogoProps) => {
|
|
10
|
+
return <img className={classes.logoStyle} style={{ width: size }} src={src} alt={alt} />;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Logo } from './Logo';
|