Skip to content

Commit 3da194a

Browse files
add a loading state
1 parent 40d29e2 commit 3da194a

File tree

1 file changed

+83
-69
lines changed

1 file changed

+83
-69
lines changed

client/src/pages/ProductionSearchPage.js

Lines changed: 83 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { useEffect, useState } from 'react';
2-
import { Button, Checkbox, Container, FormControlLabel, Grid, TextField, FormControl, InputLabel, Select, MenuItem } from
3-
'@mui/material';
2+
import { Button, Checkbox, Container, FormControlLabel, Grid, TextField, FormControl, InputLabel, Select, MenuItem } from '@mui/material';
43
import { DataGrid } from '@mui/x-data-grid';
54
import Typography from '@mui/material/Typography';
6-
75
import { NavLink } from 'react-router-dom';
86
const config = require('../config.json');
97

108
export default function ProductionSearchPage({ type }) {
119
const [data, setData] = useState([]);
1210
const [pageSize, setPageSize] = useState(25);
11+
const [loading, setLoading] = useState(true); // New state for loading
1312

1413
const [primaryTitle, setPrimaryTitle] = useState('');
1514
const [isAdult, setIsAdult] = useState(false);
@@ -19,15 +18,18 @@ export default function ProductionSearchPage({ type }) {
1918
const [averageRating, setAverageRating] = useState([0, 10]);
2019

2120
useEffect(() => {
21+
setLoading(true);
2222
fetch(`https://${config.server_host}:${config.server_port}/search_productions/${type}`)
2323
.then(res => res.json())
2424
.then(resJson => {
2525
const productionsWithId = resJson.map((production) => ({ id: production.titleId, ...production }));
2626
setData(productionsWithId);
27+
setLoading(false);
2728
});
2829
}, [type]);
2930

3031
const search = () => {
32+
setLoading(true);
3133
fetch(`https://${config.server_host}:${config.server_port}/search_productions/${type}?primaryTitle=${primaryTitle}` +
3234
`&isAdult=${isAdult}&startYearLow=${startYear[0]}&startYearHigh=${startYear[1]}&runtimeMinutesLow=${runtimeMinutes[0]}` +
3335
`&runtimeMinutesHigh=${runtimeMinutes[1]}&genre=${genre}&averageRatingLow=${averageRating[0]}` +
@@ -37,10 +39,10 @@ export default function ProductionSearchPage({ type }) {
3739
.then(resJson => {
3840
const productionsWithId = resJson.map((production) => ({ id: production.titleId, ...production }));
3941
setData(productionsWithId);
42+
setLoading(false);
4043
});
4144
};
4245

43-
// This defines the columns of the table of productions. We use the DataGrid component for the table.
4446
const columns = [
4547
{ field: 'primaryTitle', headerName: 'Title', width: 490, renderCell: (params) => (
4648
<NavLink to={`/production_info/${params.row.titleId}`}>{params.value}</NavLink>
@@ -59,43 +61,82 @@ export default function ProductionSearchPage({ type }) {
5961
typeDisplayed = 'Movies';
6062
releaseYear = [1900, 2023];
6163
runtime = [0, 1000];
62-
// ryWidth = 4;
63-
// rtWidth = 6;
6464
ryWidth = 4;
6565
rtWidth = 4;
6666
} else if (type === 'Short') {
6767
typeDisplayed = 'Shorts';
6868
releaseYear = [1900, 2023];
6969
runtime = [0, 110];
70-
// ryWidth = 5;
71-
// rtWidth = 4;
7270
ryWidth = 4;
7371
rtWidth = 4;
7472
} else {
7573
typeDisplayed = 'TV Series';
7674
releaseYear = [1930, 2023];
7775
runtime = [0, 5300];
78-
// ryWidth = 3;
79-
// rtWidth = 7;
8076
ryWidth = 4;
8177
rtWidth = 4;
8278
}
8379

8480
const genres = ['All', 'Documentary', 'Short', 'Animation', 'Comedy', 'Romance', 'Sport', 'News', 'Drama', 'Fantasy', 'Horror',
8581
'Biography', 'Music', 'War', 'Crime', 'Western', 'Family', 'Adventure', 'Action', 'History', 'Mystery', 'Sci-Fi', 'Musical',
8682
'Thriller', 'Film-Noir', 'Talk-Show', 'Game-Show', 'Reality-TV', 'Adult'];
87-
83+
84+
const rangeInputStyle = `
85+
input[type="range"]::-webkit-slider-thumb {
86+
-webkit-appearance: none;
87+
width: 20px;
88+
height: 20px;
89+
background: gray;
90+
cursor: pointer;
91+
border-radius: 50%;
92+
}
93+
input[type="range"]::-moz-range-thumb {
94+
width: 20px;
95+
height: 20px;
96+
background: gray;
97+
cursor: pointer;
98+
border-radius: 50%;
99+
}
100+
input[type="range"]::-ms-thumb {
101+
width: 20px;
102+
height: 20px;
103+
background: gray;
104+
cursor: pointer;
105+
border-radius: 50%;
106+
}
107+
`;
108+
109+
const getRowClassName = (params) => {
110+
if (params.index === 0) {
111+
return 'bold-row';
112+
}
113+
return '';
114+
};
115+
88116
return (
89117
<Container>
90-
<h2>Search {typeDisplayed}</h2>
118+
<style>
119+
{rangeInputStyle}
120+
{`
121+
.bold-row {
122+
font-weight: bold;
123+
}
124+
`}
125+
</style>
126+
<h2 style={{ textAlign: 'center', fontSize: '32px', marginBottom: '20px' }}>Search {typeDisplayed}</h2>
91127
<Grid container spacing={6}>
92128
<Grid item xs={6}>
93-
<TextField label='Title' value={primaryTitle} onChange={(e) => setPrimaryTitle(e.target.value)} style={{ width: "100%" }} />
129+
<TextField
130+
label='Title'
131+
value={primaryTitle}
132+
onChange={(e) => setPrimaryTitle(e.target.value)}
133+
style={{ width: "100%", border: '1px solid #ccc', borderRadius: '4px', marginBottom: '20px' }}
134+
/>
94135
</Grid>
95136
<Grid item xs={4}>
96-
<FormControl style={{ width: '100%' }}>
137+
<FormControl style={{ width: '100%', marginBottom: '20px' }}>
97138
<InputLabel id='genre_label'>Genre</InputLabel>
98-
<Select labelId='genre_label' label='Label' value={genre} onChange={(e) => setGenre(e.target.value)}>
139+
<Select labelId='genre_label' label='Genre' value={genre} onChange={(e) => setGenre(e.target.value)}>
99140
{genres.map((genre) => (
100141
<MenuItem key={genre} value={genre}>{genre}</MenuItem>
101142
))}
@@ -106,41 +147,9 @@ export default function ProductionSearchPage({ type }) {
106147
<FormControlLabel
107148
label='Adult'
108149
control={<Checkbox checked={isAdult} onChange={(e) => setIsAdult(e.target.checked)} />}
150+
style={{ marginBottom: '20px' }}
109151
/>
110152
</Grid>
111-
{/* <Grid item xs={ryWidth}>
112-
<p>Release Year</p>
113-
<Slider style={{ color: 'black' }}
114-
value={startYear}
115-
min={releaseYear[0]}
116-
max={releaseYear[1]}
117-
step={1}
118-
onChange={(e, newValue) => setStartYear(newValue)}
119-
valueLabelDisplay='auto'
120-
/>
121-
</Grid>
122-
<Grid item xs={rtWidth}>
123-
<p>Runtime (mins)</p>
124-
<Slider style={{ color: 'black' }}
125-
value={runtimeMinutes}
126-
min={runtime[0]}
127-
max={runtime[1]}
128-
step={1}
129-
onChange={(e, newValue) => setRuntimeMinutes(newValue)}
130-
valueLabelDisplay='auto'
131-
/>
132-
</Grid>
133-
<Grid item xs={12-ryWidth-rtWidth}>
134-
<p>Average Rating</p>
135-
<Slider style={{ color: 'black' }}
136-
value={averageRating}
137-
min={0.0}
138-
max={10.0}
139-
step={0.1}
140-
onChange={(e, newValue) => setAverageRating(newValue)}
141-
valueLabelDisplay='auto'
142-
/>
143-
</Grid> */}
144153
<Grid item xs={ryWidth}>
145154
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
146155
<div style={{ backgroundColor: 'gray', padding: '8px', borderRadius: '4px', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
@@ -232,12 +241,6 @@ export default function ProductionSearchPage({ type }) {
232241
</div>
233242
</Grid>
234243
</Grid>
235-
{/* <Button
236-
onClick={() => search()}
237-
style={{ backgroundColor: 'black', color: 'white', left: '50%',
238-
transform: 'translateX(-50%)', fontWeight: 'bold', marginTop: '25px' }}>
239-
Search
240-
</Button> */}
241244
<Button
242245
onClick={() => search()}
243246
style={{
@@ -246,22 +249,33 @@ export default function ProductionSearchPage({ type }) {
246249
left: '50%',
247250
transform: 'translateX(-50%)',
248251
fontWeight: 'bold',
249-
marginTop: '60px',
250-
marginBottom: '200px',
251-
fontSize: '20px', // Adjust the font size as needed
252-
padding: '15px 80px' // Adjust the padding as needed
253-
}}>
252+
marginTop: '40px',
253+
marginBottom: '60px',
254+
fontSize: '20px',
255+
padding: '15px 80px',
256+
}}
257+
>
254258
Search
255259
</Button>
256-
<h2>{typeDisplayed} YOU WOULD LIKE</h2>
257-
<DataGrid
258-
rows={data}
259-
columns={columns}
260-
pageSize={pageSize}
261-
rowsPerPageOptions={[10, 25, 50, 100]}
262-
onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
263-
autoHeight
264-
/>
260+
<h2 style={{ textAlign: 'center', marginBottom: '20px', fontSize: '28px' }}>{typeDisplayed} YOU WOULD LIKE</h2>
261+
<div style={{ marginBottom: '40px' }}>
262+
<DataGrid
263+
rows={loading ? [] : data} // Show empty rows if loading
264+
columns={columns}
265+
pageSize={pageSize}
266+
rowsPerPageOptions={[10, 25, 50, 100]}
267+
onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
268+
autoHeight
269+
getRowClassName={getRowClassName}
270+
components={{
271+
NoRowsOverlay: () => (
272+
<div style={{ padding: '10px', textAlign: 'center' }}>
273+
{loading ? "Loading..." : "No rows"}
274+
</div>
275+
)
276+
}}
277+
/>
278+
</div>
265279
</Container>
266280
);
267-
};
281+
}

0 commit comments

Comments
 (0)