diff --git a/src/components/PosterSelector.js b/src/components/PosterSelector.js index a954dbe..b16c4da 100644 --- a/src/components/PosterSelector.js +++ b/src/components/PosterSelector.js @@ -16,6 +16,7 @@ import { import Pagination from "@mui/material/Pagination"; import { createTheme, ThemeProvider } from "@mui/material/styles"; import queryString from "query-string"; +import pulpGif from "../static/images/pulp.gif"; const useStyles = makeStyles((theme) => ({ root: { @@ -25,11 +26,15 @@ const useStyles = makeStyles((theme) => ({ padding: theme.spacing(3), borderRadius: theme.shape.borderRadius, backgroundColor: "#1c1f23", + color: "white", }, title: { - color: "white", marginBottom: theme.spacing(3), }, + username: { + color: "#00A346", + marginBottom: theme.spacing(2), + }, list: { maxHeight: "800px", minHeight: "1000px", @@ -94,6 +99,44 @@ const useStyles = makeStyles((theme) => ({ marginTop: theme.spacing(2), color: "white", }, + noMoviesContainer: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + height: "400px", + }, + gifContainer: { + display: "flex", + justifyContent: "center", + position: "relative", + width: "200px", + height: "200px", + marginBottom: theme.spacing(2), + }, + circleBackground: { + position: "absolute", + width: "120%", + height: "120%", + borderRadius: "50%", + backgroundColor: "#ffffff", + clipPath: "inset(0 0 25% 0)", + bottom: "-28%", + }, + gif: { + position: "absolute", + width: "100%", + height: "100%", + objectFit: "contain", + }, + backButton: { + marginTop: theme.spacing(2), + backgroundColor: "#00A346", + color: "white", + "&:hover": { + backgroundColor: "#008036", + }, + }, })); const paginationTheme = createTheme({ @@ -134,6 +177,7 @@ const PosterSelector = () => { const [page, setPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [progress, setProgress] = useState(0); + const [username, setUsername] = useState(""); const navigate = useNavigate(); const location = useLocation(); const moviesPerPage = 10; @@ -143,8 +187,18 @@ const PosterSelector = () => { const pageNumber = parsed.page ? parseInt(parsed.page, 10) : 1; setPage(pageNumber); fetchMovies(pageNumber); + fetchUsername(); }, [location.search]); + const fetchUsername = async () => { + try { + const response = await axios.get("http://localhost:5000/api/username"); + setUsername(response.data.username); + } catch (error) { + console.error("Error fetching username:", error); + } + }; + const fetchMovies = async (pageNumber) => { try { setLoading(true); @@ -195,6 +249,10 @@ const PosterSelector = () => { navigate(`?page=${value}`); }; + const handleGoBack = () => { + navigate("/"); + }; + const formatWatchedDate = (dateString) => { const date = new Date(dateString); const day = date.getDate().toString().padStart(2, "0"); @@ -210,6 +268,11 @@ const PosterSelector = () => { Your diary + {username && ( + + Letterboxd User: {username} + + )} {loading ? ( @@ -218,93 +281,111 @@ const PosterSelector = () => { ) : movies.length > 0 ? ( - - {movies.map((movie, index) => ( - handleMovieClick(movie.Name, movie.Year)} - className={classes.listItem} - > - - - {movie.Name} + <> + + {movies.map((movie, index) => ( + handleMovieClick(movie.Name, movie.Year)} + className={classes.listItem} + > + + + {movie.Name} + + + + {movie.Name} + + + {movie.Year} + + + + + {(() => { + const { day, month } = formatWatchedDate( + movie["Watched Date"] + ); + return ( + <> + + {day} + + + {month} + + + ); + })()} + + - - - {movie.Name} - - - {movie.Year} - - - - - {(() => { - const { day, month } = formatWatchedDate( - movie["Watched Date"] - ); - return ( - <> - - {day} - - - {month} - - - ); - })()} - - - - - ))} - + + ))} + + + + + + + + ) : ( - - - No movies to display. Upload a CSV file to get started. + +
+
+ Confused reaction +
+ + No movies found in your diary. Please check your Letterboxd + username or CSV file. +
)} - - - - - - ); diff --git a/src/components/UploadDiary.js b/src/components/UploadDiary.js index ea3a51e..e1912fc 100644 --- a/src/components/UploadDiary.js +++ b/src/components/UploadDiary.js @@ -6,6 +6,7 @@ import { Typography, Button, CircularProgress, + TextField, makeStyles, } from "@material-ui/core"; import { CloudUploadOutlined } from "@material-ui/icons"; @@ -81,12 +82,31 @@ const useStyles = makeStyles((theme) => ({ marginTop: theme.spacing(4), padding: theme.spacing(3), }, + usernameField: { + marginBottom: theme.spacing(3), + "& .MuiOutlinedInput-root": { + color: "#ffffff", + "& fieldset": { + borderColor: "#00A346", + }, + "&:hover fieldset": { + borderColor: "#00A346", + }, + "&.Mui-focused fieldset": { + borderColor: "#1caff2", + }, + }, + "& .MuiInputLabel-root": { + color: "#ffffff", + }, + }, })); const UploadDiary = () => { const classes = useStyles(); const [file, setFile] = useState(null); const [uploading, setUploading] = useState(false); + const [username, setUsername] = useState(""); const navigate = useNavigate(); useEffect(() => { @@ -112,21 +132,29 @@ const UploadDiary = () => { }); const handleUpload = async () => { - if (file) { + if (username || file) { setUploading(true); try { - const formData = new FormData(); - formData.append("file", file); + if (username) { + // Here you would implement the logic to fetch the diary from Letterboxd + // For now, we'll just simulate a successful fetch + console.log(`Fetching diary for user: ${username}`); + await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate API call + navigate("/PosterSelector"); + } else if (file) { + const formData = new FormData(); + formData.append("file", file); - await axios.post("http://localhost:5000/api/upload-csv", formData, { - headers: { - "Content-Type": "multipart/form-data", - }, - }); + await axios.post("http://localhost:5000/api/upload-csv", formData, { + headers: { + "Content-Type": "multipart/form-data", + }, + }); - navigate("/PosterSelector"); + navigate("/PosterSelector"); + } } catch (error) { - console.error("Error uploading file:", error); + console.error("Error processing diary:", error); } finally { setUploading(false); } @@ -137,7 +165,22 @@ const UploadDiary = () => {
- Upload CSV File + Upload Letterboxd Diary + + setUsername(e.target.value)} + placeholder="Enter your Letterboxd username" + /> + + Or upload a CSV file:
@@ -163,41 +206,37 @@ const UploadDiary = () => { )}
- {file && ( - - {uploading ? ( - - ) : ( - - )} - - )} + + {uploading ? ( + + ) : ( + + )} +
- This tool allows you to easily upload your diary.csv file from - Letterboxd and select your favorite movie poster. Follow these simple - steps: + This tool allows you to easily import your Letterboxd diary and select + your favorite movie poster. Follow these simple steps:
- 1. Upload Your CSV File: Drag and drop your diary.csv - file or click to select it from your device. + 1. Enter Your Letterboxd Username: Type your Letterboxd + username to automatically fetch your diary.
- 2. Automatic Processing: Once uploaded, the application - will automatically process the file. + 2. Or Upload Your CSV File: If you prefer, you can + still upload your diary.csv file directly.
- 3. Poster Selection: After the file is successfully - uploaded, you'll be redirected to the Poster Selector page, where you - can browse and choose your favorite movie poster based on your - Letterboxd diary. + 3. Automatic Processing: Once submitted, the + application will process your diary. +
+ 4. Poster Selection: After processing, you'll be + redirected to the Poster Selector page, where you can browse and choose + your favorite movie poster based on your Letterboxd diary.
); diff --git a/src/static/images/pulp.gif b/src/static/images/pulp.gif new file mode 100644 index 0000000..18f4ce0 Binary files /dev/null and b/src/static/images/pulp.gif differ