Adding redux

This commit is contained in:
2024-09-22 21:55:57 +02:00
parent 9ee066b10c
commit 5516900b1b
7 changed files with 221 additions and 14 deletions

View File

@@ -1,24 +1,35 @@
import React from "react";
import "./styles/App.css";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { store, persistor } from "./services/store";
import PosterSelector from "./components/PosterSelector";
import PosterGallery from "./components/PosterGallery";
import UploadDiary from "./components/UploadDiary";
import GlobalDownloadButton from "./components/DownloadButton";
function App() {
return (
<Router>
<div className="App">
<Routes>
<Route path="/" element={<UploadDiary />} />
<Route path="/PosterSelector" element={<PosterSelector />} />
<Route
path="/posters/:movieName/:movieYear"
element={<PosterGallery />}
/>
</Routes>
</div>
</Router>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
{
<Router>
<div className="App">
<Routes>
<Route path="/" element={<UploadDiary />} />
<Route path="/PosterSelector" element={<PosterSelector />} />
<Route
path="/posters/:movieName/:movieYear"
element={<PosterGallery />}
/>
</Routes>
</div>
</Router>
}
<GlobalDownloadButton />
</PersistGate>
</Provider>
);
}

View File

@@ -0,0 +1,45 @@
import React from "react";
import { useSelector } from "react-redux";
import { Fab, makeStyles } from "@material-ui/core";
import GetAppIcon from "@material-ui/icons/GetApp";
const useStyles = makeStyles((theme) => ({
downloadFab: {
backgroundColor: "#1caff2",
position: "fixed",
bottom: theme.spacing(4),
left: "50%",
transform: "translateX(-50%)",
zIndex: 1000,
},
}));
const GlobalDownloadButton = () => {
const classes = useStyles();
const selectedPosters = useSelector((state) => {
const selections = state.posterSelections;
return Object.values(selections).flat();
});
const totalSelected = selectedPosters.length;
if (totalSelected === 0) return null;
const handleDownload = () => {
// Implement your download logic here
console.log("Downloading", totalSelected, "posters");
};
return (
<Fab
variant="extended"
className={classes.downloadFab}
onClick={handleDownload}
>
<GetAppIcon />
Download ({totalSelected})
</Fab>
);
};
export default GlobalDownloadButton;

View File

@@ -1,6 +1,8 @@
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
import { useSelector, useDispatch } from "react-redux";
import { selectPoster, deselectPoster } from "../services/action";
import {
Container,
Typography,
@@ -12,6 +14,7 @@ import {
makeStyles,
Paper,
} from "@material-ui/core";
import CheckIcon from "@material-ui/icons/Check";
const useStyles = makeStyles((theme) => ({
root: {
@@ -29,11 +32,30 @@ const useStyles = makeStyles((theme) => ({
fontWeight: "400",
},
posterCard: {
position: "relative",
height: "100%",
display: "flex",
flexDirection: "column",
backgroundColor: "transparent",
boxShadow: "none",
cursor: "pointer",
transition: "all 0.3s ease",
"&:hover": {
transform: "scale(1.05)",
},
},
selectedPoster: {
border: `4px solid ${theme.palette.primary.main}`,
borderRadius: theme.shape.borderRadius,
},
checkIcon: {
position: "absolute",
top: theme.spacing(1),
right: theme.spacing(1),
backgroundColor: theme.palette.primary.main,
color: theme.palette.common.white,
borderRadius: "50%",
padding: theme.spacing(0.5),
},
posterImage: {
paddingTop: "150%",
@@ -51,11 +73,15 @@ const useStyles = makeStyles((theme) => ({
},
}));
const PosterGallery = () => {
const PosterGallery = ({ movieId }) => {
const classes = useStyles();
const [posters, setPosters] = useState([]);
const [loading, setLoading] = useState(true);
const { movieName, movieYear } = useParams();
const dispatch = useDispatch();
const selectedPosters = useSelector(
(state) => state.posterSelections[movieId] || []
);
useEffect(() => {
const fetchPosters = async () => {
@@ -75,6 +101,14 @@ const PosterGallery = () => {
fetchPosters();
}, [movieName, movieYear]);
const handlePosterSelect = (posterId) => {
if (selectedPosters.includes(posterId)) {
dispatch(deselectPoster(movieId, posterId));
} else {
dispatch(selectPoster(movieId, posterId));
}
};
return (
<Container className={classes.root}>
<Paper elevation={3} className={classes.paper}>
@@ -89,12 +123,22 @@ const PosterGallery = () => {
<Grid container spacing={3}>
{posters.map((poster, index) => (
<Grid item xs={12} sm={6} md={4} lg={3} key={index}>
<Card className={classes.posterCard}>
<Card
className={`${classes.posterCard} ${
selectedPosters.includes(poster.file_path)
? classes.selectedPoster
: ""
}`}
onClick={() => handlePosterSelect(poster.file_path)}
>
<CardMedia
className={classes.posterImage}
image={`https://image.tmdb.org/t/p/w500${poster.file_path}`}
title={`${movieName} poster ${index + 1}`}
/>
{selectedPosters.includes(poster.file_path) && (
<CheckIcon className={classes.checkIcon} />
)}
</Card>
</Grid>
))}

11
src/services/action.js Normal file
View File

@@ -0,0 +1,11 @@
export const selectPoster = (movieId, posterId) => ({
type: "SELECT_POSTER",
movieId,
posterId,
});
export const deselectPoster = (movieId, posterId) => ({
type: "DESELECT_POSTER",
movieId,
posterId,
});

37
src/services/store.js Normal file
View File

@@ -0,0 +1,37 @@
import { legacy_createStore as createStore, combineReducers } from "redux";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
const posterSelectionReducer = (state = {}, action) => {
switch (action.type) {
case "SELECT_POSTER":
return {
...state,
[action.movieId]: [...(state[action.movieId] || []), action.posterId],
};
case "DESELECT_POSTER":
return {
...state,
[action.movieId]: state[action.movieId].filter(
(id) => id !== action.posterId
),
};
default:
return state;
}
};
const rootReducer = combineReducers({
posterSelections: posterSelectionReducer,
// other reducers...
});
const persistConfig = {
key: "root",
storage,
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(persistedReducer);
export const persistor = persistStore(store);