Adding Cart page

This commit is contained in:
Pierret Hugo
2024-10-19 14:00:38 +02:00
parent 5516900b1b
commit 129fcb672c
7 changed files with 502 additions and 166 deletions

239
src/components/Cart.js Normal file
View File

@@ -0,0 +1,239 @@
import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
Container, Typography, Card, CardMedia, CardContent,
Button, Checkbox, FormControlLabel, TextField, Dialog, DialogTitle, DialogContent, DialogActions,
Paper
} from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import DeleteIcon from '@material-ui/icons/Delete';
import GetAppIcon from '@material-ui/icons/GetApp';
import ShareIcon from '@material-ui/icons/Share';
import EditIcon from '@material-ui/icons/Edit';
import { removePoster } from '../services/action';
import axios from "axios";
const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(4),
marginBottom: theme.spacing(8),
display: 'flex',
},
posterList: {
flex: 2,
marginRight: theme.spacing(2),
maxHeight: 'calc(100vh - 200px)',
overflowY: 'auto',
},
actionPanel: {
flex: 1,
position: 'sticky',
top: theme.spacing(4),
height: 'fit-content',
},
card: {
display: 'flex',
marginBottom: theme.spacing(2),
backgroundColor: '#2c3e50',
},
cardMedia: {
width: 100,
},
cardContent: {
flex: '1 0 auto',
},
actions: {
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(2),
},
slider: {
width: '100%',
marginTop: theme.spacing(2),
},
button: {
width: '100%',
},
typography: {
color: '#ecf0f1',
},
formControl: {
marginBottom: theme.spacing(2),
},
checkbox: {
color: '#3498db',
},
paper: {
padding: theme.spacing(3),
backgroundColor: '#34495e',
},
}));
const Cart = () => {
const classes = useStyles();
const dispatch = useDispatch();
const selectedPosters = useSelector((state) => {
const selections = state.posterSelections;
return Object.entries(selections).flatMap(([movieId, posters]) =>
posters.map(posterId => ({ movieId, posterId }))
);
});
const [selectedForDownload, setSelectedForDownload] = useState(selectedPosters.map(() => true));
const [downloadFormat, setDownloadFormat] = useState('zip');
const [renameDialogOpen, setRenameDialogOpen] = useState(false);
const [currentPosterIndex, setCurrentPosterIndex] = useState(null);
const [newPosterName, setNewPosterName] = useState('');
const handleRemovePoster = (index) => {
dispatch(removePoster(selectedPosters[index].movieId, selectedPosters[index].posterId));
};
const handleDownload = async () => {
const postersToDownload = selectedPosters
.filter((_, index) => selectedForDownload[index])
.map((poster) => ({
movieId: poster.movieId,
posterId: poster.posterId,
movieName: poster.movieName,
movieYear: poster.movieYear
}));
console.log('Downloading posters:', postersToDownload);
try {
const response = await axios.post('http://localhost:5000/api/download-posters', {
posters: postersToDownload,
format: downloadFormat,
}, {
responseType: 'blob',
});
const blob = new Blob([response.data], { type: response.headers['content-type'] });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = `posters.${downloadFormat}`;
link.click();
} catch (error) {
console.error('Failed to download posters:', error);
}
};
const handleShare = () => {
console.log('Sharing selected posters');
};
const handleRename = (index) => {
setCurrentPosterIndex(index);
setNewPosterName(selectedPosters[index].posterId);
setRenameDialogOpen(true);
};
const handleRenameConfirm = () => {
console.log(`Renaming poster ${currentPosterIndex} to ${newPosterName}`);
setRenameDialogOpen(false);
};
return (
<Container className={classes.root}>
<div className={classes.posterList}>
<Typography variant="h4" gutterBottom className={classes.typography}>Your Cart</Typography>
{selectedPosters.map((poster, index) => (
<Card key={index} className={classes.card}>
<CardMedia
className={classes.cardMedia}
image={`https://image.tmdb.org/t/p/w500${poster.posterId}`}
title={`Poster ${index + 1}`}
/>
<CardContent className={classes.cardContent}>
<Typography variant="h6"
className={classes.typography}>{`Movie ID: ${poster.movieId}`}</Typography>
<Typography variant="body2"
className={classes.typography}>{poster.posterId}</Typography>
<FormControlLabel
control={
<Checkbox
checked={selectedForDownload[index]}
onChange={(e) => {
const newSelected = [...selectedForDownload];
newSelected[index] = e.target.checked;
setSelectedForDownload(newSelected);
}}
className={classes.checkbox}
/>
}
label="Select for download"
className={classes.typography}
/>
<Button startIcon={<DeleteIcon/>} onClick={() => handleRemovePoster(index)}
className={classes.typography}>Remove</Button>
<Button startIcon={<EditIcon/>} onClick={() => handleRename(index)}
className={classes.typography}>Rename</Button>
</CardContent>
</Card>
))}
</div>
<Paper className={classes.actionPanel} elevation={3}>
<div className={classes.actions}>
<Typography gutterBottom>Download Format</Typography>
<TextField
select
value={downloadFormat}
onChange={(e) => setDownloadFormat(e.target.value)}
SelectProps={{
native: true,
}}
className={classes.formControl}
>
<option value="zip">ZIP</option>
<option value="tar">TAR</option>
<option value="7z">7Z</option>
</TextField>
<Button
variant="contained"
color="primary"
startIcon={<GetAppIcon/>}
onClick={handleDownload}
disabled={selectedForDownload.every((selected) => !selected)}
className={classes.button}
>
Download Selected
</Button>
<Button
variant="contained"
color="secondary"
startIcon={<ShareIcon/>}
onClick={handleShare}
className={classes.button}
>
Share Selection
</Button>
</div>
</Paper>
<Dialog open={renameDialogOpen} onClose={() => setRenameDialogOpen(false)}>
<DialogTitle>Rename Poster</DialogTitle>
<DialogContent>
<TextField
autoFocus
margin="dense"
label="New Name"
type="text"
fullWidth
value={newPosterName}
onChange={(e) => setNewPosterName(e.target.value)}
/>
</DialogContent>
<DialogActions>
<Button onClick={() => setRenameDialogOpen(false)} color="primary">
Cancel
</Button>
<Button onClick={handleRenameConfirm} color="primary">
Rename
</Button>
</DialogActions>
</Dialog>
</Container>
);
};
export default Cart;