@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,8 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
import { NavLink as RouterNavLink } from 'react-router-dom';
|
|
3
|
+
|
|
4
|
+
type NavLinkProps = ComponentProps<typeof RouterNavLink>;
|
|
5
|
+
|
|
6
|
+
export const NavLink = ({ className, ...props }: NavLinkProps) => (
|
|
7
|
+
<RouterNavLink {...props} className={[className].filter(Boolean).join(' ')} />
|
|
8
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NavLink } from './NavLink';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.navList {
|
|
2
|
+
padding: 0;
|
|
3
|
+
list-style: none;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.navList li {
|
|
7
|
+
display: inline;
|
|
8
|
+
margin: 20px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@media screen and (width <= 900px) {
|
|
12
|
+
.navList li {
|
|
13
|
+
display: none;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.a {
|
|
18
|
+
letter-spacing: 4px;
|
|
19
|
+
text-decoration: none;
|
|
20
|
+
text-transform: uppercase;
|
|
21
|
+
color: white;
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NavLink } from '@Front/ui/atoms/NavLink';
|
|
2
|
+
import { useId } from 'react';
|
|
3
|
+
import classes from './Navigation.module.css';
|
|
4
|
+
|
|
5
|
+
type NavigationProps = {
|
|
6
|
+
links: { label: string; url: string }[];
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const Navigation = ({ links }: NavigationProps) => {
|
|
10
|
+
const id = useId();
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<nav>
|
|
14
|
+
<ul className={classes.navList}>
|
|
15
|
+
{links.map(link => (
|
|
16
|
+
<li key={`${id} ${link.label} ${link.url}`}>
|
|
17
|
+
<NavLink to={link.url} className={classes.a}>
|
|
18
|
+
{link.label}
|
|
19
|
+
</NavLink>
|
|
20
|
+
</li>
|
|
21
|
+
))}
|
|
22
|
+
</ul>
|
|
23
|
+
</nav>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Navigation } from './Navigation';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import classes from './Footer.module.css';
|
|
3
|
+
|
|
4
|
+
type FooterProps = {
|
|
5
|
+
footerContent?: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const Footer = ({ footerContent }: FooterProps) => {
|
|
9
|
+
return <footer className={classes.footer}>{footerContent}</footer>;
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Footer } from './Footer';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
header {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
flex-grow: 0;
|
|
5
|
+
flex-shrink: 0;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: space-between;
|
|
8
|
+
background-color: #00008f;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@media screen and (width <= 900px) {
|
|
12
|
+
header {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import classes from './Header.module.css';
|
|
3
|
+
|
|
4
|
+
type HeaderProps = {
|
|
5
|
+
leftComponents?: ReactNode;
|
|
6
|
+
rightComponents?: ReactNode;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const Header = ({ leftComponents, rightComponents }: HeaderProps) => {
|
|
10
|
+
return (
|
|
11
|
+
<header className={classes.header}>
|
|
12
|
+
{leftComponents}
|
|
13
|
+
{rightComponents}
|
|
14
|
+
</header>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Header } from './Header';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MainContent } from './MainContent';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Footer } from '@Front/ui/organisms/Footer';
|
|
2
|
+
import { Header } from '@Front/ui/organisms/Header';
|
|
3
|
+
import { MainContent } from '@Front/ui/organisms/MainContent';
|
|
4
|
+
import { PropsWithChildren, ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
import classes from './MainTemplate.module.css';
|
|
7
|
+
|
|
8
|
+
type MainTemplateProps = {
|
|
9
|
+
headerProps: {
|
|
10
|
+
leftComponents?: ReactNode;
|
|
11
|
+
rightComponents?: ReactNode;
|
|
12
|
+
};
|
|
13
|
+
footerProps: {
|
|
14
|
+
footerContent?: ReactNode;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const MainTemplate = ({ headerProps, footerProps, children }: PropsWithChildren<MainTemplateProps>) => {
|
|
19
|
+
return (
|
|
20
|
+
<div className={classes.mainTemplateStyle}>
|
|
21
|
+
<Header {...headerProps} />
|
|
22
|
+
<MainContent>{children}</MainContent>
|
|
23
|
+
<Footer {...footerProps} />
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MainTemplate } from './MainTemplate';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# 📁 utils
|
|
2
|
+
The `utils` folder contains reusable utilities and functionalities used across different parts of the application. These utilities are designed to simplify the code, promote reusability, and enhance the maintainability of the project.
|
|
3
|
+
|
|
4
|
+
## 📑 Table of Contents
|
|
5
|
+
- [Usage Example](#usage)
|
|
6
|
+
- [Best Practice](#best-practice)
|
|
7
|
+
|
|
8
|
+
## <span id="usage">🧑🏻💻 Example of usage</span>
|
|
9
|
+
|
|
10
|
+
### `formatDate.ts`
|
|
11
|
+
|
|
12
|
+
The `formatDate.ts` file contains a utility function to consistently format dates throughout the application. You can use it to display dates in various components.
|
|
13
|
+
|
|
14
|
+
Example of usage:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { formatDate } from '@Front/utils/formatDate';
|
|
18
|
+
|
|
19
|
+
const formattedDate = formatDate(new Date());
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### `apiUtils.ts`
|
|
23
|
+
|
|
24
|
+
The `apiUtils.ts` file contains utility functions to simplify API calls. You can find functions to handle HTTP requests, manipulate responses, and manage errors.
|
|
25
|
+
|
|
26
|
+
Example of usage:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { fetchData, handleResponse } from '@Front/utils/apiUtils';
|
|
30
|
+
|
|
31
|
+
async function fetchDataAndHandleError() {
|
|
32
|
+
try {
|
|
33
|
+
const data = await fetchData('https://api.example.com/data');
|
|
34
|
+
const processedData = handleResponse(data);
|
|
35
|
+
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('An error occurred while fetching data:', error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { formatDate, fetchData, handleResponse } from '@Front/utils';
|
|
45
|
+
// Use the utilities as needed
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
----------
|
|
49
|
+
***By using the "utils" folder, we organize our utilities efficiently for better reuse and simplified management.***
|
|
50
|
+
|
|
51
|
+
## <span id="best-practice">🎖️ Best Practice</span>
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
When dealing with utility functions, especially those sourced from external libraries like `date-fns`, it is advisable to follow these best practices for maintaining a structured codebase:
|
|
55
|
+
|
|
56
|
+
#### - Export Libraries from the `utils` Directory
|
|
57
|
+
|
|
58
|
+
Always export utility libraries, such as `date-fns` or others, from the `utils` directory. This practice provides a central location for managing library imports and ensures consistent usage throughout the codebase.
|
|
59
|
+
|
|
60
|
+
#### - Centralized Library Management
|
|
61
|
+
Exporting libraries through the `utils` directory establishes a centralized point for managing changes or updates to external libraries.
|
|
62
|
+
|
|
63
|
+
In case of updates, bug fixes, or changes in functionality, modifications can be made at a single location, preventing the need to update multiple parts of the codebase.
|
|
64
|
+
|
|
65
|
+
This approach contributes to better maintainability and ensures that updates to external libraries are efficiently handled.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
***By adhering to this practice, you create a clear separation between custom utility functions and external libraries, making your codebase more organized and reducing the impact of changes from external dependencies.***
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"lib": [
|
|
5
|
+
"dom",
|
|
6
|
+
"dom.iterable",
|
|
7
|
+
"esnext"
|
|
8
|
+
],
|
|
9
|
+
"types": ["./src/react-app-env.d.ts", "@pplancq/webpack-config", "vitest/globals", "@testing-library/jest-dom/vitest"],
|
|
10
|
+
"allowJs": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"allowSyntheticDefaultImports": true,
|
|
14
|
+
"strict": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"noFallthroughCasesInSwitch": true,
|
|
17
|
+
"module": "esnext",
|
|
18
|
+
"moduleResolution": "node",
|
|
19
|
+
"resolveJsonModule": true,
|
|
20
|
+
"isolatedModules": true,
|
|
21
|
+
"noEmit": true,
|
|
22
|
+
"jsx": "react-jsx",
|
|
23
|
+
"baseUrl": ".",
|
|
24
|
+
"paths": {
|
|
25
|
+
"@Front/*": ["src/*"]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"include": [
|
|
29
|
+
"src"
|
|
30
|
+
],
|
|
31
|
+
"exclude": ["node_modules"]
|
|
32
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import react from '@vitejs/plugin-react'
|
|
2
|
+
import { loadEnv } from 'vite'
|
|
3
|
+
import svgr from 'vite-plugin-svgr'
|
|
4
|
+
import viteTsconfigPaths from 'vite-tsconfig-paths'
|
|
5
|
+
import { defineConfig } from 'vitest/config'
|
|
6
|
+
|
|
7
|
+
export default defineConfig(({ mode }) => {
|
|
8
|
+
const env = loadEnv(mode, process.cwd(), '');
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
plugins: [react(), viteTsconfigPaths(), svgr()],
|
|
12
|
+
envPrefix: env.ENV_PREFIX ?? 'FRONT_',
|
|
13
|
+
test: {
|
|
14
|
+
globals: true,
|
|
15
|
+
environment: 'jsdom',
|
|
16
|
+
setupFiles: 'vitest.setup.ts',
|
|
17
|
+
clearMocks: true,
|
|
18
|
+
css: false,
|
|
19
|
+
reporters: ['basic', 'junit', 'vitest-sonar-reporter'],
|
|
20
|
+
outputFile: {
|
|
21
|
+
'vitest-sonar-reporter': 'sonar-report.xml',
|
|
22
|
+
'junit': 'junit-report.xml',
|
|
23
|
+
},
|
|
24
|
+
include: ['src/**/*.(spec|test|steps).[jt]s?(x)'],
|
|
25
|
+
poolOptions: {
|
|
26
|
+
threads: {
|
|
27
|
+
minThreads: env.CI ? 1 : undefined,
|
|
28
|
+
maxThreads: env.CI ? 2 : undefined,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
coverage: {
|
|
32
|
+
reporter: ['lcov', 'json', 'html', 'text', 'cobertura'],
|
|
33
|
+
provider: 'v8',
|
|
34
|
+
lines: 80,
|
|
35
|
+
functions: 75,
|
|
36
|
+
branches: 80,
|
|
37
|
+
statements: 80,
|
|
38
|
+
include: ['src/**/*.[jt]s?(x)'],
|
|
39
|
+
exclude: [
|
|
40
|
+
'src/**/*.d.[jt]s?(x)',
|
|
41
|
+
'src/utils/tests/**/*.[jt]s?(x)',
|
|
42
|
+
'src/**/*.types.[jt]s?(x)',
|
|
43
|
+
'src/**/index.[jt]s?(x)',
|
|
44
|
+
'src/**/*.stories.[jt]s?(x)',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
});
|
package/vitest.setup.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// const { ModuleFederationPlugin } = require('webpack').container;
|
|
2
|
+
|
|
3
|
+
// const deps = require('./package.json').dependencies;
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
extends: [require.resolve('@pplancq/webpack-config')],
|
|
7
|
+
// plugins: [
|
|
8
|
+
// new ModuleFederationPlugin({
|
|
9
|
+
// name: 'reactTemplate',
|
|
10
|
+
// filename: 'js/remoteEntry.js',
|
|
11
|
+
// remotes: {},
|
|
12
|
+
// exposes: {
|
|
13
|
+
// './App': './src/bootstrap.tsx',
|
|
14
|
+
// },
|
|
15
|
+
// shared: {
|
|
16
|
+
// react: { singleton: true, requiredVersion: deps.react },
|
|
17
|
+
// 'react-dom': { singleton: true, requiredVersion: deps['react-dom'] },
|
|
18
|
+
// 'react-router-dom': { singleton: true, requiredVersion: deps['react-router-dom'] },
|
|
19
|
+
// },
|
|
20
|
+
// }),
|
|
21
|
+
// ],
|
|
22
|
+
};
|