mirror of
https://github.com/rjNemo/melon_frontend
synced 2026-06-12 13:26:43 +00:00
⬆️ react router
This commit is contained in:
parent
735354da72
commit
115195ce3f
10 changed files with 590 additions and 425 deletions
28
package.json
28
package.json
|
|
@ -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": [
|
||||||
|
|
|
||||||
|
|
@ -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>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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) => (
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
]}
|
]}
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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 (
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue