@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.
Files changed (117) hide show
  1. package/.babelrc.js +1 -0
  2. package/.commitlintrc.js +1 -0
  3. package/.editorconfig +4 -0
  4. package/.env +36 -0
  5. package/.eslintrc.js +1 -0
  6. package/.gitattributes +1 -0
  7. package/.husky/commit-msg +1 -0
  8. package/.husky/pre-commit +1 -0
  9. package/.lintstagedrc.js +5 -0
  10. package/.postcssrc.js +1 -0
  11. package/.prettierrc.js +1 -0
  12. package/.stylelintrc.js +1 -0
  13. package/CHANGELOG.md +26 -0
  14. package/LICENSE +21 -0
  15. package/README.md +221 -0
  16. package/_gitignore +26 -0
  17. package/package.json +84 -0
  18. package/public/favicon.ico +0 -0
  19. package/public/index.html +17 -0
  20. package/src/api/README.md +64 -0
  21. package/src/api/demoApi.ts +44 -0
  22. package/src/assets/README.md +51 -0
  23. package/src/assets/css/index.ts +2 -0
  24. package/src/assets/css/mainBody.css +4 -0
  25. package/src/assets/css/reset.css +131 -0
  26. package/src/assets/images/logo.png +0 -0
  27. package/src/assets/images/templatePlugins.png +0 -0
  28. package/src/bootstrap.tsx +26 -0
  29. package/src/components/App/App.tsx +18 -0
  30. package/src/components/App/index.ts +1 -0
  31. package/src/components/Footer/Footer.module.css +4 -0
  32. package/src/components/Footer/Footer.tsx +16 -0
  33. package/src/components/Footer/__tests__/Footer.test.tsx +15 -0
  34. package/src/components/Footer/__tests__/__snapshots__/Footer.test.tsx.snap +21 -0
  35. package/src/components/Footer/index.ts +1 -0
  36. package/src/components/Header/Header.module.css +7 -0
  37. package/src/components/Header/Header.tsx +17 -0
  38. package/src/components/Header/__tests__/Header.test.tsx +15 -0
  39. package/src/components/Header/__tests__/__snapshots__/Header.test.tsx.snap +35 -0
  40. package/src/components/Header/index.ts +1 -0
  41. package/src/components/README.md +34 -0
  42. package/src/components/TextInput/TextInput.tsx +24 -0
  43. package/src/components/TextInput/index.ts +1 -0
  44. package/src/config/README.md +61 -0
  45. package/src/config/index.ts +1 -0
  46. package/src/config/queryClientConfig.ts +3 -0
  47. package/src/forms/ProfileForm/ProfileForm.module.scss +10 -0
  48. package/src/forms/ProfileForm/ProfileForm.tsx +51 -0
  49. package/src/forms/ProfileForm/index.ts +1 -0
  50. package/src/forms/README.md +131 -0
  51. package/src/hooks/README.md +87 -0
  52. package/src/hooks/api/queryKey.ts +1 -0
  53. package/src/hooks/api/useDemoApi.ts +16 -0
  54. package/src/main.ts +3 -0
  55. package/src/pages/Demo/Demo.module.scss +184 -0
  56. package/src/pages/Demo/Demo.tsx +237 -0
  57. package/src/pages/Demo/ReactHookFormDemo/ReactHookFormDemo.module.css +32 -0
  58. package/src/pages/Demo/ReactHookFormDemo/ReactHookFormDemo.tsx +48 -0
  59. package/src/pages/Demo/ReactHookFormDemo/index.ts +1 -0
  60. package/src/pages/Demo/ReactHookFormDemo/routes.tsx +7 -0
  61. package/src/pages/Demo/ReactQueryDemo/ReactQueryDemo.module.scss +38 -0
  62. package/src/pages/Demo/ReactQueryDemo/ReactQueryDemo.tsx +55 -0
  63. package/src/pages/Demo/ReactQueryDemo/index.ts +1 -0
  64. package/src/pages/Demo/ReactQueryDemo/routes.tsx +7 -0
  65. package/src/pages/Demo/__tests__/Demo.test.tsx +15 -0
  66. package/src/pages/Demo/__tests__/__snapshots__/Demo.test.tsx.snap +555 -0
  67. package/src/pages/Demo/index.ts +1 -0
  68. package/src/pages/Demo/routes.tsx +8 -0
  69. package/src/pages/Error/Error.module.css +8 -0
  70. package/src/pages/Error/Error.tsx +22 -0
  71. package/src/pages/Error/index.ts +1 -0
  72. package/src/pages/Layout/Layout.tsx +12 -0
  73. package/src/pages/Layout/index.ts +1 -0
  74. package/src/pages/README.md +88 -0
  75. package/src/providers/QueryClientProvider/QueryClientProvider.tsx +16 -0
  76. package/src/providers/QueryClientProvider/index.ts +1 -0
  77. package/src/providers/README.md +115 -0
  78. package/src/providers/index.ts +1 -0
  79. package/src/providers/withProviders/index.ts +1 -0
  80. package/src/providers/withProviders/withProviders.tsx +18 -0
  81. package/src/react-app-env.d.ts +3 -0
  82. package/src/routing/README.md +80 -0
  83. package/src/routing/appRoutes.ts +5 -0
  84. package/src/routing/routerFactory.ts +10 -0
  85. package/src/routing/routes.tsx +13 -0
  86. package/src/types/README.md +61 -0
  87. package/src/types/demoApi.ts +9 -0
  88. package/src/types/profileTypes.ts +5 -0
  89. package/src/ui/README.md +141 -0
  90. package/src/ui/atoms/Input/Input.module.scss +32 -0
  91. package/src/ui/atoms/Input/Input.tsx +27 -0
  92. package/src/ui/atoms/Input/index.ts +1 -0
  93. package/src/ui/atoms/Logo/Logo.module.css +3 -0
  94. package/src/ui/atoms/Logo/Logo.tsx +11 -0
  95. package/src/ui/atoms/Logo/index.ts +1 -0
  96. package/src/ui/atoms/NavLink/NavLink.tsx +8 -0
  97. package/src/ui/atoms/NavLink/index.ts +1 -0
  98. package/src/ui/molecules/Navigation/Navigation.module.css +22 -0
  99. package/src/ui/molecules/Navigation/Navigation.tsx +25 -0
  100. package/src/ui/molecules/Navigation/index.ts +1 -0
  101. package/src/ui/organisms/Footer/Footer.module.css +10 -0
  102. package/src/ui/organisms/Footer/Footer.tsx +10 -0
  103. package/src/ui/organisms/Footer/index.ts +1 -0
  104. package/src/ui/organisms/Header/Header.module.css +17 -0
  105. package/src/ui/organisms/Header/Header.tsx +16 -0
  106. package/src/ui/organisms/Header/index.ts +1 -0
  107. package/src/ui/organisms/MainContent/MainContent.module.css +3 -0
  108. package/src/ui/organisms/MainContent/MainContent.tsx +6 -0
  109. package/src/ui/organisms/MainContent/index.ts +1 -0
  110. package/src/ui/templates/MainTemplate/MainTemplate.module.css +5 -0
  111. package/src/ui/templates/MainTemplate/MainTemplate.tsx +26 -0
  112. package/src/ui/templates/MainTemplate/index.ts +1 -0
  113. package/src/utils/README.md +68 -0
  114. package/tsconfig.json +32 -0
  115. package/vitest.config.mts +49 -0
  116. package/vitest.setup.ts +1 -0
  117. 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
+ footer {
2
+ width: 100%;
3
+ flex-grow: 0;
4
+ flex-shrink: 0;
5
+ letter-spacing: 4px;
6
+ text-align: center;
7
+ text-transform: uppercase;
8
+ color: white;
9
+ background-color: #00008f;
10
+ }
@@ -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,3 @@
1
+ main {
2
+ flex-grow: 1;
3
+ }
@@ -0,0 +1,6 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import classes from './MainContent.module.css';
3
+
4
+ export const MainContent = ({ children }: PropsWithChildren) => {
5
+ return <main className={classes.main}>{children}</main>;
6
+ };
@@ -0,0 +1 @@
1
+ export { MainContent } from './MainContent';
@@ -0,0 +1,5 @@
1
+ .mainTemplateStyle {
2
+ display: flex;
3
+ min-height: 100%;
4
+ flex-direction: column;
5
+ }
@@ -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
+ });
@@ -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
+ };