import React, { useState } from "react"; import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { Container, Typography, Box, Button, IconButton, LinearProgress, } from "@material-ui/core"; import GetAppIcon from "@material-ui/icons/GetApp"; import ArrowBackIcon from "@material-ui/icons/ArrowBack"; import CheckIcon from "@material-ui/icons/Check"; import JSZip from "jszip"; const MONTH_NAMES = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ]; const SelectionRecap = () => { const navigate = useNavigate(); const posterSelections = useSelector((state) => state.posterSelections); const [downloadState, setDownloadState] = useState(null); const entries = Object.entries(posterSelections) .flatMap(([movieId, posters]) => { if (!posters?.length) return []; const match = movieId.match(/^(.+)-(\d{4})$/); if (!match) return []; return posters.map((p) => ({ movieId, movieName: match[1], movieYear: match[2], posterId: p.posterId, watchedDate: p.watchedDate || "", })); }) .sort((a, b) => a.watchedDate.localeCompare(b.watchedDate)); const groups = entries.reduce((acc, entry) => { const key = entry.watchedDate.slice(0, 7); if (!acc[key]) acc[key] = []; acc[key].push(entry); return acc; }, {}); const sortedMonths = Object.keys(groups).sort().reverse(); const handleDownload = async () => { if (downloadState) return; setDownloadState({ current: 0, total: entries.length }); try { const zip = new JSZip(); for (let i = 0; i < entries.length; i++) { const { movieId, posterId, watchedDate } = entries[i]; const res = await fetch(`https://image.tmdb.org/t/p/original${posterId}`); const blob = await res.blob(); zip.file(`${watchedDate}_${movieId}.jpg`, blob); setDownloadState({ current: i + 1, total: entries.length }); } const content = await zip.generateAsync({ type: "blob" }); const url = URL.createObjectURL(content); const link = document.createElement("a"); link.href = url; link.download = "posters.zip"; document.body.appendChild(link); link.click(); link.remove(); URL.revokeObjectURL(url); } catch (err) { console.error("Download error:", err); } finally { setDownloadState(null); } }; if (entries.length === 0) { return ( No posters selected yet. navigate("/PosterSelector")} > Go to calendar ); } const isDownloading = !!downloadState; const progress = isDownloading ? Math.round((downloadState.current / downloadState.total) * 100) : 0; return ( navigate(-1)}> Selected Posters ({entries.length}) } onClick={handleDownload} disabled={isDownloading} > {isDownloading ? ( {downloadState.current} / {downloadState.total} ) : ( "Download all" )} {sortedMonths.map((monthKey) => { const [year, month] = monthKey.split("-").map(Number); const monthLabel = `${MONTH_NAMES[month - 1]} ${year}`; return ( {monthLabel} {groups[monthKey].map((entry) => ( navigate( `/posters/${encodeURIComponent(entry.movieName)}/${encodeURIComponent(entry.movieYear)}`, { state: { watchedDate: entry.watchedDate } } ) } > {entry.movieName} {entry.movieYear} ))} ); })} ); }; export default SelectionRecap;