Skip to content

Commit 6b0c921

Browse files
committed
Use react-router-dom to manage routing
1 parent c1c230f commit 6b0c921

File tree

8 files changed

+186
-75
lines changed

8 files changed

+186
-75
lines changed

django_react/urls.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
urlpatterns = [
2020
path('', include('leads.urls')),
21-
path('', include('frontend.urls')),
2221
path('admin/', admin.site.urls),
2322
path('api/', include('api.urls')),
23+
24+
# Must be last, as it's a catch-all
25+
path('', include('frontend.urls')),
2426
]

frontend/package-lock.json

+67
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"css-loader": "^6.7.3",
2020
"react": "^17.0.2",
2121
"react-dom": "^17.0.2",
22+
"react-router-dom": "^6.6.2",
2223
"universal-cookie": "^4.0.4",
2324
"webpack": "^5.75.0",
2425
"webpack-cli": "^5.0.1"

frontend/src/components/App.jsx

+15-14
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Box from '@mui/material/Box';
99
import Grid from '@mui/material/Grid';
1010
import {anonUser} from "./Authentication";
1111
import {AppContext} from "./AppContext";
12+
import Welcome from "./Welcome";
13+
import {Route, Routes, Router, BrowserRouter} from 'react-router-dom';
1214

1315

1416
const darkTheme = createTheme({
@@ -50,28 +52,27 @@ export function App() {
5052
<AppContext.Provider value={{user, darkMode, error, setUser, setError}}>
5153
<ThemeProvider theme={darkMode ? darkTheme : lightTheme}>
5254
<CssBaseline/>
53-
<ButtonAppBar onChangeTheme={changeTheme}/>
54-
<Box align="center" sx={{flexGrow: 1}} style={{marginLeft: 20, marginRight: 20}}>
55-
<Grid container align="left" maxWidth="xl" spacing={1} wrap="wrap">
56-
{!user.isAuthenticated ? <Grid item xs={12}>
57-
<h1>Login</h1>
58-
<Alert severity="error">Please login to see the lead list.</Alert>
59-
</Grid> : <>
60-
<Grid item xs={12}>
61-
<h1>Lead List</h1>
62-
</Grid>
55+
56+
<ButtonAppBar onChangeTheme={changeTheme}/>
57+
<Box align="center" sx={{flexGrow: 1}} style={{marginLeft: 20, marginRight: 20}}>
58+
<Grid container align="left" maxWidth="xl" spacing={1} wrap="wrap">
6359
<Grid item xs={12}>
64-
<LeadList/>
60+
<Routes>
61+
<Route exact path="/" element={<Welcome />} />
62+
<Route exact path="/lead-list" element={<LeadList />} />
63+
</Routes>
6564
</Grid>
66-
</>}
67-
</Grid>
68-
</Box>
65+
</Grid>
66+
</Box>
67+
6968
</ThemeProvider>
7069
</AppContext.Provider>
7170
)
7271
}
7372

7473
const container = document.getElementById("app");
7574
render(<React.StrictMode>
75+
<BrowserRouter>
7676
<App/>
77+
</BrowserRouter>
7778
</React.StrictMode>, container);

frontend/src/components/AppBar.jsx

+17-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import Brightness4Icon from '@mui/icons-material/Brightness4';
1717
import Brightness7Icon from '@mui/icons-material/Brightness7';
1818
import {LoginDialog} from './Authentication';
1919
import {AppContext} from "./AppContext";
20+
import {Link as RouterLink} from "react-router-dom";
21+
import {Link} from "@mui/material";
2022

2123
function ResponsiveAppBar({onChangeTheme}) {
2224
const [anchorElNav, setAnchorElNav] = React.useState(null);
@@ -106,7 +108,10 @@ function ResponsiveAppBar({onChangeTheme}) {
106108
}}
107109
>
108110
<MenuItem key="home" onClick={handleCloseNavMenu}>
109-
<Typography textAlign="center">Home</Typography>
111+
<Typography style={{ color: 'inherit', textDecoration: 'inherit'}} textAlign="center" component={RouterLink} to="/">Home</Typography>
112+
</MenuItem>
113+
<MenuItem key="lead-list" onClick={handleCloseNavMenu}>
114+
<Typography style={{ color: 'inherit', textDecoration: 'inherit'}} color="inherit" textAlign="center" component={RouterLink} to="/lead-list">Lead List</Typography>
110115
</MenuItem>
111116
</Menu>
112117
</Box>
@@ -135,12 +140,23 @@ function ResponsiveAppBar({onChangeTheme}) {
135140
{/* Desktop menu */}
136141
<Box sx={{flexGrow: 1, display: {xs: 'none', md: 'flex'}}}>
137142
<Button
143+
component={RouterLink}
144+
to="/"
138145
key="home"
139146
onClick={handleCloseNavMenu}
140147
sx={{my: 2, color: 'white', display: 'block'}}
141148
>
142149
Home
143150
</Button>
151+
<Button
152+
component={RouterLink}
153+
to="/lead-list"
154+
key="lead-list"
155+
onClick={handleCloseNavMenu}
156+
sx={{my: 2, color: 'white', display: 'block'}}
157+
>
158+
Lead List
159+
</Button>
144160
</Box>
145161

146162
{/* User icon & menu */}

frontend/src/components/LeadList.jsx

+67-59
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {Component} from "react";
1+
import React, {Component, useContext, useEffect, useState} from "react";
22
import Table from '@mui/material/Table';
33
import TableBody from '@mui/material/TableBody';
44
import TableCell from '@mui/material/TableCell';
@@ -7,75 +7,83 @@ import TableHead from '@mui/material/TableHead';
77
import TableRow from '@mui/material/TableRow';
88
import Paper from '@mui/material/Paper';
99
import Alert from "@mui/material/Alert";
10+
import Grid from "@mui/material/Grid";
11+
import {AppContext} from "./AppContext";
1012

1113

12-
class LeadList extends Component {
13-
constructor(props) {
14-
super(props);
15-
this.state = {
16-
data: [],
17-
error: ''
18-
};
19-
}
14+
function LeadList(props) {
15+
const [data, setData] = useState([]);
16+
const [error, setError] = useState([]);
17+
18+
const appContext = useContext(AppContext);
2019

21-
componentDidMount() {
20+
useEffect(()=>{
2221
const requestOptions = {
2322
headers: { 'Accept': 'application/json' },
2423
};
2524

26-
fetch("api/lead/", requestOptions)
27-
.then(response => {
28-
if (response.status > 400) {
29-
return this.setState(() => {
30-
return { error: 'Request status: ' + response.status + ' - ' + response.statusText };
31-
});
32-
}
33-
return response.json();
34-
})
35-
.then(data => {
36-
this.setState(() => {
37-
return {
38-
data
39-
};
25+
if (appContext.user.isAuthenticated) {
26+
fetch("api/lead/", requestOptions)
27+
.then(response => {
28+
if (response.status > 400) {
29+
return setError('Request status: ' + response.status + ' - ' + response.statusText);
30+
}
31+
return response.json();
32+
})
33+
.then(data => {
34+
setData(data);
4035
});
41-
});
42-
}
36+
}
37+
else
38+
{
39+
setError('');
40+
}
41+
42+
},[appContext.user.isAuthenticated])
4343

44-
render() {
45-
return (
46-
<>
47-
{this.state.error == '' ?
48-
<TableContainer component={Paper}>
49-
<Table size="small" aria-label="Lead List">
50-
<TableHead>
51-
<TableRow>
52-
<TableCell>Name</TableCell>
53-
<TableCell>Email</TableCell>
54-
<TableCell>Message</TableCell>
55-
</TableRow>
56-
</TableHead>
57-
<TableBody>
58-
{this.state.data.map((contact) => (
59-
<TableRow
60-
key={contact.name}
61-
sx={{'&:last-child td, &:last-child th': {border: 0}}}
62-
>
63-
<TableCell component="th" scope="row">
64-
{contact.name}
65-
</TableCell>
66-
<TableCell>{contact.email}</TableCell>
67-
<TableCell>{contact.message}</TableCell>
68-
</TableRow>
69-
))}
70-
</TableBody>
71-
</Table>
72-
</TableContainer>
44+
return (
45+
<>
46+
{!appContext.user.isAuthenticated ?
47+
<>
48+
<h1>Login</h1>
49+
<Alert severity="error">Please login to see the lead list.</Alert>
50+
</>
7351
:
74-
<Alert severity="error">{this.state.error}</Alert>
52+
<>
53+
<h1>Lead List</h1>
54+
{error == '' ?
55+
<TableContainer component={Paper}>
56+
<Table size="small" aria-label="Lead List">
57+
<TableHead>
58+
<TableRow>
59+
<TableCell>Name</TableCell>
60+
<TableCell>Email</TableCell>
61+
<TableCell>Message</TableCell>
62+
</TableRow>
63+
</TableHead>
64+
<TableBody>
65+
{data.map((contact) => (
66+
<TableRow
67+
key={contact.name}
68+
sx={{'&:last-child td, &:last-child th': {border: 0}}}
69+
>
70+
<TableCell component="th" scope="row">
71+
{contact.name}
72+
</TableCell>
73+
<TableCell>{contact.email}</TableCell>
74+
<TableCell>{contact.message}</TableCell>
75+
</TableRow>
76+
))}
77+
</TableBody>
78+
</Table>
79+
</TableContainer>
80+
:
81+
<Alert severity="error">{error}</Alert>
82+
}
83+
</>
7584
}
76-
</>
77-
);
78-
}
85+
</>
86+
);
7987
}
8088

8189
export default LeadList;

frontend/src/components/Welcome.jsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as React from 'react';
2+
import Alert from '@mui/material/Alert';
3+
import AlertTitle from '@mui/material/AlertTitle';
4+
5+
export default function DescriptionAlerts() {
6+
return (
7+
<>
8+
<h1>Welcome</h1>
9+
<Alert severity="success">
10+
<AlertTitle>Welcome</AlertTitle>
11+
<strong>Welcome to the Leads App!</strong> Click the Leads option on the menu above to view leads.
12+
</Alert>
13+
</>
14+
);
15+
}

frontend/urls.py

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@
44

55
urlpatterns = [
66
path('', views.index),
7+
path('lead-list', views.index),
78
]

0 commit comments

Comments
 (0)