feat: switch done

This commit is contained in:
Ruidy 2021-07-15 11:09:33 +02:00
parent 74d84b748a
commit e953246d06
24 changed files with 327 additions and 179 deletions

View file

@ -1 +0,0 @@
NEXT_PUBLIC_API_URL=http://localhost:9000/bills

5
.gitignore vendored
View file

@ -11,10 +11,7 @@
# misc # misc
.DS_Store .DS_Store
.env.local .env*
.env.development.local
.env.test.local
.env.production.local
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*

View file

@ -12,7 +12,7 @@ yarn dev
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. You can start editing the page by modifying `pages/home.tsx`. The page auto-updates as you edit the file.
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

View file

@ -1,7 +0,0 @@
import { ReactNode } from "react";
type ListProps<T> = { items: T[]; render: (item: T) => ReactNode };
export default function List<T>({ items, render }: ListProps<T>) {
return <ul>{items.map((item) => render(item))}</ul>;
}

View file

@ -14,16 +14,18 @@
"react": "^17.0.2", "react": "^17.0.2",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-hook-form": "^7.8.0", "react-hook-form": "^7.8.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3" "react-scripts": "4.0.3"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15", "@types/jest": "^26.0.15",
"@types/node": "^12.0.0", "@types/node": "^12.0.0",
"@types/react": "^17.0.11", "@types/react": "^17.0.11",
"@types/react-dom": "^17.0.0", "@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.8",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"typescript": "^4.3.4", "typescript": "^4.3.4",
"web-vitals": "^1.0.1" "web-vitals": "^1.0.1"

View file

@ -1,6 +0,0 @@
import "../styles/globals.css";
import { AppProps } from "next/app";
export default function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}

View file

@ -1,37 +0,0 @@
import { Card, List } from "antd";
import { GetStaticProps } from "next";
import Link from "next/link";
import { fetchAllBills } from "../api";
import { withLayout } from "../layouts/main";
import { Bill } from "../types/bill";
type BillsProps = { bills: Bill[] };
export const getStaticProps: GetStaticProps = async () => {
const bills = await fetchAllBills();
return { props: { bills } };
};
const BillsPage = ({ bills }: BillsProps) => (
<section>
<h1>All bills</h1>
<List
grid={{ gutter: 16, column: 4 }}
pagination={{ pageSize: 12 }}
dataSource={bills}
renderItem={(bill) => (
<Link href={`/bills/${bill.id}`}>
<a>
<List.Item>
<Card title={bill.id} bordered={false}>
<p>{bill.name}</p>
</Card>
</List.Item>
</a>
</Link>
)}
/>
</section>
);
export default withLayout(BillsPage);

View file

@ -1,56 +0,0 @@
import {Button, message, Space, Typography} from "antd";
import {GetStaticPaths, GetStaticProps} from "next";
import {useState} from "react";
import {fetchAllBills, fetchOneBill, sendBillAsPDF} from "../../api";
import {withLayout} from "../../layouts/main";
import {Bill} from "../../types/bill";
type BillProps = { bill: Bill };
type QueryParams = { id: string };
export const getStaticPaths: GetStaticPaths<QueryParams> = async () => {
const bills = await fetchAllBills();
const paths = bills.map(({ id }) => ({
params: { id: id.toString() },
}));
return { paths, fallback: false };
};
export const getStaticProps: GetStaticProps<BillProps, QueryParams> = async ({ params }) => {
const billID = parseInt(params!.id);
const bill = await fetchOneBill(billID);
return { props: { bill } };
};
const BillPage = ({ bill }: BillProps) => {
const [sent, setSent] = useState(false);
const handleSendPDF = (id: number) => {
sendBillAsPDF(id);
message.success("The bill will be sent to the customer");
setSent(() => true);
};
return (
<main>
<Typography.Title>Facture #VFNI{`${bill.id}`.padStart(4,"0")}</Typography.Title>
<Space>
<Button type="primary" onClick={() => handleSendPDF(bill.id)} disabled={sent}>
{sent ? "The bill is on its way to your customer" : "Send Bill"}
</Button>
</Space>
<Space>
<Typography.Text>{bill?.name}</Typography.Text>
<Typography.Text>{bill?.price} </Typography.Text>
<Typography.Text>
from {bill?.start} to {bill?.end}
</Typography.Text>
</Space>
</main>
);
};
export default withLayout(BillPage);

View file

