⬆️ react router

This commit is contained in:
Ruidy 2022-09-10 13:38:48 +02:00
parent 735354da72
commit 115195ce3f
10 changed files with 590 additions and 425 deletions

View file

@ -9,26 +9,26 @@
"eject": "react-scripts eject" "eject": "react-scripts eject"
}, },
"dependencies": { "dependencies": {
"antd": "^4.16.6", "antd": "^4.23.1",
"axios": "^0.21.2", "axios": "^0.27.2",
"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.35.0",
"react-router-dom": "^5.2.0", "react-router-dom": "^6.3.0",
"react-scripts": "^5.0.0" "react-scripts": "^5.0.1"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^11.1.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^14.4.3",
"@types/jest": "^26.0.15", "@types/jest": "^29.0.0",
"@types/node": "^12.0.0", "@types/node": "^18.7.16",
"@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", "@types/react-router-dom": "^5.3.3",
"prettier": "^2.2.1", "prettier": "^2.7.1",
"typescript": "^4.3.4", "typescript": "^4.8.3",
"web-vitals": "^1.0.1" "web-vitals": "^3.0.1"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [

View file

@ -1,4 +1,4 @@
import { Route, Switch } from 'react-router-dom'; import { Route, Routes } from 'react-router-dom';
import BillPage from './pages/bill'; import BillPage from './pages/bill';
import BillsPage from './pages/bills'; import BillsPage from './pages/bills';
import HomePage from './pages/home'; import HomePage from './pages/home';
@ -6,10 +6,9 @@ import NewBillPage from './pages/newBill';
import NotFoundPage from './pages/notFound'; import NotFoundPage from './pages/notFound';
import ReportPage from './pages/report'; import ReportPage from './pages/report';
type RouteConfig = { type Params = {
path: string; path: string;
component: ({ ...props }: any) => JSX.Element; component: ({ ...props }: any) => JSX.Element;
exact?: boolean;
}; };
export const AppRoutes = { export const AppRoutes = {
@ -20,23 +19,20 @@ export const AppRoutes = {
}; };
export default function Router() { export default function Router() {
const routes: RouteConfig[] = [ const routes: Params[] = [
// Home // Home
{ {
path: AppRoutes.home, path: AppRoutes.home,
component: HomePage, component: HomePage
exact: true
}, },
// Bills // Bills
{ {
path: `${AppRoutes.bills}/new`, path: `${AppRoutes.bills}/new`,
component: NewBillPage, component: NewBillPage
exact: true
}, },
{ {
path: AppRoutes.bills, path: AppRoutes.bills,
component: BillsPage, component: BillsPage
exact: true
}, },
{ {
path: `${AppRoutes.bills}/:id`, path: `${AppRoutes.bills}/:id`,
@ -45,8 +41,7 @@ export default function Router() {
// Reports // Reports
{ {
path: AppRoutes.reports, path: AppRoutes.reports,
component: ReportPage, component: ReportPage
exact: true
}, },
// … rest // … rest
{ {
@ -56,12 +51,12 @@ export default function Router() {
]; ];
return ( return (
<Switch> <>
{routes.map(({ exact, path, component: Component }) => ( <Routes>
<Route key={path} exact={!!exact} path={path}> {routes.map(({ path, component: Component }) => (
<Component /> <Route key={path} path={path} element={<Component />} />
</Route> ))}
))} </Routes>
</Switch> </>
); );
} }

View file

@ -20,7 +20,7 @@ export const InputSelect = ({ control, name, label, placeholder, options }: Inpu
placeholder={placeholder} placeholder={placeholder}
optionFilterProp="children" optionFilterProp="children"
filterOption={(input, option) => filterOption={(input, option) =>
option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 option?.label!.toLowerCase().indexOf(input.toLowerCase())! >= 0
} }
options={options.map((label, value) => ({ options={options.map((label, value) => ({
value, value,

View file

@ -1,5 +1,5 @@
import { Layout, Menu, Row } from 'antd'; import { Layout, Menu, Row } from 'antd';
import { Link, useRouteMatch } from 'react-router-dom'; import { Link, useMatch } from 'react-router-dom';
import { AppRoutes } from '../Router'; import { AppRoutes } from '../Router';
const { Header, Content, Footer } = Layout; const { Header, Content, Footer } = Layout;
@ -7,7 +7,6 @@ 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 { url } = useRouteMatch();
const menuItems = [ const menuItems = [
{ label: 'Home', path: AppRoutes.home }, { label: 'Home', path: AppRoutes.home },
{ label: 'Bills', path: AppRoutes.bills }, { label: 'Bills', path: AppRoutes.bills },
@ -24,7 +23,7 @@ export const withLayout =
theme="dark" theme="dark"
mode="horizontal" mode="horizontal"
selectedKeys={[ selectedKeys={[
(menuItems.findIndex((item) => url.includes(item.path)) + 1).toString() (menuItems.findIndex((item) => useMatch(item.path)) + 1).toString()
]} ]}
> >
{menuItems.map(({ label, path }, index) => ( {menuItems.map(({ label, path }, index) => (

View file

@ -1,15 +1,15 @@
import { Button, Result } from 'antd'; import { Button, Result } from 'antd';
import { useHistory } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
export function BillSent() { export function BillSent() {
const history = useHistory(); const navigate = useNavigate();
return ( return (
<Result <Result
status="success" status="success"
title="Bill sent" title="Bill sent"
subTitle="The bill is on its way to your customer" subTitle="The bill is on its way to your customer"
extra={[ extra={[
<Button key="back" type="primary" onClick={() => history.push('/')}> <Button key="back" type="primary" onClick={() => navigate('/')}>
Go Back Home Go Back Home
</Button> </Button>
]} ]}

View file

@ -1,7 +1,7 @@
import { Button, Col, Divider, message, PageHeader, Space, Typography } from 'antd'; import { Button, Col, Divider, message, PageHeader, Space, Typography } from 'antd';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { useHistory, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { fetchOneBill, sendBillAsPDF, updateBill } from '../../api/bills'; import { fetchOneBill, sendBillAsPDF, updateBill } from '../../api/bills';
import { BillForm } from '../../components/billForm'; import { BillForm } from '../../components/billForm';
import { withLayout } from '../../layouts/main'; import { withLayout } from '../../layouts/main';
@ -13,7 +13,7 @@ export type QueryParams = { id: string };
const BillPage = () => { const BillPage = () => {
// Hooks // Hooks
let { id } = useParams<QueryParams>(); let { id } = useParams<QueryParams>();
const history = useHistory(); const navigate = useNavigate();
const { handleSubmit, control, reset } = useForm<BillFormType>(); const { handleSubmit, control, reset } = useForm<BillFormType>();
// Local State // Local State
@ -36,7 +36,7 @@ const BillPage = () => {
); );
useEffect(() => { useEffect(() => {
loadBill(id); loadBill(id!);
}, [id, loadBill, reset]); }, [id, loadBill, reset]);
// Logic // Logic
@ -47,12 +47,12 @@ const BillPage = () => {
}; };
const onSubmit = handleSubmit(async (data) => { const onSubmit = handleSubmit(async (data) => {
const { error } = await updateBill(parseInt(id), data); const { error } = await updateBill(parseInt(id!), data);
if (error) { if (error) {
message.error(`Update failed because of ${error}`); message.error(`Update failed because of ${error}`);
} }
setEdit(() => false); setEdit(() => false);
loadBill(id); loadBill(id!);
}); });
const content = edit ? ( const content = edit ? (
@ -72,7 +72,7 @@ const BillPage = () => {
return ( return (
<> <>
<PageHeader <PageHeader
onBack={() => history.goBack()} onBack={() => navigate(-1)}
title={`Facture #VFNI${bill.id?.toString().padStart(4, '0')}`} title={`Facture #VFNI${bill.id?.toString().padStart(4, '0')}`}
subTitle={bill.name} subTitle={bill.name}
/> />

View file

@ -1,19 +1,19 @@
import { Button, Row } from 'antd'; import { Button, Row } from 'antd';
import { useHistory } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { withLayout } from '../layouts/main'; import { withLayout } from '../layouts/main';
function HomePage() { function HomePage() {
// Hooks // Hooks
const history = useHistory(); const navigate = useNavigate();
return ( return (
<> <>
<h1>Rent it Like a Pro</h1> <h1>Rent it Like a Pro</h1>
<Row> <Row>
<Button type="primary" size="large" onClick={() => history.push('/bills/new')}> <Button type="primary" size="large" onClick={() => navigate('/bills/new')}>
Add Bill Add Bill
</Button> </Button>
<Button type="default" size="large" onClick={() => history.push('/reports')}> <Button type="default" size="large" onClick={() => navigate('/reports')}>
Edit Report Edit Report
</Button> </Button>
</Row> </Row>

View file

@ -1,5 +1,5 @@
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { useHistory } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { createBill } from '../../api/bills'; import { createBill } from '../../api/bills';
import { BillForm } from '../../components/billForm'; import { BillForm } from '../../components/billForm';
import { withLayout } from '../../layouts/main'; import { withLayout } from '../../layouts/main';
@ -8,12 +8,12 @@ import { BillFormType } from '../../types/bill';
const NewBillPage = () => { const NewBillPage = () => {
// Hooks // Hooks
const { handleSubmit, control } = useForm<BillFormType>(); const { handleSubmit, control } = useForm<BillFormType>();
const history = useHistory(); const navigate = useNavigate();
// Logic // Logic
const onSubmit = handleSubmit(async (data) => { const onSubmit = handleSubmit(async (data) => {
const newId = await createBill(data); const newId = await createBill(data);
history.push(`/bills/${newId}`); navigate(`/bills/${newId}`);
}); });
return ( return (

View file

@ -1,14 +1,14 @@
import { Button, Image, Row } from 'antd'; import { Button, Image, Row } from 'antd';
import { useHistory } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import NotFoundImage from '../assets/notFound/404.png'; import NotFoundImage from '../assets/notFound/404.png';
import { withLayout } from '../layouts/main'; import { withLayout } from '../layouts/main';
function NotFoundPage() { function NotFoundPage() {
const history = useHistory(); const navigate = useNavigate();
return ( return (
<> <>
<Row justify="center"> <Row justify="center">
<Button size="large" type="link" onClick={() => history.push('/')}> <Button size="large" type="link" onClick={() => navigate('/')}>
Go Back to Safety Go Back to Safety
</Button> </Button>
</Row> </Row>

909
yarn.lock

File diff suppressed because it is too large Load diff