Card updates
This commit is contained in:
1
package-lock.json
generated
1
package-lock.json
generated
@@ -14805,6 +14805,7 @@
|
|||||||
"version": "0.453.0",
|
"version": "0.453.0",
|
||||||
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.453.0.tgz",
|
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.453.0.tgz",
|
||||||
"integrity": "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ==",
|
"integrity": "sha512-kL+RGZCcJi9BvJtzg2kshO192Ddy9hv3ij+cPrVPWSRzgCWCVazoQJxOjAwgK53NomL07HB7GPHW120FimjNhQ==",
|
||||||
|
"license": "ISC",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
|
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from "react";
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
import { removePoster } from '../services/action';
|
import { removePoster } from "../services/action";
|
||||||
import DeleteIcon from '@material-ui/icons/Delete';
|
import DeleteIcon from "@material-ui/icons/Delete";
|
||||||
|
import { Camera } from "lucide-react";
|
||||||
|
|
||||||
const apiUrl = process.env.REACT_APP_API_URL;
|
const apiUrl = process.env.REACT_APP_API_URL;
|
||||||
|
|
||||||
@@ -10,11 +11,11 @@ const Cart = () => {
|
|||||||
const selectedPosters = useSelector((state) => {
|
const selectedPosters = useSelector((state) => {
|
||||||
const selections = state.posterSelections;
|
const selections = state.posterSelections;
|
||||||
return Object.entries(selections).flatMap(([movieId, posters]) =>
|
return Object.entries(selections).flatMap(([movieId, posters]) =>
|
||||||
posters.map((posterId) => ({ movieId, posterId }))
|
posters.map((posterId) => ({ movieId, posterId }))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const [downloadFormat, setDownloadFormat] = useState('zip');
|
const [downloadFormat, setDownloadFormat] = useState("zip");
|
||||||
|
|
||||||
const handleRemovePoster = (movieId, posterId) => {
|
const handleRemovePoster = (movieId, posterId) => {
|
||||||
dispatch(removePoster(movieId, posterId));
|
dispatch(removePoster(movieId, posterId));
|
||||||
@@ -23,9 +24,9 @@ const Cart = () => {
|
|||||||
const handleDownload = async () => {
|
const handleDownload = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${apiUrl}/api/download-posters`, {
|
const response = await fetch(`${apiUrl}/api/download-posters`, {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
posters: selectedPosters,
|
posters: selectedPosters,
|
||||||
@@ -33,69 +34,93 @@ const Cart = () => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) throw new Error('Download failed');
|
if (!response.ok) throw new Error("Download failed");
|
||||||
|
|
||||||
const contentType = response.headers.get('content-type');
|
const contentType = response.headers.get("content-type");
|
||||||
if (contentType && contentType.includes('application/zip')) {
|
if (contentType && contentType.includes("application/zip")) {
|
||||||
const blob = await response.blob();
|
const blob = await response.blob();
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement("a");
|
||||||
link.href = url;
|
link.href = url;
|
||||||
link.download = 'posters.zip';
|
link.download = "posters.zip";
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
link.remove();
|
link.remove();
|
||||||
window.URL.revokeObjectURL(url);
|
window.URL.revokeObjectURL(url);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Invalid response format');
|
throw new Error("Invalid response format");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to download posters:', error);
|
console.error("Failed to download posters:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const totalSlots = 4;
|
||||||
|
const posterSlots = [...Array(totalSlots)].map((_, index) => {
|
||||||
|
if (index < selectedPosters.length) {
|
||||||
|
return selectedPosters[index];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="cart-container">
|
<div className="cart-container">
|
||||||
<div className="poster-grid">
|
<div className="poster-grid">
|
||||||
{selectedPosters.map((poster) => (
|
{posterSlots.map((poster, index) => (
|
||||||
<div key={`${poster.movieId}-${poster.posterId}`} className="poster-card">
|
<div
|
||||||
|
key={
|
||||||
|
poster ? `${poster.movieId}-${poster.posterId}` : `empty-${index}`
|
||||||
|
}
|
||||||
|
className="poster-card"
|
||||||
|
>
|
||||||
|
{poster ? (
|
||||||
|
<>
|
||||||
<img
|
<img
|
||||||
src={`https://image.tmdb.org/t/p/w500${poster.posterId}`}
|
src={`https://image.tmdb.org/t/p/w500${poster.posterId}`}
|
||||||
alt="Movie poster"
|
alt="Movie poster"
|
||||||
className="poster-image"
|
className="poster-image"
|
||||||
/>
|
/>
|
||||||
<div className="delete-overlay">
|
<div className="delete-overlay">
|
||||||
<button
|
<button
|
||||||
className="delete-button"
|
className="delete-button"
|
||||||
onClick={() => handleRemovePoster(poster.movieId, poster.posterId)}
|
onClick={() =>
|
||||||
|
handleRemovePoster(poster.movieId, poster.posterId)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<DeleteIcon />
|
<DeleteIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="empty-poster">
|
||||||
|
<Camera size={48} />
|
||||||
|
<p>Emplacement disponible</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
))}
|
||||||
<div className="action-panel">
|
|
||||||
<h2>Download Options</h2>
|
|
||||||
<select
|
|
||||||
value={downloadFormat}
|
|
||||||
onChange={(e) => setDownloadFormat(e.target.value)}
|
|
||||||
className="format-select"
|
|
||||||
>
|
|
||||||
<option value="zip">ZIP</option>
|
|
||||||
<option value="tar">TAR</option>
|
|
||||||
<option value="7z">7Z</option>
|
|
||||||
</select>
|
|
||||||
<button
|
|
||||||
className="download-button"
|
|
||||||
onClick={handleDownload}
|
|
||||||
disabled={selectedPosters.length === 0}
|
|
||||||
>
|
|
||||||
Download Selected
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="action-panel">
|
||||||
|
<h2>Download Options</h2>
|
||||||
|
<select
|
||||||
|
value={downloadFormat}
|
||||||
|
onChange={(e) => setDownloadFormat(e.target.value)}
|
||||||
|
className="format-select"
|
||||||
|
>
|
||||||
|
<option value="zip">ZIP</option>
|
||||||
|
<option value="tar">TAR</option>
|
||||||
|
<option value="7z">7Z</option>
|
||||||
|
</select>
|
||||||
|
<button
|
||||||
|
className="download-button"
|
||||||
|
onClick={handleDownload}
|
||||||
|
disabled={selectedPosters.length === 0}
|
||||||
|
>
|
||||||
|
Download Selected
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,30 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-poster {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #f5f6fa10;
|
||||||
|
border: 2px #95a5a6;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #7f8c8d;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: #95a5a6;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-panel {
|
.action-panel {
|
||||||
|
|||||||
Reference in New Issue
Block a user