├── .eslintrc.json
├── .gitignore
├── .prettierrc
├── .prettierrc.json
├── LICENSE
├── README.md
├── babel.config.js
├── index.html
├── jest.config.js
├── package.json
├── pnpm-lock.yaml
├── setupTests.ts
├── src
├── App.scss
├── App.tsx
├── __mocks__
│ ├── axios.mock.tsx
│ ├── index.ts
│ ├── morty.mock.tsx
│ └── store.mock.tsx
├── __tests__
│ ├── Login.test.tsx
│ └── ModifyButton.test.tsx
├── adapters
│ ├── index.ts
│ └── user.adapter.ts
├── components
│ ├── CustomDialog.tsx
│ ├── Dialog.tsx
│ ├── Input.tsx
│ ├── RouteGuard.tsx
│ ├── Select.tsx
│ └── index.ts
├── contexts
│ ├── index.ts
│ └── selected-user.context.ts
├── favicon.svg
├── hooks
│ ├── asyncComponentClean.hook.ts
│ ├── index.ts
│ ├── useFetchAndLoad.ts
│ └── useYupValidationResolver.ts
├── index.css
├── logo.svg
├── main.tsx
├── models
│ ├── axios-call.model.ts
│ ├── index.ts
│ ├── regex.model.ts
│ ├── select-options.model.ts
│ ├── subject-manager.model.ts
│ └── user.model.ts
├── pages
│ ├── Dashboard
│ │ ├── DashboardSuperFix.tsx
│ │ └── index.ts
│ ├── Login
│ │ ├── Login.tsx
│ │ └── index.ts
│ └── index.ts
├── redux
│ ├── states
│ │ ├── index.ts
│ │ └── user.ts
│ └── store.ts
├── services
│ └── public.service.ts
├── styled-components
│ ├── index.ts
│ ├── input-error.styled.component.ts
│ └── layout.styled.component.ts
├── theme.ts
├── utilities
│ ├── format-date-mmmd.utility.ts
│ ├── format-snake-case.utility.ts
│ ├── get-yesterday-unix-utility.ts
│ ├── index.ts
│ ├── load-abort-axios.utility.ts
│ └── snackbar.utility.ts
└── vite-env.d.ts
├── svgTransform.js
├── tsconfig.json
├── vercel.json
├── vite.config.ts
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "airbnb",
4 | "plugin:prettier/recommended",
5 | "prettier/react"
6 | ],
7 | "env": {
8 | "browser": true,
9 | "commonjs": true,
10 | "es6": true,
11 | "jest": true,
12 | "node": true
13 | },
14 | "rules": {
15 | "jsx-a11y/href-no-hash": ["off"],
16 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }],
17 | "max-len": [
18 | "warn",
19 | {
20 | "code": 140,
21 | "tabWidth": 2,
22 | "comments": 140,
23 | "ignoreComments": false,
24 | "ignoreTrailingComments": true,
25 | "ignoreUrls": true,
26 | "ignoreStrings": true,
27 | "ignoreTemplateLiterals": true,
28 | "ignoreRegExpLiterals": true
29 | }
30 | ]
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
6 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "printWidth": 140,
4 | "trailingComma": "none"
5 | }
6 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "singleQuote": true,
4 | "trailingComma": "all"
5 | }
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Alan Buscaglia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Estructura de Proyecto de ReactJs con Clean Architecture - Documentación Detallada
2 |
3 | **Autor**: Gentleman
4 |
5 | **Fuente del Video**: [Cómo estructurar tu project de ReactJs? Aplicamos Clean Architecture en Front End - #part1](https://www.youtube.com/watch?v=5LqhlCd2_nE)
6 |
7 | ## Introducción
8 |
9 | Este documento proporciona una guía detallada sobre la aplicación de la Clean Architecture en proyectos de ReactJs, orientándonos hacia una estructuración eficiente y una gestión eficaz del estado y de los componentes.
10 |
11 | ## Clean Architecture
12 |
13 | ### Conceptos Básicos
14 |
15 | - **Dominio/Modelos/State**: Define las entidades y su estado durante el ciclo de vida de la aplicación.
16 | - **Casos de Uso**: Operaciones que se pueden realizar sobre los modelos.
17 | - **Adaptadores**: Facilitan la conversión de datos externos para que puedan ser manejados por la aplicación.
18 |
19 | ### Beneficios
20 |
21 | - Organización clara del código.
22 | - Facilidad de mantenimiento.
23 | - Escalabilidad del proyecto.
24 |
25 | ## Estructura de Carpetas Sugerida
26 |
27 | ```
28 | src/
29 | ├── adapters/
30 | │ ├── index.js
31 | │ └── userAdapter.js
32 | ├── components/
33 | │ ├── UserComponent.jsx
34 | │ └── AdminComponent.jsx
35 | ├── models/
36 | │ └── userModel.js
37 | ├── hooks/
38 | │ ├── useUser.js
39 | │ └── useAdmin.js
40 | ├── services/
41 | │ └── userService.js
42 | ├── utilities/
43 | │ └── formatter.js
44 | ├── interceptors/
45 | │ └── authInterceptor.js
46 | ├── contexts/
47 | │ └── UserContext.js
48 | └── pages/
49 | └── Home/
50 | ├── Home.jsx
51 | ├── components/
52 | │ └── HomeButton.jsx
53 | ├── models/
54 | │ └── homeModel.js
55 | ├── hooks/
56 | │ └── useHomeLogic.js
57 | ├── services/
58 | │ └── homeService.js
59 | └── utilities/
60 | └── homeFormatter.js
61 | ```
62 |
63 | ### Descripción Detallada de la Estructura
64 |
65 | #### Pages/Home
66 |
67 | La carpeta `Home` funciona como un contenedor (Container Pattern), encapsulando toda la lógica y los componentes específicos de la página de inicio. Esto permite una mejor organización y un enfoque modular:
68 |
69 | - **Home.jsx**: El componente principal que actúa como el contenedor.
70 | - **Components**: Componentes específicos de la página Home, como `HomeButton.jsx`.
71 | - **Models**: Define modelos específicos utilizados en la página Home.
72 | - **Hooks**: Hooks personalizados para la lógica de negocio de la página Home.
73 | - **Services**: Servicios que interactúan con APIs o recursos externos específicos para Home.
74 | - **Utilities**: Herramientas y funciones de ayuda específicas para la página Home.
75 |
76 | ### La Regla del Alcance
77 |
78 | La regla del alcance es fundamental para entender y organizar la reutilización y la carga perezosa de componentes:
79 |
80 | - **Components en Root**: Accesibles y reutilizables por toda la aplicación.
81 | - **Components en Funcionalidades Específicas**: Utilizados solo dentro de su contexto específico, como en la carpeta `Home`.
82 |
83 | ### Beneficios de la Regla del Alcance
84 |
85 | - **Claridad y Escalabilidad**: Facilita la comprensión del alcance y uso de los componentes, y mejora la escalabilidad del proyecto.
86 | - **Optimización de la Carga**: Permite una carga más eficiente al cargar solo los componentes necesarios para la funcionalidad solicitada.
87 |
88 | ## Conclusión
89 |
90 | Adoptar la Clean Architecture en ReactJs con un enfoque estructurado y modular facilita el desarrollo y mantenimiento de aplicaciones complejas y escalables. La inclusión del patrón de contenedor dentro de las páginas específicas, como se muestra en la carpeta `Home`, proporciona un marco claro para la organización y optimización de los componentes y la lógica de negocio.
91 |
92 | ### Patrón Contenedor en la Estructura de Carpetas de ReactJs
93 |
94 | #### Uso del Patrón Contenedor
95 |
96 | El patrón contenedor es una estrategia de diseño que encapsula los componentes y la lógica específicos de una funcionalidad dentro de su propia subcarpeta bajo `pages`. Esto facilita la organización modular del código y mejora la carga perezosa de los componentes. Aquí te muestro cómo se implementa típicamente dentro de la carpeta `Home`:
97 |
98 | ```
99 | src/
100 | └── pages/
101 | └── Home/
102 | ├── Home.jsx # Contenedor principal
103 | ├── components/ # Componentes específicos de Home
104 | │ └── HomeButton.jsx
105 | ├── models/ # Modelos usados en Home
106 | │ └── homeModel.js
107 | ├── hooks/ # Hooks específicos de Home
108 | │ └── useHomeLogic.js
109 | ├── services/ # Servicios usados por Home
110 | │ └── homeService.js
111 | └── utilities/ # Funciones auxiliares para Home
112 | └── homeFormatter.js
113 | ```
114 |
115 | #### Detalles del Patrón Contenedor
116 |
117 | - **Home.jsx**: Actúa como el componente principal que coordina y gestiona los otros componentes específicos dentro de la carpeta `Home`. Este componente funciona como un "contenedor" que encapsula toda la lógica y estado específicos de la página de inicio.
118 | - **Components**: Contiene todos los componentes visuales que solo son relevantes para la página `Home`. Por ejemplo, `HomeButton.jsx` podría ser un botón personalizado solo usado en esta página.
119 | - **Models**: Define estructuras de datos que son únicas para la página `Home`, como `homeModel.js` que podría contener definiciones de estado y lógica de negocio específicas.
120 | - **Hooks**: Agrupa todos los hooks que son utilizados únicamente dentro de la página `Home`, como `useHomeLogic.js`, que puede contener lógica de manejo de estado o efectos secundarios.
121 | - **Services**: Los servicios que realiza llamadas a APIs o realiza operaciones de datos que solo conciernen a la página `Home`.
122 | - **Utilities**: Funciones de ayuda o herramientas específicas que son utilizadas solamente dentro del contexto de `Home`, como formateadores, validadores, o calculadoras.
123 |
124 | #### Beneficios del Patrón Contenedor
125 |
126 | - **Encapsulación**: Aísla la lógica y componentes de una página específica, haciendo el código más fácil de entender y mantener.
127 | - **Modularidad**: Facilita el manejo de cada funcionalidad como un módulo independiente, lo cual es ideal para el mantenimiento y la prueba de unidades.
128 | - **Optimización de la Carga**: Mejora la carga perezosa al asegurar que solo se carguen los recursos necesarios cuando se accede a la página `Home`.
129 |
130 | ---
131 |
132 | Este enfoque del patrón contenedor en la estructura del proyecto de ReactJs es crucial para mantener una arquitectura limpia y organizada, asegurando que cada componente y pieza de lógica tenga un lugar bien definido y un propósito claro.
133 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [['es2015', '@babel/preset-env', '@babel/preset-react'], '@babel/preset-typescript'],
3 | };
4 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // The root of your source code, typically /src
3 | // `` is a token Jest substitutes
4 | roots: ['/src'],
5 |
6 | // Jest transformations -- this adds support for TypeScript
7 | // using ts-jest
8 | transform: {
9 | '^.+\\.tsx?$': 'ts-jest',
10 | '^.+\\.ts?$': 'ts-jest',
11 | '^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '/svgTransform.js'
12 | },
13 | // testPathIgnorePatterns: ['./node_modules/'],
14 | // Test spec file resolution pattern
15 | // Matches parent folder `__tests__` and filename
16 | // should contain `test` or `spec`.
17 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
18 |
19 | // Module file extensions for importing
20 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
21 | moduleNameMapper: {
22 | '^@/(.*)$': '/src/$1',
23 | '^.+\\.(css|less|scss)$': 'babel-jest',
24 | d3: '/node_modules/d3/dist/d3.min.js'
25 | },
26 | testEnvironment: 'jsdom',
27 | setupFilesAfterEnv: ['/setupTests.ts']
28 | };
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gp-react-js",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "build": "vite build",
6 | "local": "vite",
7 | "staging": "vite --mode staging",
8 | "dev": "vite --mode dev",
9 | "prod": "vite --mode prod",
10 | "serve": "vite preview",
11 | "test": "jest",
12 | "test:coverage": "jest --coverage",
13 | "test:watch": "jest --watch",
14 | "analyze": "source-map-explorer 'build/static/js/*.js'"
15 | },
16 | "dependencies": {
17 | "@emotion/react": "^11.8.1",
18 | "@emotion/styled": "^11.8.1",
19 | "@mui/icons-material": "^5.4.4",
20 | "@mui/material": "^5.4.4",
21 | "@mui/styled-engine-sc": "^5.4.2",
22 | "@mui/x-data-grid": "^5.5.1",
23 | "@reduxjs/toolkit": "^1.8.0",
24 | "axios": "^0.26.0",
25 | "context": "^1.2.1",
26 | "d3": "^7.3.0",
27 | "eslint": "^8.10.0",
28 | "eslint-plugin-react-hooks": "^4.3.0",
29 | "install": "^0.13.0",
30 | "notistack": "^2.0.3",
31 | "react": "^17.0.2",
32 | "react-dom": "^17.0.2",
33 | "react-hook-form": "^7.27.1",
34 | "react-is": "^17.0.2",
35 | "react-redux": "^7.2.6",
36 | "react-router": "^6.2.2",
37 | "react-router-dom": "^6.2.2",
38 | "sass": "^1.49.9",
39 | "styled-components": "^5.3.3",
40 | "yup": "^0.32.11"
41 | },
42 | "devDependencies": {
43 | "@babel/core": "^7.17.5",
44 | "@babel/eslint-parser": "^7.17.0",
45 | "@babel/preset-env": "^7.16.11",
46 | "@babel/preset-react": "^7.16.7",
47 | "@testing-library/dom": "^8.11.3",
48 | "@testing-library/jest-dom": "^5.16.2",
49 | "@testing-library/react": "^12.1.3",
50 | "@testing-library/user-event": "^13.5.0",
51 | "@types/d3": "^7.1.0",
52 | "@types/jest": "^27.4.1",
53 | "@types/react": "^17.0.39",
54 | "@types/react-dom": "^17.0.13",
55 | "@types/react-redux": "^7.1.23",
56 | "@types/react-router": "^5.1.18",
57 | "@types/styled-components": "^5.1.24",
58 | "@vitejs/plugin-react": "^1.2.0",
59 | "babel-jest": "^27.5.1",
60 | "eslint-config-airbnb": "^19.0.4",
61 | "eslint-config-prettier": "^8.5.0",
62 | "eslint-plugin-import": "^2.25.4",
63 | "eslint-plugin-jsx-a11y": "^6.5.1",
64 | "eslint-plugin-prettier": "^4.0.0",
65 | "eslint-plugin-react": "^7.29.3",
66 | "jest": "^27.5.1",
67 | "prettier": "^2.5.1",
68 | "react-test-renderer": "^17.0.2",
69 | "rollup": "^2.69.1",
70 | "rxjs": "^7.5.4",
71 | "source-map-explorer": "^2.5.2",
72 | "ts-jest": "^27.1.3",
73 | "typescript": "^4.6.2",
74 | "vite": "^2.8.6"
75 | },
76 | "main": "babel.config.js",
77 | "repository": {
78 | "type": "git",
79 | "url": "git+https://github.com/erudit-ai/Erudit-Front-End.git"
80 | },
81 | "keywords": [],
82 | "author": "",
83 | "license": "ISC",
84 | "bugs": {
85 | "url": "https://github.com/erudit-ai/Erudit-Front-End/issues"
86 | },
87 | "homepage": "https://github.com/erudit-ai/Erudit-Front-End#readme",
88 | "description": ""
89 | }
90 |
--------------------------------------------------------------------------------
/setupTests.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/extend-expect';
2 |
--------------------------------------------------------------------------------
/src/App.scss:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
40 | button {
41 | font-size: calc(10px + 2vmin);
42 | }
43 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import store from '@/redux/store';
2 | import { ThemeProvider } from '@emotion/react';
3 | import { SnackbarProvider } from 'notistack';
4 | import React, { lazy, Suspense } from 'react';
5 | import { Provider } from 'react-redux';
6 | import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
7 | import './App.scss';
8 | import { AppContainer } from './styled-components';
9 | import theme from './theme';
10 | import { SnackbarUtilsConfigurator } from './utilities';
11 |
12 | // Routes
13 | const DashboardSuperFix = lazy(() => import('@/pages/Dashboard/DashboardSuperFix'));
14 | const Login = lazy(() => import('@/pages/Login/Login'));
15 |
16 | const App = () => {
17 | return (
18 |
19 |
20 |
21 |
22 |
23 | Loading ...}>
24 |
25 |
26 |
27 | } />
28 | } />
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | );
38 | };
39 |
40 | export default App;
41 |
--------------------------------------------------------------------------------
/src/__mocks__/axios.mock.tsx:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export const axiosMock = axios as jest.Mocked;
4 |
--------------------------------------------------------------------------------
/src/__mocks__/index.ts:
--------------------------------------------------------------------------------
1 | export * from './axios.mock';
2 | export * from './morty.mock';
3 | export * from './store.mock';
4 |
--------------------------------------------------------------------------------
/src/__mocks__/morty.mock.tsx:
--------------------------------------------------------------------------------
1 | export const mortyMock = {
2 | id: 2,
3 | name: 'Morty Smith',
4 | status: 'Alive',
5 | species: 'Human',
6 | type: '',
7 | gender: 'Male',
8 | origin: { name: 'unknown', url: '' },
9 | location: { name: 'Citadel of Ricks', url: 'https://rickandmortyapi.com/api/location/3' },
10 | image: 'https://rickandmortyapi.com/api/character/avatar/2.jpeg',
11 | episode: [
12 | 'https://rickandmortyapi.com/api/episode/1',
13 | 'https://rickandmortyapi.com/api/episode/2',
14 | 'https://rickandmortyapi.com/api/episode/3',
15 | 'https://rickandmortyapi.com/api/episode/4',
16 | 'https://rickandmortyapi.com/api/episode/5',
17 | 'https://rickandmortyapi.com/api/episode/6',
18 | 'https://rickandmortyapi.com/api/episode/7',
19 | 'https://rickandmortyapi.com/api/episode/8',
20 | 'https://rickandmortyapi.com/api/episode/9',
21 | 'https://rickandmortyapi.com/api/episode/10',
22 | 'https://rickandmortyapi.com/api/episode/11',
23 | 'https://rickandmortyapi.com/api/episode/12',
24 | 'https://rickandmortyapi.com/api/episode/13',
25 | 'https://rickandmortyapi.com/api/episode/14',
26 | 'https://rickandmortyapi.com/api/episode/15',
27 | 'https://rickandmortyapi.com/api/episode/16',
28 | 'https://rickandmortyapi.com/api/episode/17',
29 | 'https://rickandmortyapi.com/api/episode/18',
30 | 'https://rickandmortyapi.com/api/episode/19',
31 | 'https://rickandmortyapi.com/api/episode/20',
32 | 'https://rickandmortyapi.com/api/episode/21',
33 | 'https://rickandmortyapi.com/api/episode/22',
34 | 'https://rickandmortyapi.com/api/episode/23',
35 | 'https://rickandmortyapi.com/api/episode/24',
36 | 'https://rickandmortyapi.com/api/episode/25',
37 | 'https://rickandmortyapi.com/api/episode/26',
38 | 'https://rickandmortyapi.com/api/episode/27',
39 | 'https://rickandmortyapi.com/api/episode/28',
40 | 'https://rickandmortyapi.com/api/episode/29',
41 | 'https://rickandmortyapi.com/api/episode/30',
42 | 'https://rickandmortyapi.com/api/episode/31',
43 | 'https://rickandmortyapi.com/api/episode/32',
44 | 'https://rickandmortyapi.com/api/episode/33',
45 | 'https://rickandmortyapi.com/api/episode/34',
46 | 'https://rickandmortyapi.com/api/episode/35',
47 | 'https://rickandmortyapi.com/api/episode/36',
48 | 'https://rickandmortyapi.com/api/episode/37',
49 | 'https://rickandmortyapi.com/api/episode/38',
50 | 'https://rickandmortyapi.com/api/episode/39',
51 | 'https://rickandmortyapi.com/api/episode/40',
52 | 'https://rickandmortyapi.com/api/episode/41',
53 | 'https://rickandmortyapi.com/api/episode/42',
54 | 'https://rickandmortyapi.com/api/episode/43',
55 | 'https://rickandmortyapi.com/api/episode/44',
56 | 'https://rickandmortyapi.com/api/episode/45',
57 | 'https://rickandmortyapi.com/api/episode/46',
58 | 'https://rickandmortyapi.com/api/episode/47',
59 | 'https://rickandmortyapi.com/api/episode/48',
60 | 'https://rickandmortyapi.com/api/episode/49',
61 | 'https://rickandmortyapi.com/api/episode/50',
62 | 'https://rickandmortyapi.com/api/episode/51'
63 | ],
64 | url: 'https://rickandmortyapi.com/api/character/2',
65 | created: '2017-11-04T18:50:21.651Z'
66 | };
67 |
--------------------------------------------------------------------------------
/src/__mocks__/store.mock.tsx:
--------------------------------------------------------------------------------
1 | import { userSlice } from '@/redux/states/user';
2 | import { AppStore } from '@/redux/store';
3 | import { configureStore } from '@reduxjs/toolkit';
4 |
5 | export const store = configureStore({
6 | reducer: {
7 | user: userSlice.reducer
8 | }
9 | });
10 |
--------------------------------------------------------------------------------
/src/__tests__/Login.test.tsx:
--------------------------------------------------------------------------------
1 | import { Login } from '@/pages';
2 | import store from '@/redux/store';
3 | import { axiosMock, mortyMock } from '@/__mocks__';
4 | import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react/pure';
5 | import { Provider } from 'react-redux';
6 |
7 | jest.mock('axios');
8 |
9 | jest.mock('@/pages/Login/components/ModifyButton', () => ({
10 | __esModule: true,
11 | default: () => mocked ModifyButton
12 | }));
13 |
14 | describe('Login', () => {
15 | const mockedAxios = axiosMock;
16 | mockedAxios.get.mockResolvedValue({ data: mortyMock });
17 | afterEach(jest.clearAllMocks);
18 | afterEach(cleanup);
19 |
20 | it('renders Logic component', async () => {
21 | const component = render(
22 |
23 |
24 |
25 | );
26 | expect(component).toBeTruthy;
27 | });
28 |
29 | it('has to call the login endpoint and update the store', async () => {
30 | render(
31 |
32 |
33 |
34 | );
35 | const button = screen.getByRole('button', { name: 'Login' });
36 | expect(button).toBeInTheDocument();
37 | fireEvent.click(button);
38 | await waitFor(() => {
39 | expect(mockedAxios.get).toHaveBeenCalled();
40 | expect(screen.getByText('{"name":"Morty Smith","gender":"Male","status":"Alive"}'));
41 | });
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/src/__tests__/ModifyButton.test.tsx:
--------------------------------------------------------------------------------
1 | import { ModifyButton } from '@/pages';
2 | import store from '@/redux/store';
3 | import { cleanup, render, screen, fireEvent, waitFor } from '@testing-library/react/pure';
4 | import { Provider } from 'react-redux';
5 |
6 | jest.mock('axios');
7 |
8 | describe('ModifyButton', () => {
9 | afterEach(jest.clearAllMocks);
10 | afterEach(cleanup);
11 |
12 | it('renders ModifyButton component', async () => {
13 | const component = render(
14 |
15 |
16 |
17 | );
18 | expect(component).toBeTruthy;
19 | });
20 |
21 | it('has to modify the user state on modify button click', async () => {
22 | render(
23 |
24 |
25 |
26 | );
27 | const button = screen.getByRole('button', { name: 'Modify User' });
28 | expect(button).toBeInTheDocument();
29 | fireEvent.click(button);
30 | await waitFor(() => {
31 | expect(store.getState().user).toEqual({ name: 'Carlos', gender: '', status: '' });
32 | });
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/src/adapters/index.ts:
--------------------------------------------------------------------------------
1 | export * from './user.adapter';
2 |
--------------------------------------------------------------------------------
/src/adapters/user.adapter.ts:
--------------------------------------------------------------------------------
1 | export const createUserAdapter = (user: any) => ({
2 | name: user.data.name,
3 | gender: user.data.gender,
4 | status: user.data.status
5 | });
6 |
--------------------------------------------------------------------------------
/src/components/CustomDialog.tsx:
--------------------------------------------------------------------------------
1 | import { SubjectManager } from '@/models/subject-manager.model';
2 | import Dialog from '@mui/material/Dialog';
3 | import { useEffect, useState } from 'react';
4 | import { Subscription } from 'rxjs';
5 |
6 | interface Props {
7 | children: React.ReactNode;
8 | }
9 |
10 | export const dialogOpenSubject$ = new SubjectManager();
11 | export const dialogCloseSubject$ = new SubjectManager();
12 |
13 | export const CustomDialog = ({ children }: Props) => {
14 | const [open, setOpen] = useState(false);
15 | let openSubject$ = new Subscription();
16 | let closeSubject$ = new Subscription();
17 |
18 | useEffect(() => {
19 | openSubject$ = dialogOpenSubject$.getSubject.subscribe(() => handleClickOpen());
20 | closeSubject$ = dialogCloseSubject$.getSubject.subscribe(() => handleClose());
21 | return () => {
22 | openSubject$.unsubscribe();
23 | closeSubject$.unsubscribe();
24 | };
25 | }, []);
26 |
27 | const handleClickOpen = () => {
28 | setOpen(true);
29 | };
30 |
31 | const handleClose = () => {
32 | setOpen(false);
33 | };
34 |
35 | const handleExit = () => {
36 | dialogCloseSubject$.setSubject = false;
37 | };
38 |
39 | return (
40 |
41 | handleExit()} aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description">
42 | {children}
43 |
44 |
45 | );
46 | };
47 |
48 | export default CustomDialog;
49 |
--------------------------------------------------------------------------------
/src/components/Dialog.tsx:
--------------------------------------------------------------------------------
1 | import { SubjectManager } from '@/models/subject-manager.model';
2 | import Button from '@mui/material/Button';
3 | import Dialog from '@mui/material/Dialog';
4 | import DialogActions from '@mui/material/DialogActions';
5 | import React, { useEffect, useState } from 'react';
6 | import { Subscription } from 'rxjs';
7 |
8 | interface Props {
9 | children: React.ReactNode;
10 | }
11 |
12 | export const dialogOpenSubject$ = new SubjectManager();
13 | export const dialogCloseSubject$ = new SubjectManager();
14 |
15 | export const AlertDialog = ({ children }: Props) => {
16 | const [open, setOpen] = useState(false);
17 | let openSubject$ = new Subscription();
18 | let closeSubject$ = new Subscription();
19 |
20 | useEffect(() => {
21 | // inicio, cambios
22 | return () => {
23 | //destruccion
24 | };
25 | }, []);
26 | useEffect(() => {
27 | openSubject$ = dialogOpenSubject$.getSubject.subscribe(() => handleClickOpen());
28 | return () => {
29 | openSubject$.unsubscribe();
30 | closeSubject$.unsubscribe();
31 | };
32 | }, []);
33 | const handleClickOpen = () => {
34 | setOpen(true);
35 | dialogCloseSubject$.setSubject = true;
36 | };
37 |
38 | const handleClose = (value = false) => {
39 | setOpen(false);
40 | dialogCloseSubject$.setSubject = value;
41 | };
42 |
43 | return (
44 |
45 | handleClose(false)}
48 | aria-labelledby="alert-dialog-title"
49 | aria-describedby="alert-dialog-description"
50 | >
51 | {children}
52 |
53 | handleClose(false)} data-testid="dialog-cancel">
54 | Cancel
55 |
56 | handleClose(true)} data-testid="dialog-confirm" autoFocus>
57 | Confirm
58 |
59 |
60 |
61 |
62 | );
63 | };
64 |
65 | export default AlertDialog;
66 |
--------------------------------------------------------------------------------
/src/components/Input.tsx:
--------------------------------------------------------------------------------
1 | import { InputError } from '@/styled-components';
2 | import { InputBaseProps, TextField } from '@mui/material';
3 | import { FieldErrors, UseFormRegister, UseFormTrigger } from 'react-hook-form';
4 |
5 | const formValidation = (errors: FieldErrors, errorKey: string) => {
6 | return errors[errorKey] ? {errors[errorKey].message} : '';
7 | };
8 |
9 | interface InputProps {
10 | register: UseFormRegister;
11 | name: string;
12 | errors?: FieldErrors;
13 | label?: string;
14 | type: InputType;
15 | inputProps?: InputBaseProps['inputProps'];
16 | disabled?: boolean;
17 | trigger?: UseFormTrigger;
18 | }
19 |
20 | export enum InputType {
21 | NUMBER = 'number',
22 | PASSWORD = 'password',
23 | SEARCH = 'search',
24 | TEXT = 'text',
25 | HIDDEN = 'hidden',
26 | CHECKBOX = 'checkbox'
27 | }
28 |
29 | export const Input = ({ register, name, errors, label = '', type, inputProps, disabled = false, trigger }: InputProps) => {
30 | return (
31 |
32 | trigger && trigger()}
43 | fullWidth
44 | />
45 | {errors && formValidation(errors, name)}
46 |
47 | );
48 | };
49 |
50 | export default Input;
51 |
--------------------------------------------------------------------------------
/src/components/RouteGuard.tsx:
--------------------------------------------------------------------------------
1 | import { AppStore } from '@/redux/store';
2 | import { useSelector } from 'react-redux';
3 | import { Navigate, Outlet } from 'react-router-dom';
4 |
5 | export const RouteGuard = () => {
6 | const userState = useSelector((state: AppStore) => state.user);
7 | return userState.name ? : ;
8 | };
9 |
10 | export default RouteGuard;
11 |
--------------------------------------------------------------------------------
/src/components/Select.tsx:
--------------------------------------------------------------------------------
1 | import { SelectOption } from '@/models';
2 | import { InputError } from '@/styled-components';
3 | import { InputBaseProps, MenuItem, TextField } from '@mui/material';
4 | import { FieldErrors, UseFormRegister } from 'react-hook-form';
5 |
6 | const formValidation = (errors: FieldErrors, errorKey: string) => {
7 | return errors[errorKey] ? {errors[errorKey].message} : '';
8 | };
9 |
10 | interface SelectProps {
11 | register: UseFormRegister;
12 | name: string;
13 | errors: FieldErrors;
14 | label: string;
15 | options: SelectOption[];
16 | inputProps?: InputBaseProps['inputProps'];
17 | }
18 |
19 | export const CustomSelect = ({ register, name, errors, label, options, inputProps }: SelectProps) => {
20 | return (
21 |
22 |
35 | {options.map((option) => (
36 |
37 | {option.label}
38 |
39 | ))}
40 |
41 | {formValidation(errors, name)}
42 |
43 | );
44 | };
45 |
46 | export default CustomSelect;
47 |
--------------------------------------------------------------------------------
/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export { default as CustomDialog } from './CustomDialog';
2 | export { default as Dialog } from './Dialog';
3 | export { default as Input } from './Input';
4 | export { default as RouteGuard } from './RouteGuard';
5 | export { default as Select } from './Select';
6 |
--------------------------------------------------------------------------------
/src/contexts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './selected-user.context';
2 |
--------------------------------------------------------------------------------
/src/contexts/selected-user.context.ts:
--------------------------------------------------------------------------------
1 | import { User } from '@/models';
2 | import { createContext } from 'react';
3 |
4 | export const SelectedUserContext = createContext({
5 | selectedUser: {} as User,
6 | setSelectedUser: (user: User) => {}
7 | });
8 |
--------------------------------------------------------------------------------
/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/hooks/asyncComponentClean.hook.ts:
--------------------------------------------------------------------------------
1 | import { AxiosResponse } from 'axios';
2 | import { useEffect } from 'react';
3 |
4 | export const useAsync = (
5 | asyncFn: () => Promise>,
6 | successFunction: Function,
7 | returnFunction: Function,
8 | dependencies: any[] = []
9 | ) => {
10 | useEffect(() => {
11 | let isActive = true;
12 | asyncFn().then((result) => {
13 | if (isActive) successFunction(result.data);
14 | });
15 | return () => {
16 | returnFunction && returnFunction();
17 | isActive = false;
18 | };
19 | }, dependencies);
20 | };
21 |
--------------------------------------------------------------------------------
/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './asyncComponentClean.hook';
2 | export { default as useFetchAndLoad } from './useFetchAndLoad';
3 | export * from './useYupValidationResolver';
4 |
--------------------------------------------------------------------------------
/src/hooks/useFetchAndLoad.ts:
--------------------------------------------------------------------------------
1 | import { AxiosCall } from '@/models';
2 | import { AxiosResponse } from 'axios';
3 | import { useEffect, useState } from 'react';
4 |
5 | const useFetchAndLoad = () => {
6 | const [loading, setLoading] = useState(false);
7 | let controller: AbortController;
8 |
9 | const callEndpoint = async (axiosCall: AxiosCall) => {
10 | if (axiosCall.controller) controller = axiosCall.controller;
11 | setLoading(true);
12 | let result = {} as AxiosResponse;
13 | try {
14 | result = await axiosCall.call;
15 | } catch (err: any) {
16 | setLoading(false);
17 | throw err;
18 | }
19 | setLoading(false);
20 | return result;
21 | };
22 |
23 | const cancelEndpoint = () => {
24 | setLoading(false);
25 | controller && controller.abort();
26 | };
27 |
28 | useEffect(() => {
29 | return () => {
30 | cancelEndpoint();
31 | };
32 | }, []);
33 |
34 | return { loading, callEndpoint };
35 | };
36 |
37 | export default useFetchAndLoad;
38 |
--------------------------------------------------------------------------------
/src/hooks/useYupValidationResolver.ts:
--------------------------------------------------------------------------------
1 | import { useCallback } from 'react';
2 |
3 | export const useYupValidationResolver = (validationSchema: any) =>
4 | useCallback(
5 | async (data) => {
6 | try {
7 | const values = await validationSchema.validate(data, {
8 | abortEarly: false
9 | });
10 |
11 | return {
12 | values,
13 | errors: {}
14 | };
15 | } catch (errors: any) {
16 | return {
17 | values: {},
18 | errors: errors.inner.reduce(
19 | (
20 | allErrors: any,
21 | currentError: { path: any; type: any; message: any }
22 | ) => ({
23 | ...allErrors,
24 | [currentError.path]: {
25 | type: currentError.type ?? 'validation',
26 | message: currentError.message
27 | }
28 | }),
29 | {}
30 | )
31 | };
32 | }
33 | },
34 | [validationSchema]
35 | );
36 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import './index.css'
4 | import App from './App'
5 |
6 | ReactDOM.render(
7 |
8 |
9 | ,
10 | document.getElementById('root')
11 | )
12 |
--------------------------------------------------------------------------------
/src/models/axios-call.model.ts:
--------------------------------------------------------------------------------
1 | import { AxiosResponse } from 'axios';
2 |
3 | export interface AxiosCall {
4 | call: Promise>;
5 | controller?: AbortController;
6 | }
7 |
--------------------------------------------------------------------------------
/src/models/index.ts:
--------------------------------------------------------------------------------
1 | export * from './axios-call.model';
2 | export * from './regex.model';
3 | export * from './select-options.model';
4 | export * from './subject-manager.model';
5 | export * from './user.model';
6 |
--------------------------------------------------------------------------------
/src/models/regex.model.ts:
--------------------------------------------------------------------------------
1 | export const PasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[$*.{}?"!@#%&/,><':;|_~`^\]\[)(]).{8,99}/;
2 | export const EmailRegex = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/;
3 | export const DomainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9](?:\.[a-zA-Z]{2,})+$/;
4 |
--------------------------------------------------------------------------------
/src/models/select-options.model.ts:
--------------------------------------------------------------------------------
1 | export interface SelectOption {
2 | label: string;
3 | value: string;
4 | }
5 |
--------------------------------------------------------------------------------
/src/models/subject-manager.model.ts:
--------------------------------------------------------------------------------
1 | import { Subject } from 'rxjs';
2 |
3 | export class SubjectManager {
4 | private subject = new Subject();
5 |
6 | get getSubject() {
7 | return this.subject.asObservable();
8 | }
9 |
10 | set setSubject(value: T) {
11 | this.subject.next(value);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/models/user.model.ts:
--------------------------------------------------------------------------------
1 | export interface User {
2 | name: string;
3 | gender: string;
4 | status: string;
5 | }
6 |
--------------------------------------------------------------------------------
/src/pages/Dashboard/DashboardSuperFix.tsx:
--------------------------------------------------------------------------------
1 | import { useAsync, useFetchAndLoad } from '@/hooks';
2 | import { getCoolMorty, getCoolRick } from '@/services/public.service';
3 | import { LayoutContainer } from '@/styled-components';
4 | import { Tab, Tabs } from '@mui/material';
5 | import { useState } from 'react';
6 |
7 | const Component1 = () => {
8 | const { loading, callEndpoint } = useFetchAndLoad();
9 | const [morty, setMorty] = useState(null);
10 | const getApiData = async () => await callEndpoint(getCoolMorty());
11 |
12 | const adaptMorty = (data: any) => {
13 | setMorty(data.name);
14 | };
15 |
16 | useAsync(getApiData, adaptMorty, () => {});
17 | return {loading ? 'LOADING' : morty}
;
18 | };
19 |
20 | function Component2() {
21 | const { loading, callEndpoint } = useFetchAndLoad();
22 | const [rick, setRick] = useState(null);
23 |
24 | const getApiData = async () => await callEndpoint(getCoolRick());
25 |
26 | const adaptRick = (data: any) => {
27 | setRick(data.name);
28 | };
29 |
30 | useAsync(getApiData, adaptRick, () => {}, []);
31 | return {loading ? 'LOADING' : rick}
;
32 | }
33 |
34 | export const DashboardSuperFix = () => {
35 | const [value, setValue] = useState(0);
36 |
37 | const handleChange = (event: any, newValue: any) => {
38 | setValue(newValue);
39 | };
40 |
41 | function a11yProps(index: number) {
42 | return {
43 | id: `simple-tab-${index}`,
44 | 'aria-controls': `simple-tabpanel-${index}`
45 | };
46 | }
47 |
48 | return (
49 |
50 |
51 |
Buenas buenas mi gente !
52 |
53 |
54 |
55 |
56 |
{value === 0 ? : }
57 |
58 |
59 | );
60 | };
61 |
62 | export default DashboardSuperFix;
63 |
--------------------------------------------------------------------------------
/src/pages/Dashboard/index.ts:
--------------------------------------------------------------------------------
1 | export { default as DashboardSuperFix } from './DashboardSuperFix';
2 |
--------------------------------------------------------------------------------
/src/pages/Login/Login.tsx:
--------------------------------------------------------------------------------
1 | import { createUserAdapter } from '@/adapters';
2 | import { useFetchAndLoad } from '@/hooks';
3 | import { createUser, modifyUser } from '@/redux/states/user';
4 | import { AppStore } from '@/redux/store';
5 | import { login } from '@/services/public.service';
6 | import { Button } from '@mui/material';
7 | import { useDispatch, useSelector } from 'react-redux';
8 |
9 | export const Login = () => {
10 | const { loading, callEndpoint } = useFetchAndLoad();
11 | const dispatch = useDispatch();
12 | const userState = useSelector((store: AppStore) => store.user);
13 | const handleClick = async () => {
14 | const morty = await callEndpoint(login());
15 | dispatch(createUser(createUserAdapter(morty)));
16 | };
17 | const handleModify = () => {
18 | dispatch(modifyUser({ name: 'Gentleman' }));
19 | };
20 |
21 | return (
22 | <>
23 | {loading ? (
24 |
25 |
LOADING
26 |
27 | ) : (
28 | <>
29 |
30 | LOGIN
31 |
32 |
33 | MODIFY
34 |
35 |
36 |
{JSON.stringify(userState)}
37 |
38 | >
39 | )}
40 | >
41 | );
42 | };
43 |
44 | export default Login;
45 |
--------------------------------------------------------------------------------
/src/pages/Login/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Login } from './Login';
2 |
--------------------------------------------------------------------------------
/src/pages/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Dashboard';
2 | export * from './Login';
3 |
--------------------------------------------------------------------------------
/src/redux/states/index.ts:
--------------------------------------------------------------------------------
1 | export { default as user } from './user';
2 |
--------------------------------------------------------------------------------
/src/redux/states/user.ts:
--------------------------------------------------------------------------------
1 | import { User } from '@/models';
2 | import { createSlice } from '@reduxjs/toolkit';
3 |
4 | export const UserEmptyState: User = {
5 | name: '',
6 | gender: '',
7 | status: ''
8 | };
9 |
10 | export const userSlice = createSlice({
11 | name: 'user',
12 | initialState: UserEmptyState,
13 | reducers: {
14 | createUser: (state, action) => action.payload,
15 | modifyUser: (state, action) => ({ ...state, ...action.payload }),
16 | resetUser: () => UserEmptyState
17 | }
18 | });
19 |
20 | export const { createUser, modifyUser, resetUser } = userSlice.actions;
21 |
22 | export default userSlice.reducer;
23 |
--------------------------------------------------------------------------------
/src/redux/store.ts:
--------------------------------------------------------------------------------
1 | import { configureStore } from '@reduxjs/toolkit';
2 | import { userSlice } from './states/user';
3 |
4 | export interface AppStore {
5 | user: any;
6 | }
7 |
8 | export default configureStore({
9 | reducer: {
10 | user: userSlice.reducer
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/src/services/public.service.ts:
--------------------------------------------------------------------------------
1 | import { User } from '@/models';
2 | import { loadAbort } from '@/utilities';
3 | import axios from 'axios';
4 |
5 | export const login = () => {
6 | const controller = loadAbort();
7 | return {
8 | call: axios.get('https://rickandmortyapi.com/api/character/2', { signal: controller.signal }),
9 | controller
10 | };
11 | };
12 |
13 | export const getMorty = () => {
14 | return axios.get('https://rickandmortyapi.com/api/character/2');
15 | };
16 |
17 | export const getRick = () => {
18 | return axios.get('https://rickandmortyapi.com/api/character/1');
19 | };
20 |
21 | export const getCoolMorty = () => {
22 | const controller = loadAbort();
23 | return { call: axios.get('https://rickandmortyapi.com/api/character/2', { signal: controller.signal }), controller };
24 | };
25 |
26 | export const getCoolRick = () => {
27 | const controller = loadAbort();
28 | return { call: axios.get('https://rickandmortyapi.com/api/character/1', { signal: controller.signal }), controller };
29 | };
30 |
--------------------------------------------------------------------------------
/src/styled-components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './input-error.styled.component';
2 | export * from './layout.styled.component';
3 |
--------------------------------------------------------------------------------
/src/styled-components/input-error.styled.component.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const InputError = styled.p`
4 | color: #d32f2f;
5 | text-align: left;
6 | margin-bottom: 0;
7 | `
--------------------------------------------------------------------------------
/src/styled-components/layout.styled.component.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const LayoutContainer = styled.div`
4 | display: flex;
5 | flex-direction: column;
6 | gap: 20px;
7 | flex-grow: 1;
8 | padding-right: 20px;
9 | border-radius: 4px;
10 | max-width: 1440px;
11 | padding: 4rem;
12 | `;
13 |
14 | export const MainContainer = styled.div`
15 | background-color: white;
16 | position: relative;
17 | overflow-y: auto;
18 | padding: 20px 20px 20px 20px;
19 | border-radius: 4px;
20 | min-width: 794px;
21 | height: 100%;
22 | `;
23 |
24 | export const AppContainer = styled.div`
25 | justify-content: center;
26 | background-color: #f4f5ff;
27 | display: flex;
28 | `;
29 |
--------------------------------------------------------------------------------
/src/theme.ts:
--------------------------------------------------------------------------------
1 | import { createTheme } from '@mui/material';
2 |
3 | const theme = createTheme({
4 | typography: {
5 | button: {
6 | textTransform: 'none',
7 | width: 'auto',
8 | height: 'auto'
9 | }
10 | }
11 | });
12 |
13 | export default theme;
14 |
--------------------------------------------------------------------------------
/src/utilities/format-date-mmmd.utility.ts:
--------------------------------------------------------------------------------
1 | export const FormatDateMMMD = (dateString: string): string => {
2 | const date = new Date(dateString);
3 | return `${date.toLocaleDateString('en-us', { month: 'short' })} ${date.getDate()}`;
4 | };
5 |
--------------------------------------------------------------------------------
/src/utilities/format-snake-case.utility.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @desc formats a string to snake case.
3 | * @param element- the string to format.
4 | * @return string
5 | */
6 | export const formatToSnakeCase = (element: string): string => {
7 | return element.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
8 | };
9 |
--------------------------------------------------------------------------------
/src/utilities/get-yesterday-unix-utility.ts:
--------------------------------------------------------------------------------
1 | export const GetYesterdayUnix = () => {
2 | const today = new Date();
3 | today.setDate(today.getDate() - 1);
4 | return today.getTime();
5 | };
6 |
--------------------------------------------------------------------------------
/src/utilities/index.ts:
--------------------------------------------------------------------------------
1 | export * from './format-date-mmmd.utility';
2 | export * from './format-snake-case.utility';
3 | export * from './get-yesterday-unix-utility';
4 | export * from './load-abort-axios.utility';
5 | export * from './snackbar.utility';
6 |
--------------------------------------------------------------------------------
/src/utilities/load-abort-axios.utility.ts:
--------------------------------------------------------------------------------
1 | export const loadAbort = () => {
2 | const controller = new AbortController();
3 | return controller;
4 | };
5 |
--------------------------------------------------------------------------------
/src/utilities/snackbar.utility.ts:
--------------------------------------------------------------------------------
1 | import { useSnackbar, VariantType, WithSnackbarProps } from 'notistack';
2 | import React from 'react';
3 |
4 | let useSnackbarRef: WithSnackbarProps;
5 | export const SnackbarUtilsConfigurator: React.FC = () => {
6 | useSnackbarRef = useSnackbar();
7 | return null;
8 | };
9 |
10 | export const SnackbarUtilities = {
11 | success(msg: string) {
12 | this.toast(msg, 'success');
13 | },
14 | warning(msg: string) {
15 | this.toast(msg, 'warning');
16 | },
17 | info(msg: string) {
18 | this.toast(msg, 'info');
19 | },
20 | error(msg: string) {
21 | this.toast(msg, 'error');
22 | },
23 | toast(msg: string, variant: VariantType = 'default') {
24 | useSnackbarRef.enqueueSnackbar(msg, { variant });
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/svgTransform.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | process(src, filename, config, options) {
5 | return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "baseUrl": ".",
5 | "paths": { "@/*": ["./src/*"] },
6 | "useDefineForClassFields": true,
7 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
8 | "allowJs": false,
9 | "skipLibCheck": false,
10 | "esModuleInterop": false,
11 | "allowSyntheticDefaultImports": true,
12 | "isolatedModules": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "module": "ESNext",
16 | "moduleResolution": "node",
17 | "resolveJsonModule": true,
18 | "noEmit": true,
19 | "jsx": "react-jsx",
20 | "types": ["node", "jest", "vite/client", "@testing-library/jest-dom"]
21 | },
22 | "include": ["./src"]
23 | }
24 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "rewrites": [{ "source": "/(.*)", "destination": "/" }]
3 | }
4 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import react from '@vitejs/plugin-react';
2 | import path from 'path';
3 | import { defineConfig, loadEnv } from 'vite';
4 |
5 | export default ({ mode }: { mode: string }) => {
6 | return defineConfig({
7 | plugins: [react()],
8 | resolve: {
9 | alias: {
10 | '@': path.resolve(__dirname, './src')
11 | }
12 | },
13 | define: { 'process.env': { ...loadEnv(mode, process.cwd()) } },
14 | server: {
15 | proxy: {
16 | '^/assets': {
17 | target: 'http://localhost:3000/'
18 | }
19 | }
20 | }
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@babel/code-frame@^7.14.5", "@babel/code-frame@^7.15.8":
6 | version "7.15.8"
7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.15.8.tgz#45990c47adadb00c03677baa89221f7cc23d2503"
8 | integrity sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==
9 | dependencies:
10 | "@babel/highlight" "^7.14.5"
11 |
12 | "@babel/compat-data@^7.15.0":
13 | version "7.15.0"
14 | resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176"
15 | integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==
16 |
17 | "@babel/core@^7.15.5":
18 | version "7.15.8"
19 | resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.8.tgz#195b9f2bffe995d2c6c159e72fe525b4114e8c10"
20 | integrity sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==
21 | dependencies:
22 | "@babel/code-frame" "^7.15.8"
23 | "@babel/generator" "^7.15.8"
24 | "@babel/helper-compilation-targets" "^7.15.4"
25 | "@babel/helper-module-transforms" "^7.15.8"
26 | "@babel/helpers" "^7.15.4"
27 | "@babel/parser" "^7.15.8"
28 | "@babel/template" "^7.15.4"
29 | "@babel/traverse" "^7.15.4"
30 | "@babel/types" "^7.15.6"
31 | convert-source-map "^1.7.0"
32 | debug "^4.1.0"
33 | gensync "^1.0.0-beta.2"
34 | json5 "^2.1.2"
35 | semver "^6.3.0"
36 | source-map "^0.5.0"
37 |
38 | "@babel/generator@^7.15.4", "@babel/generator@^7.15.8":
39 | version "7.15.8"
40 | resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.8.tgz#fa56be6b596952ceb231048cf84ee499a19c0cd1"
41 | integrity sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==
42 | dependencies:
43 | "@babel/types" "^7.15.6"
44 | jsesc "^2.5.1"
45 | source-map "^0.5.0"
46 |
47 | "@babel/helper-annotate-as-pure@^7.14.5", "@babel/helper-annotate-as-pure@^7.15.4":
48 | version "7.15.4"
49 | resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz#3d0e43b00c5e49fdb6c57e421601a7a658d5f835"
50 | integrity sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==
51 | dependencies:
52 | "@babel/types" "^7.15.4"
53 |
54 | "@babel/helper-compilation-targets@^7.15.4":
55 | version "7.15.4"
56 | resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz#cf6d94f30fbefc139123e27dd6b02f65aeedb7b9"
57 | integrity sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==
58 | dependencies:
59 | "@babel/compat-data" "^7.15.0"
60 | "@babel/helper-validator-option" "^7.14.5"
61 | browserslist "^4.16.6"
62 | semver "^6.3.0"
63 |
64 | "@babel/helper-function-name@^7.15.4":
65 | version "7.15.4"
66 | resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz#845744dafc4381a4a5fb6afa6c3d36f98a787ebc"
67 | integrity sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==
68 | dependencies:
69 | "@babel/helper-get-function-arity" "^7.15.4"
70 | "@babel/template" "^7.15.4"
71 | "@babel/types" "^7.15.4"
72 |
73 | "@babel/helper-get-function-arity@^7.15.4":
74 | version "7.15.4"
75 | resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz#098818934a137fce78b536a3e015864be1e2879b"
76 | integrity sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==
77 | dependencies:
78 | "@babel/types" "^7.15.4"
79 |
80 | "@babel/helper-hoist-variables@^7.15.4":
81 | version "7.15.4"
82 | resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz#09993a3259c0e918f99d104261dfdfc033f178df"
83 | integrity sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==
84 | dependencies:
85 | "@babel/types" "^7.15.4"
86 |
87 | "@babel/helper-member-expression-to-functions@^7.15.4":
88 | version "7.15.4"
89 | resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz#bfd34dc9bba9824a4658b0317ec2fd571a51e6ef"
90 | integrity sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==
91 | dependencies:
92 | "@babel/types" "^7.15.4"
93 |
94 | "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.14.5", "@babel/helper-module-imports@^7.15.4":
95 | version "7.15.4"
96 | resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz#e18007d230632dea19b47853b984476e7b4e103f"
97 | integrity sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==
98 | dependencies:
99 | "@babel/types" "^7.15.4"
100 |
101 | "@babel/helper-module-transforms@^7.15.8":
102 | version "7.15.8"
103 | resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz#d8c0e75a87a52e374a8f25f855174786a09498b2"
104 | integrity sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==
105 | dependencies:
106 | "@babel/helper-module-imports" "^7.15.4"
107 | "@babel/helper-replace-supers" "^7.15.4"
108 | "@babel/helper-simple-access" "^7.15.4"
109 | "@babel/helper-split-export-declaration" "^7.15.4"
110 | "@babel/helper-validator-identifier" "^7.15.7"
111 | "@babel/template" "^7.15.4"
112 | "@babel/traverse" "^7.15.4"
113 | "@babel/types" "^7.15.6"
114 |
115 | "@babel/helper-optimise-call-expression@^7.15.4":
116 | version "7.15.4"
117 | resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz#f310a5121a3b9cc52d9ab19122bd729822dee171"
118 | integrity sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==
119 | dependencies:
120 | "@babel/types" "^7.15.4"
121 |
122 | "@babel/helper-plugin-utils@^7.14.5":
123 | version "7.14.5"
124 | resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9"
125 | integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==
126 |
127 | "@babel/helper-replace-supers@^7.15.4":
128 | version "7.15.4"
129 | resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz#52a8ab26ba918c7f6dee28628b07071ac7b7347a"
130 | integrity sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==
131 | dependencies:
132 | "@babel/helper-member-expression-to-functions" "^7.15.4"
133 | "@babel/helper-optimise-call-expression" "^7.15.4"
134 | "@babel/traverse" "^7.15.4"
135 | "@babel/types" "^7.15.4"
136 |
137 | "@babel/helper-simple-access@^7.15.4":
138 | version "7.15.4"
139 | resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz#ac368905abf1de8e9781434b635d8f8674bcc13b"
140 | integrity sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==
141 | dependencies:
142 | "@babel/types" "^7.15.4"
143 |
144 | "@babel/helper-split-export-declaration@^7.15.4":
145 | version "7.15.4"
146 | resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz#aecab92dcdbef6a10aa3b62ab204b085f776e257"
147 | integrity sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==
148 | dependencies:
149 | "@babel/types" "^7.15.4"
150 |
151 | "@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9", "@babel/helper-validator-identifier@^7.15.7":
152 | version "7.15.7"
153 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389"
154 | integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==
155 |
156 | "@babel/helper-validator-option@^7.14.5":
157 | version "7.14.5"
158 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3"
159 | integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==
160 |
161 | "@babel/helpers@^7.15.4":
162 | version "7.15.4"
163 | resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.15.4.tgz#5f40f02050a3027121a3cf48d497c05c555eaf43"
164 | integrity sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==
165 | dependencies:
166 | "@babel/template" "^7.15.4"
167 | "@babel/traverse" "^7.15.4"
168 | "@babel/types" "^7.15.4"
169 |
170 | "@babel/highlight@^7.14.5":
171 | version "7.14.5"
172 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.14.5.tgz#6861a52f03966405001f6aa534a01a24d99e8cd9"
173 | integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==
174 | dependencies:
175 | "@babel/helper-validator-identifier" "^7.14.5"
176 | chalk "^2.0.0"
177 | js-tokens "^4.0.0"
178 |
179 | "@babel/parser@^7.15.4", "@babel/parser@^7.15.8":
180 | version "7.15.8"
181 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.8.tgz#7bacdcbe71bdc3ff936d510c15dcea7cf0b99016"
182 | integrity sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==
183 |
184 | "@babel/plugin-syntax-jsx@^7.14.5":
185 | version "7.14.5"
186 | resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201"
187 | integrity sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==
188 | dependencies:
189 | "@babel/helper-plugin-utils" "^7.14.5"
190 |
191 | "@babel/plugin-transform-react-jsx-development@^7.14.5":
192 | version "7.14.5"
193 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz#1a6c73e2f7ed2c42eebc3d2ad60b0c7494fcb9af"
194 | integrity sha512-rdwG/9jC6QybWxVe2UVOa7q6cnTpw8JRRHOxntG/h6g/guAOe6AhtQHJuJh5FwmnXIT1bdm5vC2/5huV8ZOorQ==
195 | dependencies:
196 | "@babel/plugin-transform-react-jsx" "^7.14.5"
197 |
198 | "@babel/plugin-transform-react-jsx-self@^7.14.9":
199 | version "7.14.9"
200 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.14.9.tgz#33041e665453391eb6ee54a2ecf3ba1d46bd30f4"
201 | integrity sha512-Fqqu0f8zv9W+RyOnx29BX/RlEsBRANbOf5xs5oxb2aHP4FKbLXxIaVPUiCti56LAR1IixMH4EyaixhUsKqoBHw==
202 | dependencies:
203 | "@babel/helper-plugin-utils" "^7.14.5"
204 |
205 | "@babel/plugin-transform-react-jsx-source@^7.14.5":
206 | version "7.14.5"
207 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.14.5.tgz#79f728e60e6dbd31a2b860b0bf6c9765918acf1d"
208 | integrity sha512-1TpSDnD9XR/rQ2tzunBVPThF5poaYT9GqP+of8fAtguYuI/dm2RkrMBDemsxtY0XBzvW7nXjYM0hRyKX9QYj7Q==
209 | dependencies:
210 | "@babel/helper-plugin-utils" "^7.14.5"
211 |
212 | "@babel/plugin-transform-react-jsx@^7.14.5", "@babel/plugin-transform-react-jsx@^7.14.9":
213 | version "7.14.9"
214 | resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz#3314b2163033abac5200a869c4de242cd50a914c"
215 | integrity sha512-30PeETvS+AeD1f58i1OVyoDlVYQhap/K20ZrMjLmmzmC2AYR/G43D4sdJAaDAqCD3MYpSWbmrz3kES158QSLjw==
216 | dependencies:
217 | "@babel/helper-annotate-as-pure" "^7.14.5"
218 | "@babel/helper-module-imports" "^7.14.5"
219 | "@babel/helper-plugin-utils" "^7.14.5"
220 | "@babel/plugin-syntax-jsx" "^7.14.5"
221 | "@babel/types" "^7.14.9"
222 |
223 | "@babel/runtime@^7.9.2":
224 | version "7.15.4"
225 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
226 | integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
227 | dependencies:
228 | regenerator-runtime "^0.13.4"
229 |
230 | "@babel/template@^7.15.4":
231 | version "7.15.4"
232 | resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
233 | integrity sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==
234 | dependencies:
235 | "@babel/code-frame" "^7.14.5"
236 | "@babel/parser" "^7.15.4"
237 | "@babel/types" "^7.15.4"
238 |
239 | "@babel/traverse@^7.15.4", "@babel/traverse@^7.4.5":
240 | version "7.15.4"
241 | resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.4.tgz#ff8510367a144bfbff552d9e18e28f3e2889c22d"
242 | integrity sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==
243 | dependencies:
244 | "@babel/code-frame" "^7.14.5"
245 | "@babel/generator" "^7.15.4"
246 | "@babel/helper-function-name" "^7.15.4"
247 | "@babel/helper-hoist-variables" "^7.15.4"
248 | "@babel/helper-split-export-declaration" "^7.15.4"
249 | "@babel/parser" "^7.15.4"
250 | "@babel/types" "^7.15.4"
251 | debug "^4.1.0"
252 | globals "^11.1.0"
253 |
254 | "@babel/types@^7.14.9", "@babel/types@^7.15.4", "@babel/types@^7.15.6":
255 | version "7.15.6"
256 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f"
257 | integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==
258 | dependencies:
259 | "@babel/helper-validator-identifier" "^7.14.9"
260 | to-fast-properties "^2.0.0"
261 |
262 | "@emotion/is-prop-valid@^0.8.8":
263 | version "0.8.8"
264 | resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a"
265 | integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==
266 | dependencies:
267 | "@emotion/memoize" "0.7.4"
268 |
269 | "@emotion/memoize@0.7.4":
270 | version "0.7.4"
271 | resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
272 | integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==
273 |
274 | "@emotion/stylis@^0.8.4":
275 | version "0.8.5"
276 | resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04"
277 | integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==
278 |
279 | "@emotion/unitless@^0.7.4":
280 | version "0.7.5"
281 | resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
282 | integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
283 |
284 | "@reduxjs/toolkit@^1.6.2":
285 | version "1.6.2"
286 | resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.6.2.tgz#2f2b5365df77dd6697da28fdf44f33501ed9ba37"
287 | integrity sha512-HbfI/hOVrAcMGAYsMWxw3UJyIoAS9JTdwddsjlr5w3S50tXhWb+EMyhIw+IAvCVCLETkzdjgH91RjDSYZekVBA==
288 | dependencies:
289 | immer "^9.0.6"
290 | redux "^4.1.0"
291 | redux-thunk "^2.3.0"
292 | reselect "^4.0.0"
293 |
294 | "@rollup/pluginutils@^4.1.1":
295 | version "4.1.1"
296 | resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec"
297 | integrity sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==
298 | dependencies:
299 | estree-walker "^2.0.1"
300 | picomatch "^2.2.2"
301 |
302 | "@types/prop-types@*":
303 | version "15.7.4"
304 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
305 | integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
306 |
307 | "@types/react-dom@^17.0.0":
308 | version "17.0.10"
309 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.10.tgz#d6972ec018d23cf22b99597f1289343d99ea9d9d"
310 | integrity sha512-8oz3NAUId2z/zQdFI09IMhQPNgIbiP8Lslhv39DIDamr846/0spjZK0vnrMak0iB8EKb9QFTTIdg2Wj2zH5a3g==
311 | dependencies:
312 | "@types/react" "*"
313 |
314 | "@types/react@*", "@types/react@^17.0.0":
315 | version "17.0.33"
316 | resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.33.tgz#e01ae3de7613dac1094569880bb3792732203ad5"
317 | integrity sha512-pLWntxXpDPaU+RTAuSGWGSEL2FRTNyRQOjSWDke/rxRg14ncsZvx8AKWMWZqvc1UOaJIAoObdZhAWvRaHFi5rw==
318 | dependencies:
319 | "@types/prop-types" "*"
320 | "@types/scheduler" "*"
321 | csstype "^3.0.2"
322 |
323 | "@types/scheduler@*":
324 | version "0.16.2"
325 | resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
326 | integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
327 |
328 | "@vitejs/plugin-react@^1.0.0":
329 | version "1.0.7"
330 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.0.7.tgz#d542003afbae875f86fb89f3811a0f7c0c9479f5"
331 | integrity sha512-dzxzohFOAVVXpGlFn6Uvw2xaSLp80Vjmg2e5G1XdMV266vVKrcDqg9CWP/AiJiXuubNUdgy1k4E8dNXI6WCyhw==
332 | dependencies:
333 | "@babel/core" "^7.15.5"
334 | "@babel/plugin-transform-react-jsx" "^7.14.9"
335 | "@babel/plugin-transform-react-jsx-development" "^7.14.5"
336 | "@babel/plugin-transform-react-jsx-self" "^7.14.9"
337 | "@babel/plugin-transform-react-jsx-source" "^7.14.5"
338 | "@rollup/pluginutils" "^4.1.1"
339 | react-refresh "^0.10.0"
340 | resolve "^1.20.0"
341 |
342 | ansi-styles@^3.2.1:
343 | version "3.2.1"
344 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
345 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
346 | dependencies:
347 | color-convert "^1.9.0"
348 |
349 | anymatch@~3.1.2:
350 | version "3.1.2"
351 | resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
352 | integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
353 | dependencies:
354 | normalize-path "^3.0.0"
355 | picomatch "^2.0.4"
356 |
357 | axios@^0.24.0:
358 | version "0.24.0"
359 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
360 | integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
361 | dependencies:
362 | follow-redirects "^1.14.4"
363 |
364 | "babel-plugin-styled-components@>= 1.12.0":
365 | version "1.13.3"
366 | resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.3.tgz#1f1cb3927d4afa1e324695c78f690900e3d075bc"
367 | integrity sha512-meGStRGv+VuKA/q0/jXxrPNWEm4LPfYIqxooDTdmh8kFsP/Ph7jJG5rUPwUPX3QHUvggwdbgdGpo88P/rRYsVw==
368 | dependencies:
369 | "@babel/helper-annotate-as-pure" "^7.15.4"
370 | "@babel/helper-module-imports" "^7.15.4"
371 | babel-plugin-syntax-jsx "^6.18.0"
372 | lodash "^4.17.11"
373 |
374 | babel-plugin-syntax-jsx@^6.18.0:
375 | version "6.18.0"
376 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
377 | integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
378 |
379 | binary-extensions@^2.0.0:
380 | version "2.2.0"
381 | resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
382 | integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
383 |
384 | braces@~3.0.2:
385 | version "3.0.2"
386 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
387 | integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
388 | dependencies:
389 | fill-range "^7.0.1"
390 |
391 | browserslist@^4.16.6:
392 | version "4.17.5"
393 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.5.tgz#c827bbe172a4c22b123f5e337533ceebadfdd559"
394 | integrity sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==
395 | dependencies:
396 | caniuse-lite "^1.0.30001271"
397 | electron-to-chromium "^1.3.878"
398 | escalade "^3.1.1"
399 | node-releases "^2.0.1"
400 | picocolors "^1.0.0"
401 |
402 | camelize@^1.0.0:
403 | version "1.0.0"
404 | resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
405 | integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
406 |
407 | caniuse-lite@^1.0.30001271:
408 | version "1.0.30001272"
409 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001272.tgz#8e9790ff995e9eb6e1f4c45cd07ddaa87cddbb14"
410 | integrity sha512-DV1j9Oot5dydyH1v28g25KoVm7l8MTxazwuiH3utWiAS6iL/9Nh//TGwqFEeqqN8nnWYQ8HHhUq+o4QPt9kvYw==
411 |
412 | chalk@^2.0.0:
413 | version "2.4.2"
414 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
415 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
416 | dependencies:
417 | ansi-styles "^3.2.1"
418 | escape-string-regexp "^1.0.5"
419 | supports-color "^5.3.0"
420 |
421 | "chokidar@>=3.0.0 <4.0.0":
422 | version "3.5.2"
423 | resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
424 | integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
425 | dependencies:
426 | anymatch "~3.1.2"
427 | braces "~3.0.2"
428 | glob-parent "~5.1.2"
429 | is-binary-path "~2.1.0"
430 | is-glob "~4.0.1"
431 | normalize-path "~3.0.0"
432 | readdirp "~3.6.0"
433 | optionalDependencies:
434 | fsevents "~2.3.2"
435 |
436 | color-convert@^1.9.0:
437 | version "1.9.3"
438 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
439 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
440 | dependencies:
441 | color-name "1.1.3"
442 |
443 | color-name@1.1.3:
444 | version "1.1.3"
445 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
446 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
447 |
448 | convert-source-map@^1.7.0:
449 | version "1.8.0"
450 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
451 | integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
452 | dependencies:
453 | safe-buffer "~5.1.1"
454 |
455 | css-color-keywords@^1.0.0:
456 | version "1.0.0"
457 | resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05"
458 | integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=
459 |
460 | css-to-react-native@^3.0.0:
461 | version "3.0.0"
462 | resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756"
463 | integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==
464 | dependencies:
465 | camelize "^1.0.0"
466 | css-color-keywords "^1.0.0"
467 | postcss-value-parser "^4.0.2"
468 |
469 | csstype@^3.0.2:
470 | version "3.0.9"
471 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b"
472 | integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==
473 |
474 | debug@^4.1.0:
475 | version "4.3.2"
476 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
477 | integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
478 | dependencies:
479 | ms "2.1.2"
480 |
481 | electron-to-chromium@^1.3.878:
482 | version "1.3.884"
483 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.884.tgz#0cd8c3a80271fd84a81f284c60fb3c9ecb33c166"
484 | integrity sha512-kOaCAa+biA98PwH5BpCkeUeTL6mCeg8p3Q3OhqzPyqhu/5QUnWAN2wr/3IK8xMQxIV76kfoQpP+Bn/wij/jXrg==
485 |
486 | esbuild-android-arm64@0.13.10:
487 | version "0.13.10"
488 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.10.tgz#3545c71bf01e8b36535681078cdb0191c8654452"
489 | integrity sha512-1sCdVAq64yMp2Uhlu+97/enFxpmrj31QHtThz7K+/QGjbHa7JZdBdBsZCzWJuntKHZ+EU178tHYkvjaI9z5sGg==
490 |
491 | esbuild-darwin-64@0.13.10:
492 | version "0.13.10"
493 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.13.10.tgz#143e34d7f5d3860cc681c64c860f531e60496b5b"
494 | integrity sha512-XlL+BYZ2h9cz3opHfFgSHGA+iy/mljBFIRU9q++f9SiBXEZTb4gTW/IENAD1l9oKH0FdO9rUpyAfV+lM4uAxrg==
495 |
496 | esbuild-darwin-arm64@0.13.10:
497 | version "0.13.10"
498 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.10.tgz#456a044b789d5d256af8d264314da5217ca9fcd1"
499 | integrity sha512-RZMMqMTyActMrXKkW71IQO8B0tyQm0Bm+ZJQWNaHJchL5LlqazJi7rriwSocP+sKLszHhsyTEBBh6qPdw5g5yQ==
500 |
501 | esbuild-freebsd-64@0.13.10:
502 | version "0.13.10"
503 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.10.tgz#dcd829a4a95226716faae8a2f378f08688f921b6"
504 | integrity sha512-pf4BEN9reF3jvZEZdxljVgOv5JS4kuYFCI78xk+2HWustbLvTP0b9XXfWI/OD0ZLWbyLYZYIA+VbVe4tdAklig==
505 |
506 | esbuild-freebsd-arm64@0.13.10:
507 | version "0.13.10"
508 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.10.tgz#116c254b3eb1b9d1dd6f12e0271967de4512ca09"
509 | integrity sha512-j9PUcuNWmlxr4/ry4dK/s6zKh42Jhh/N5qnAAj7tx3gMbkIHW0JBoVSbbgp97p88X9xgKbXx4lG2sJDhDWmsYQ==
510 |
511 | esbuild-linux-32@0.13.10:
512 | version "0.13.10"
513 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.13.10.tgz#131971622c38e5aa014303a494a1b5c3cc90f2be"
514 | integrity sha512-imtdHG5ru0xUUXuc2ofdtyw0fWlHYXV7JjF7oZHgmn0b+B4o4Nr6ZON3xxoo1IP8wIekW+7b9exIf/MYq0QV7w==
515 |
516 | esbuild-linux-64@0.13.10:
517 | version "0.13.10"
518 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.13.10.tgz#48826c388abd5dde3fc098a8ef38d8b548674f93"
519 | integrity sha512-O7fzQIH2e7GC98dvoTH0rad5BVLm9yU3cRWfEmryCEIFTwbNEWCEWOfsePuoGOHRtSwoVY1hPc21CJE4/9rWxQ==
520 |
521 | esbuild-linux-arm64@0.13.10:
522 | version "0.13.10"
523 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.10.tgz#0be9ffc92e30641869c7fbca0ec5d30fa8cbddd6"
524 | integrity sha512-bkGxN67S2n0PF4zhh87/92kBTsH2xXLuH6T5omReKhpXdJZF5SVDSk5XU/nngARzE+e6QK6isK060Dr5uobzNw==
525 |
526 | esbuild-linux-arm@0.13.10:
527 | version "0.13.10"
528 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.13.10.tgz#8c15bcaa41a022c834f049a71a7d1fbade507532"
529 | integrity sha512-R2Jij4A0K8BcmBehvQeUteQEcf24Y2YZ6mizlNFuJOBPxe3vZNmkZ4mCE7Pf1tbcqA65qZx8J3WSHeGJl9EsJA==
530 |
531 | esbuild-linux-mips64le@0.13.10:
532 | version "0.13.10"
533 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.10.tgz#5bb33a2bc82e9c78ed724f345a8359610ddc9695"
534 | integrity sha512-UDNO5snJYOLWrA2uOUxM/PVbzzh2TR7Zf2i8zCCuFlYgvAb/81XO+Tasp3YAElDpp4VGqqcpBXLtofa9nrnJGA==
535 |
536 | esbuild-linux-ppc64le@0.13.10:
537 | version "0.13.10"
538 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.10.tgz#18703cd0d52447d97486735b8e79fba7d81eac65"
539 | integrity sha512-xu6J9rMWu1TcEGuEmoc8gsTrJCEPsf+QtxK4IiUZNde9r4Q4nlRVah4JVZP3hJapZgZJcxsse0XiKXh1UFdOeA==
540 |
541 | esbuild-netbsd-64@0.13.10:
542 | version "0.13.10"
543 | resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.10.tgz#3ecb06158aadb5b7396a5b7632069181b1591c56"
544 | integrity sha512-d+Gr0ScMC2J83Bfx/ZvJHK0UAEMncctwgjRth9d4zppYGLk/xMfFKxv5z1ib8yZpQThafq8aPm8AqmFIJrEesw==
545 |
546 | esbuild-openbsd-64@0.13.10:
547 | version "0.13.10"
548 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.10.tgz#3a6950b1d955de921ac52f7af0b4865e89d6e4f1"
549 | integrity sha512-OuCYc+bNKumBvxflga+nFzZvxsgmWQW+z4rMGIjM5XIW0nNbGgRc5p/0PSDv0rTdxAmwCpV69fezal0xjrDaaA==
550 |
551 | esbuild-sunos-64@0.13.10:
552 | version "0.13.10"
553 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.13.10.tgz#ad407f721a8b5727fca31958b5eab1b0232e2d73"
554 | integrity sha512-gUkgivZK11bD56wDoLsnYrsOHD/zHzzLSdqKcIl3wRMulfHpRBpoX8gL0dbWr+8N9c+1HDdbNdvxSRmZ4RCVwg==
555 |
556 | esbuild-windows-32@0.13.10:
557 | version "0.13.10"
558 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.13.10.tgz#ddaaa0b6e172df6512edc7a91bd2456615cfa914"
559 | integrity sha512-C1xJ54E56dGWRaYcTnRy7amVZ9n1/D/D2/qVw7e5EtS7p+Fv/yZxxgqyb1hMGKXgtFYX4jMpU5eWBF/AsYrn+A==
560 |
561 | esbuild-windows-64@0.13.10:
562 | version "0.13.10"
563 | resolved "https://registry.yarnpkg.com/esbuild-windows-64/-/esbuild-windows-64-0.13.10.tgz#93d861abf36bf71b6e61f5cbd2e42762ce5cb83a"
564 | integrity sha512-6+EXEXopEs3SvPFAHcps2Krp/FvqXXsOQV33cInmyilb0ZBEQew4MIoZtMIyB3YXoV6//dl3i6YbPrFZaWEinQ==
565 |
566 | esbuild-windows-arm64@0.13.10:
567 | version "0.13.10"
568 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.10.tgz#85a2d338aaa8b0cd1d8ecbe9150def9a608e8947"
569 | integrity sha512-xTqM/XKhORo6u9S5I0dNJWEdWoemFjogLUTVLkQMVyUV3ZuMChahVA+bCqKHdyX55pCFxD/8v2fm3/sfFMWN+g==
570 |
571 | esbuild@^0.13.2:
572 | version "0.13.10"
573 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.13.10.tgz#e3d24d59f1d8b2130d746ca858efcb80e1d99b26"
574 | integrity sha512-0NfCsnAh5XatHIx6Cu93wpR2v6opPoOMxONYhaAoZKzGYqAE+INcDeX2wqMdcndvPQdWCuuCmvlnsh0zmbHcSQ==
575 | optionalDependencies:
576 | esbuild-android-arm64 "0.13.10"
577 | esbuild-darwin-64 "0.13.10"
578 | esbuild-darwin-arm64 "0.13.10"
579 | esbuild-freebsd-64 "0.13.10"
580 | esbuild-freebsd-arm64 "0.13.10"
581 | esbuild-linux-32 "0.13.10"
582 | esbuild-linux-64 "0.13.10"
583 | esbuild-linux-arm "0.13.10"
584 | esbuild-linux-arm64 "0.13.10"
585 | esbuild-linux-mips64le "0.13.10"
586 | esbuild-linux-ppc64le "0.13.10"
587 | esbuild-netbsd-64 "0.13.10"
588 | esbuild-openbsd-64 "0.13.10"
589 | esbuild-sunos-64 "0.13.10"
590 | esbuild-windows-32 "0.13.10"
591 | esbuild-windows-64 "0.13.10"
592 | esbuild-windows-arm64 "0.13.10"
593 |
594 | escalade@^3.1.1:
595 | version "3.1.1"
596 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
597 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
598 |
599 | escape-string-regexp@^1.0.5:
600 | version "1.0.5"
601 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
602 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
603 |
604 | eslint-plugin-react-hooks@^4.2.0:
605 | version "4.2.0"
606 | resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556"
607 | integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==
608 |
609 | estree-walker@^2.0.1:
610 | version "2.0.2"
611 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
612 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
613 |
614 | fill-range@^7.0.1:
615 | version "7.0.1"
616 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
617 | integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
618 | dependencies:
619 | to-regex-range "^5.0.1"
620 |
621 | follow-redirects@^1.14.4:
622 | version "1.14.4"
623 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
624 | integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
625 |
626 | fsevents@~2.3.2:
627 | version "2.3.2"
628 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
629 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
630 |
631 | function-bind@^1.1.1:
632 | version "1.1.1"
633 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
634 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
635 |
636 | gensync@^1.0.0-beta.2:
637 | version "1.0.0-beta.2"
638 | resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
639 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
640 |
641 | glob-parent@~5.1.2:
642 | version "5.1.2"
643 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
644 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
645 | dependencies:
646 | is-glob "^4.0.1"
647 |
648 | globals@^11.1.0:
649 | version "11.12.0"
650 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
651 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
652 |
653 | has-flag@^3.0.0:
654 | version "3.0.0"
655 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
656 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
657 |
658 | has@^1.0.3:
659 | version "1.0.3"
660 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
661 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
662 | dependencies:
663 | function-bind "^1.1.1"
664 |
665 | hoist-non-react-statics@^3.0.0:
666 | version "3.3.2"
667 | resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
668 | integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
669 | dependencies:
670 | react-is "^16.7.0"
671 |
672 | immer@^9.0.6:
673 | version "9.0.6"
674 | resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73"
675 | integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ==
676 |
677 | is-binary-path@~2.1.0:
678 | version "2.1.0"
679 | resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
680 | integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
681 | dependencies:
682 | binary-extensions "^2.0.0"
683 |
684 | is-core-module@^2.2.0:
685 | version "2.8.0"
686 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548"
687 | integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==
688 | dependencies:
689 | has "^1.0.3"
690 |
691 | is-extglob@^2.1.1:
692 | version "2.1.1"
693 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
694 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
695 |
696 | is-glob@^4.0.1, is-glob@~4.0.1:
697 | version "4.0.3"
698 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
699 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
700 | dependencies:
701 | is-extglob "^2.1.1"
702 |
703 | is-number@^7.0.0:
704 | version "7.0.0"
705 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
706 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
707 |
708 | "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
709 | version "4.0.0"
710 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
711 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
712 |
713 | jsesc@^2.5.1:
714 | version "2.5.2"
715 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
716 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
717 |
718 | json5@^2.1.2:
719 | version "2.2.0"
720 | resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
721 | integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
722 | dependencies:
723 | minimist "^1.2.5"
724 |
725 | lodash@^4.17.11:
726 | version "4.17.21"
727 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
728 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
729 |
730 | loose-envify@^1.1.0:
731 | version "1.4.0"
732 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
733 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
734 | dependencies:
735 | js-tokens "^3.0.0 || ^4.0.0"
736 |
737 | minimist@^1.2.5:
738 | version "1.2.5"
739 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
740 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
741 |
742 | ms@2.1.2:
743 | version "2.1.2"
744 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
745 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
746 |
747 | nanoid@^3.1.30:
748 | version "3.1.30"
749 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362"
750 | integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==
751 |
752 | node-releases@^2.0.1:
753 | version "2.0.1"
754 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5"
755 | integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==
756 |
757 | normalize-path@^3.0.0, normalize-path@~3.0.0:
758 | version "3.0.0"
759 | resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
760 | integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
761 |
762 | object-assign@^4.1.1:
763 | version "4.1.1"
764 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
765 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
766 |
767 | path-parse@^1.0.6:
768 | version "1.0.7"
769 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
770 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
771 |
772 | picocolors@^1.0.0:
773 | version "1.0.0"
774 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
775 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
776 |
777 | picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2:
778 | version "2.3.0"
779 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
780 | integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
781 |
782 | postcss-value-parser@^4.0.2:
783 | version "4.1.0"
784 | resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
785 | integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
786 |
787 | postcss@^8.3.8:
788 | version "8.3.11"
789 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858"
790 | integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA==
791 | dependencies:
792 | nanoid "^3.1.30"
793 | picocolors "^1.0.0"
794 | source-map-js "^0.6.2"
795 |
796 | prettier@2.4.1:
797 | version "2.4.1"
798 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c"
799 | integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==
800 |
801 | react-dom@^17.0.0:
802 | version "17.0.2"
803 | resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
804 | integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
805 | dependencies:
806 | loose-envify "^1.1.0"
807 | object-assign "^4.1.1"
808 | scheduler "^0.20.2"
809 |
810 | react-is@^16.7.0:
811 | version "16.13.1"
812 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
813 | integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
814 |
815 | react-refresh@^0.10.0:
816 | version "0.10.0"
817 | resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.10.0.tgz#2f536c9660c0b9b1d500684d9e52a65e7404f7e3"
818 | integrity sha512-PgidR3wST3dDYKr6b4pJoqQFpPGNKDSCDx4cZoshjXipw3LzO7mG1My2pwEzz2JVkF+inx3xRpDeQLFQGH/hsQ==
819 |
820 | react@^17.0.0:
821 | version "17.0.2"
822 | resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
823 | integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
824 | dependencies:
825 | loose-envify "^1.1.0"
826 | object-assign "^4.1.1"
827 |
828 | readdirp@~3.6.0:
829 | version "3.6.0"
830 | resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
831 | integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
832 | dependencies:
833 | picomatch "^2.2.1"
834 |
835 | redux-thunk@^2.3.0:
836 | version "2.4.0"
837 | resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.0.tgz#ac89e1d6b9bdb9ee49ce69a69071be41bbd82d67"
838 | integrity sha512-/y6ZKQNU/0u8Bm7ROLq9Pt/7lU93cT0IucYMrubo89ENjxPa7i8pqLKu6V4X7/TvYovQ6x01unTeyeZ9lgXiTA==
839 |
840 | redux@^4.1.0:
841 | version "4.1.2"
842 | resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104"
843 | integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw==
844 | dependencies:
845 | "@babel/runtime" "^7.9.2"
846 |
847 | regenerator-runtime@^0.13.4:
848 | version "0.13.9"
849 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
850 | integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
851 |
852 | reselect@^4.0.0:
853 | version "4.1.1"
854 | resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.1.tgz#7e2c110efbf3d70df3482604bcf2bc0ab571346a"
855 | integrity sha512-Jjt8Us6hAWJpjucyladHvUGR+q1mHHgWtGDXlhvvKyNyIeQ3bjuWLDX0bsTLhbm/gd4iXEACBlODUHBlLWiNnA==
856 |
857 | resolve@^1.20.0:
858 | version "1.20.0"
859 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
860 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
861 | dependencies:
862 | is-core-module "^2.2.0"
863 | path-parse "^1.0.6"
864 |
865 | rollup@^2.57.0:
866 | version "2.58.3"
867 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.58.3.tgz#71a08138d9515fb65043b6a18618b2ed9ac8d239"
868 | integrity sha512-ei27MSw1KhRur4p87Q0/Va2NAYqMXOX++FNEumMBcdreIRLURKy+cE2wcDJKBn0nfmhP2ZGrJkP1XPO+G8FJQw==
869 | optionalDependencies:
870 | fsevents "~2.3.2"
871 |
872 | rxjs@^7.4.0:
873 | version "7.4.0"
874 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68"
875 | integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==
876 | dependencies:
877 | tslib "~2.1.0"
878 |
879 | safe-buffer@~5.1.1:
880 | version "5.1.2"
881 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
882 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
883 |
884 | sass@^1.43.4:
885 | version "1.43.4"
886 | resolved "https://registry.yarnpkg.com/sass/-/sass-1.43.4.tgz#68c7d6a1b004bef49af0d9caf750e9b252105d1f"
887 | integrity sha512-/ptG7KE9lxpGSYiXn7Ar+lKOv37xfWsZRtFYal2QHNigyVQDx685VFT/h7ejVr+R8w7H4tmUgtulsKl5YpveOg==
888 | dependencies:
889 | chokidar ">=3.0.0 <4.0.0"
890 |
891 | scheduler@^0.20.2:
892 | version "0.20.2"
893 | resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
894 | integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
895 | dependencies:
896 | loose-envify "^1.1.0"
897 | object-assign "^4.1.1"
898 |
899 | semver@^6.3.0:
900 | version "6.3.0"
901 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
902 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
903 |
904 | shallowequal@^1.1.0:
905 | version "1.1.0"
906 | resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
907 | integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
908 |
909 | source-map-js@^0.6.2:
910 | version "0.6.2"
911 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e"
912 | integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==
913 |
914 | source-map@^0.5.0:
915 | version "0.5.7"
916 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
917 | integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
918 |
919 | styled-components@^5.3.3:
920 | version "5.3.3"
921 | resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.3.tgz#312a3d9a549f4708f0fb0edc829eb34bde032743"
922 | integrity sha512-++4iHwBM7ZN+x6DtPPWkCI4vdtwumQ+inA/DdAsqYd4SVgUKJie5vXyzotA00ttcFdQkCng7zc6grwlfIfw+lw==
923 | dependencies:
924 | "@babel/helper-module-imports" "^7.0.0"
925 | "@babel/traverse" "^7.4.5"
926 | "@emotion/is-prop-valid" "^0.8.8"
927 | "@emotion/stylis" "^0.8.4"
928 | "@emotion/unitless" "^0.7.4"
929 | babel-plugin-styled-components ">= 1.12.0"
930 | css-to-react-native "^3.0.0"
931 | hoist-non-react-statics "^3.0.0"
932 | shallowequal "^1.1.0"
933 | supports-color "^5.5.0"
934 |
935 | supports-color@^5.3.0, supports-color@^5.5.0:
936 | version "5.5.0"
937 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
938 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
939 | dependencies:
940 | has-flag "^3.0.0"
941 |
942 | to-fast-properties@^2.0.0:
943 | version "2.0.0"
944 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
945 | integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
946 |
947 | to-regex-range@^5.0.1:
948 | version "5.0.1"
949 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
950 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
951 | dependencies:
952 | is-number "^7.0.0"
953 |
954 | tslib@~2.1.0:
955 | version "2.1.0"
956 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
957 | integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
958 |
959 | typescript@^4.3.2:
960 | version "4.4.4"
961 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c"
962 | integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
963 |
964 | vite@^2.6.4:
965 | version "2.6.13"
966 | resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.13.tgz#16b3ec85a66d5b461ac29a903874d4357f9af432"
967 | integrity sha512-+tGZ1OxozRirTudl4M3N3UTNJOlxdVo/qBl2IlDEy/ZpTFcskp+k5ncNjayR3bRYTCbqSOFz2JWGN1UmuDMScA==
968 | dependencies:
969 | esbuild "^0.13.2"
970 | postcss "^8.3.8"
971 | resolve "^1.20.0"
972 | rollup "^2.57.0"
973 | optionalDependencies:
974 | fsevents "~2.3.2"
975 |
--------------------------------------------------------------------------------