@ -1,7 +1,5 @@
import Router from "./Router";
export default function App() { export default function App() {
return ( return <Router />;
<div className="App">
<p>Hi</p>
</div>
);
} }

44
src/Router.tsx Normal file
View file

@ -0,0 +1,44 @@
import { Route, Switch } from 'react-router-dom';
import BillPage from './pages/bill';
import BillsPage from './pages/bills';
import HomePage from './pages/home';
import NotFoundPage from './pages/notFound';
type Config = {
path: string;
component: ({ ...props }: any) => JSX.Element;
exact?: boolean;
};
export default function Router() {
const routes: Config[] = [
{
path: '/',
component: HomePage,
exact: true
},
{
path: '/bills',
component: BillsPage,
exact: true
},
{
path: '/bills/:id',
component: BillPage
},
{
path: '*',
component: NotFoundPage
}
];
return (
<Switch>
{routes.map(({ exact, path, component: Component }) => (
<Route key={path} exact={!!exact} path={path}>
<Component />
</Route>
))}
</Switch>
);
}

View file

@ -1,12 +1,12 @@
import axios from "axios"; import axios from 'axios';
import { Bill, BillForm } from "../types/bill"; import { Bill, BillForm } from '../types/bill';
const BASE_URL = process.env.NEXT_PUBLIC_API_URL const BASE_URL = process.env.REACT_APP_API_URL;
const client = axios.create({ baseURL: BASE_URL }); const client = axios.create({ baseURL: BASE_URL });
export const createBill = async (data: BillForm) => { export const createBill = async (data: BillForm) => {
try { try {
const { data: response } = await client.post<number>("/", data) const { data: response } = await client.post<number>('/', data);
return response; return response;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -14,19 +14,24 @@ export const createBill = async (data: BillForm) => {
} }
}; };
export const fetchOneBill = async (id: number) => { type Response<T> = {
data?: T;
error?: any;
};
export const fetchOneBill = async (id: number): Promise<Response<Bill>> => {
try { try {
const { data } = await client.get<Bill>(`/${id}`); const { data } = await client.get<Bill>(`/${id}`);
return data; return { data };
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return {} as Bill; return { error };
} }
}; };
export const fetchAllBills = async () => { export const fetchAllBills = async () => {
try { try {
const { data } = await client.get<Bill[]>("/"); const { data } = await client.get<Bill[]>('/');
return data; return data;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -40,6 +45,6 @@ export const sendBillAsPDF = async (id: number) => {
return data; return data;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
return false return false;
} }
}; };

View file

@ -1,13 +1 @@
body { @import "antd/dist/antd.css";
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

View file

@ -1,12 +1,15 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import App from "./App"; import App from "./App";
import "./index.css"; import "./index.css";
import reportWebVitals from "./reportWebVitals"; import reportWebVitals from "./reportWebVitals";
ReactDOM.render( ReactDOM.render(
<React.StrictMode> <React.StrictMode>
<App /> <BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>, </React.StrictMode>,
document.getElementById("root") document.getElementById("root")
); );

View file

@ -1,46 +1,42 @@
import { Layout, Menu, Row } from "antd"; import { Layout, Menu, Row } from 'antd';
import Link from "next/link"; import { Link, useRouteMatch } from 'react-router-dom';
import { useRouter } from "next/router";
const { Header, Content, Footer } = Layout; const { Header, Content, Footer } = Layout;
export const withLayout = export const withLayout =
(Component: (arg: any) => JSX.Element) => (Component: (arg: any) => JSX.Element) =>
({ ...props }: any) => { ({ ...props }: any) => {
const { route } = useRouter(); const { url } = useRouteMatch();
const menuItems = [ const menuItems = [
{ label: "Home", path: "/" }, { label: 'Home', path: '/' },
{ label: "Bills", path: "/bills" }, { label: 'Bills', path: '/bills' }
]; ];
return ( return (
<> <>
<Layout style={{ minHeight: "100vh" }}> <Layout style={{ minHeight: '100vh' }}>
<Header> <Header>
<Row> <Row>
<span style={{ color: "white", paddingRight: "16px" }}>🍉 Melon</span> <span style={{ color: 'white', paddingRight: '16px' }}>🍉 Melon</span>
<Menu <Menu
theme="dark" theme="dark"
mode="horizontal" mode="horizontal"
selectedKeys={[ selectedKeys={[
(menuItems.findIndex((item) => item.path === route) + 1).toString(), (menuItems.findIndex((item) => url.includes(item.path)) + 1).toString()
]} ]}
> >
{menuItems.map(({ label, path }, index) => ( {menuItems.map(({ label, path }, index) => (
<Menu.Item key={index + 1}> <Menu.Item key={index + 1}>
<Link href={path}> <Link to={path}>{label}</Link>
<a>{label}</a>
</Link>
</Menu.Item> </Menu.Item>
))} ))}
</Menu> </Menu>
</Row> </Row>
</Header> </Header>
<Content style={{ padding: "20px 50px" }}> <Content style={{ padding: '20px 50px' }}>
<Component {...props} /> <Component {...props} />
</Content> </Content>
<Footer style={{ textAlign: "center" }}>🍉 Melon - Property Management</Footer> <Footer style={{ textAlign: 'center' }}>🍉 Melon - Property Management</Footer>
</Layout> </Layout>
</> </>
); );

60
src/pages/bill.tsx Normal file
View file

@ -0,0 +1,60 @@
import { Button, message, Space, Typography } from 'antd';
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { fetchOneBill, sendBillAsPDF } from '../api';
import { withLayout } from '../layouts/main';
import { Bill } from '../types/bill';
import NotFoundPage from './notFound';
export type QueryParams = { id: string };
const BillPage = () => {
// Hooks
const { id } = useParams<QueryParams>();
const [sent, setSent] = useState(false);
// Local State
const [bill, setBill] = useState<Bill>({} as Bill);
// Effects
useEffect(() => {
const loadBIllById = async (id: string) => {
const billID = parseInt(id);
const { data: loadedBill, error } = await fetchOneBill(billID);
if (!loadedBill || error) {
return <NotFoundPage />;
}
setBill(() => loadedBill);
return;
};
loadBIllById(id);
}, [id]);
// Logic
const handleSendPDF = (id: number) => {
sendBillAsPDF(id);
message.success('The bill will be sent to the customer');
setSent(() => true);
};
return (
<main>
<Typography.Title>Facture #VFNI{`${bill.id}`.padStart(4, '0')}</Typography.Title>
<Space>
<Button type="primary" onClick={() => handleSendPDF(bill.id)} disabled={sent}>
{sent ? 'The bill is on its way to your customer' : 'Send Bill'}
</Button>
</Space>
<Space>
<Typography.Text>{bill?.name}</Typography.Text>
<Typography.Text>{bill?.price} </Typography.Text>
<Typography.Text>
from {bill?.start} to {bill?.end}
</Typography.Text>
</Space>
</main>
);
};
export default withLayout(BillPage);

43
src/pages/bills.tsx Normal file
View file

@ -0,0 +1,43 @@
import { Card, List } from 'antd';
import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { fetchAllBills } from '../api';
import { withLayout } from '../layouts/main';
import { Bill } from '../types/bill';
function BillsPage() {
// Local State
const [bills, setBills] = useState<Bill[]>([]);
// Effects
useEffect(() => {
const loadBills = async () => {
const loadedBills = await fetchAllBills();
setBills(() => loadedBills);
};
loadBills();
}, []);
return (
<section>
<h1>All bills</h1>
<List
grid={{ gutter: 16, column: 4 }}
pagination={{ pageSize: 12 }}
dataSource={bills}
renderItem={(bill) => (
<Link to={`/bills/${bill.id}`}>
<List.Item>
<Card title={bill.id} bordered={false}>
<p>{bill.name}</p>
</Card>
</List.Item>
</Link>
)}
/>
</section>
);
}
export default withLayout(BillsPage);

View file

@ -1,12 +1,15 @@
import { Button, Form, Input, Switch } from "antd"; import { Button, Form, Input, Switch } from 'antd';
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from 'react-hook-form';
import { createBill } from "../api"; import { createBill } from '../api';
import { InputSelect } from "../components/inputSelect"; import { InputSelect } from '../components/inputSelect';
import { withLayout } from "../layouts/main"; import { withLayout } from '../layouts/main';
import { BillForm } from "../types/bill"; import { BillForm } from '../types/bill';
const Home = () => { const HomePage = () => {
// Hooks
const { register, handleSubmit, control } = useForm<BillForm>(); const { register, handleSubmit, control } = useForm<BillForm>();
// Logic
const onSubmit = handleSubmit((data) => createBill(data)); const onSubmit = handleSubmit((data) => createBill(data));
return ( return (
@ -16,23 +19,23 @@ const Home = () => {
<Form layout="vertical" onFinish={onSubmit}> <Form layout="vertical" onFinish={onSubmit}>
<Form.Item label="Customer name"> <Form.Item label="Customer name">
<Input placeholder="Cameron Doe" {...register("name")} /> <Input placeholder="Cameron Doe" {...register('name')} />
</Form.Item> </Form.Item>
<Form.Item label="Customer phone number"> <Form.Item label="Customer phone number">
<Input placeholder="06 12 34 56 78" {...register("phoneNumber")} /> <Input placeholder="06 12 34 56 78" {...register('phoneNumber')} />
</Form.Item> </Form.Item>
<Form.Item label="Price"> <Form.Item label="Price">
<Input placeholder="75.00" addonAfter="€" {...register("price")} /> <Input placeholder="75.00" addonAfter="€" {...register('price')} />
</Form.Item> </Form.Item>
<Form.Item label="Start"> <Form.Item label="Start">
<Input type="date" {...register("start")} /> <Input type="date" {...register('start')} />
</Form.Item> </Form.Item>
<Form.Item label="End"> <Form.Item label="End">
<Input type="date" {...register("end")} /> <Input type="date" {...register('end')} />
</Form.Item> </Form.Item>
<InputSelect <InputSelect
@ -40,11 +43,11 @@ const Home = () => {
name="room" name="room"
label="Room" label="Room"
placeholder="Choose a room to stay" placeholder="Choose a room to stay"
options={["T2 Corail", "T3 Azur"]} options={['T2 Corail', 'T3 Azur']}
/> />
<Form.Item label="Customers number"> <Form.Item label="Customers number">
<Input type="number" {...register("customers")} placeholder="1" /> <Input type="number" {...register('customers')} placeholder="1" />
</Form.Item> </Form.Item>
<InputSelect <InputSelect
@ -52,7 +55,7 @@ const Home = () => {
name="platform" name="platform"
label="Booking Platform" label="Booking Platform"
placeholder="Select a booking platform" placeholder="Select a booking platform"
options={["Site", "Booking.com", "AirBnB", "TripAdvisor", "Perso"]} options={['Site', 'Booking.com', 'AirBnB', 'TripAdvisor', 'Perso']}
/> />
<Controller <Controller
@ -80,7 +83,7 @@ const Home = () => {
name="paymentMethod" name="paymentMethod"
label="Payment method" label="Payment method"
placeholder="How do you want to pay?" placeholder="How do you want to pay?"
options={["Card", "Cash", "Cheque", "Transfer"]} options={['Card', 'Cash', 'Cheque', 'Transfer']}
/> />
<InputSelect <InputSelect
@ -88,7 +91,7 @@ const Home = () => {
name="paymentStatus" name="paymentStatus"
label="Payment status" label="Payment status"
placeholder="What is the current payment status?" placeholder="What is the current payment status?"
options={["Pending", "Canceled", "Completed", "Refunded"]} options={['Pending', 'Canceled', 'Completed', 'Refunded']}
/> />
<Form.Item> <Form.Item>
@ -102,4 +105,4 @@ const Home = () => {
); );
}; };
export default withLayout(Home); export default withLayout(HomePage);

7
src/pages/notFound.tsx Normal file
View file

@ -0,0 +1,7 @@
import { withLayout } from '../layouts/main';
function NotFoundPage() {
return <div>Hoho</div>;
}
export default withLayout(NotFoundPage);

View file

@ -1 +0,0 @@
@import "antd/dist/antd.css";

118
yarn.lock
View file

@ -1191,7 +1191,7 @@
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.14.6" version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg== integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
@ -1820,6 +1820,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/history@*":
version "4.7.9"
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.9.tgz#1cfb6d60ef3822c589f18e70f8b12f9a28ce8724"
integrity sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==
"@types/html-minifier-terser@^5.0.0": "@types/html-minifier-terser@^5.0.0":
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57"
@ -1904,6 +1909,23 @@
dependencies: dependencies:
"@types/react" "*" "@types/react" "*"
"@types/react-router-dom@^5.1.8":
version "5.1.8"
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.8.tgz#bf3e1c8149b3d62eaa206d58599de82df0241192"
integrity sha512-03xHyncBzG0PmDmf8pf3rehtjY0NpUj7TIN46FrT5n1ZWHPZvXz32gUyNboJ+xsL8cpg8bQVLcllptcQHvocrw==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react-router" "*"
"@types/react-router@*":
version "5.1.16"
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.16.tgz#f3ba045fb96634e38b21531c482f9aeb37608a99"
integrity sha512-8d7nR/fNSqlTFGHti0R3F9WwIertOaaA1UEB8/jr5l5mDMOs4CidEgvvYMw4ivqrBK+vtVLxyTj2P+Pr/dtgzg==
dependencies:
"@types/history" "*"
"@types/react" "*"
"@types/react@*": "@types/react@*":
version "17.0.14" version "17.0.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.14.tgz#f0629761ca02945c4e8fea99b8177f4c5c61fb0f" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.14.tgz#f0629761ca02945c4e8fea99b8177f4c5c61fb0f"
@ -5614,6 +5636,18 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
history@^4.9.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
dependencies:
"@babel/runtime" "^7.1.2"
loose-envify "^1.2.0"
resolve-pathname "^3.0.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
value-equal "^1.0.1"
hmac-drbg@^1.0.1: hmac-drbg@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@ -5623,6 +5657,13 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0" minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1" minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.1.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
hoopy@^0.1.4: hoopy@^0.1.4:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
@ -6304,6 +6345,11 @@ is-wsl@^2.1.1, is-wsl@^2.2.0:
dependencies: dependencies:
is-docker "^2.0.0" is-docker "^2.0.0"
isarray@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@ -7143,7 +7189,7 @@ loglevel@^1.6.8:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@ -7349,6 +7395,14 @@ min-indent@^1.0.0:
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
mini-create-react-context@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e"
integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==
dependencies:
"@babel/runtime" "^7.12.1"
tiny-warning "^1.0.3"
mini-css-extract-plugin@0.11.3: mini-css-extract-plugin@0.11.3:
version "0.11.3" version "0.11.3"
resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz#15b0910a7f32e62ffde4a7430cfefbd700724ea6"
@ -8111,6 +8165,13 @@ path-to-regexp@0.1.7:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-to-regexp@^1.7.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
dependencies:
isarray "0.0.1"
path-type@^3.0.0: path-type@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
@ -8978,7 +9039,7 @@ prompts@^2.0.1:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.5" sisteransi "^1.0.5"
prop-types@^15.7.2: prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -9540,7 +9601,7 @@ react-hook-form@^7.8.0:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.9.0.tgz#0b5ed2f262a1e3cc64cfcf855f09a6e236d46ac3" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.9.0.tgz#0b5ed2f262a1e3cc64cfcf855f09a6e236d46ac3"
integrity sha512-1SazsTvsC5A4jLxc8fIf0bB92kEp4MGjP69k8s+2nI1spHPha5UkLwaebOXhO9vY95aGqcyBU67pRiv+6T5KZQ== integrity sha512-1SazsTvsC5A4jLxc8fIf0bB92kEp4MGjP69k8s+2nI1spHPha5UkLwaebOXhO9vY95aGqcyBU67pRiv+6T5KZQ==
react-is@^16.12.0, react-is@^16.8.1: react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -9555,6 +9616,35 @@ react-refresh@^0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
react-router-dom@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
loose-envify "^1.3.1"
prop-types "^15.6.2"
react-router "5.2.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-router@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293"
integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
hoist-non-react-statics "^3.1.0"
loose-envify "^1.3.1"
mini-create-react-context "^0.4.0"
path-to-regexp "^1.7.0"
prop-types "^15.6.2"
react-is "^16.6.0"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
react-scripts@4.0.3: react-scripts@4.0.3:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345"
@ -9882,6 +9972,11 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
resolve-pathname@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
resolve-url-loader@^3.1.2: resolve-url-loader@^3.1.2:
version "3.1.4" version "3.1.4"
resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.4.tgz#3c16caebe0b9faea9c7cc252fa49d2353c412320" resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.4.tgz#3c16caebe0b9faea9c7cc252fa49d2353c412320"
@ -10990,6 +11085,16 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
tiny-invariant@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
tiny-warning@^1.0.0, tiny-warning@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
tmpl@1.0.x: tmpl@1.0.x:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
@ -11411,6 +11516,11 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0" spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0" spdx-expression-parse "^3.0.0"
value-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
vary@~1.1.2: vary@~1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"