Skip to content

Commit

Permalink
Refactor: lift state up to Recommendation component
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardsavin committed May 25, 2023
1 parent 9d4854e commit 1ceb6d9
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/components/movie-recommendation.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Image from "next/image";
import useTmdbMovieInfo from "~/utils/hooks/use-tmdb-movie-info";
import type { MovieInfo } from "~/pages/api/tmdb-fetch-movie-info";
import type { Movie } from "./movie-recommendations-button";
import { useEffect, useState } from "react";
import { api } from "~/utils/api";
import type { MovieInfo } from "~/pages/api/tmdb-fetch-movie-info";
import type { Movie } from "./movie-recommendations-button";

// Display the movie recommendations modal with a poster, title, release year, overview and links to TMDB and Letterboxd
export const MovieModal = ({
Expand Down
47 changes: 29 additions & 18 deletions src/components/movie-recommendations-button.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { toast } from "react-hot-toast";
import getMovieRecommendations from "~/utils/get-movie-recommendations";
import { useState } from "react";
import MovieRecommendations from "./movie-recommendation";
import { useEffect, useState } from "react";
import { api } from "~/utils/api";
import type { TrackData } from "~/utils/hooks/use-recent-tracks";

export type MovieData = {
recommendationId: string;
recommendedMovies: Movie[];
uniqueKey: number;
};

export type Movie = {
title: string;
year: string;
Expand All @@ -13,10 +18,15 @@ export type Movie = {
type Props = {
songs: string;
trackData: TrackData;
handleMovieData: (movieData: MovieData) => void;
};

// Start fetching movie recommendations based on the user's Spotify history
const FetchMovieRecommendationsButton = ({ songs, trackData }: Props) => {
const FetchMovieRecommendationsButton = ({
songs,
trackData,
handleMovieData,
}: Props) => {
const [recommendedMovies, setRecommendedMovies] = useState<Movie[]>([]);
const [uniqueKey, setUniqueKey] = useState<number>(Date.now());

Expand All @@ -28,6 +38,16 @@ const FetchMovieRecommendationsButton = ({ songs, trackData }: Props) => {
const { mutate: mutateRecommendation } =
api.recommendation.create.useMutation();

useEffect(() => {
if (recommendedMovies.length > 0 && recommendationId) {
handleMovieData({
recommendationId,
recommendedMovies,
uniqueKey,
});
}
}, [recommendationId, recommendedMovies, uniqueKey, handleMovieData]);

const handleClick = async () => {
try {
let movies = await getMovieRecommendations(songs, temperature);
Expand Down Expand Up @@ -72,21 +92,12 @@ const FetchMovieRecommendationsButton = ({ songs, trackData }: Props) => {
};

return (
<>
<button
className="rounded-md bg-white px-4 py-2 text-black"
onClick={handleClick as () => void}
>
Get movie recommendations
</button>
{recommendedMovies.length > 0 && recommendationId && (
<MovieRecommendations
key={uniqueKey}
movies={recommendedMovies}
recommendationId={recommendationId}
/>
)}
</>
<button
className="rounded-md bg-white px-4 py-2 text-black"
onClick={handleClick as () => void}
>
Get movie recommendations
</button>
);
};

Expand Down
21 changes: 8 additions & 13 deletions src/components/recent-tracks.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import useRecentTracks from "~/utils/hooks/use-recent-tracks";
import FetchMovieRecommendationsButton from "./movie-recommendations-button";
import { api } from "~/utils/api";
import { useEffect } from "react";
import type { TrackData } from "~/utils/hooks/use-recent-tracks";
import TracksCarousel from "./tracks-carousel";
import type { TrackData } from "~/utils/hooks/use-recent-tracks";

// Prepare the data to be sent to the backend
const transformTrackData = (tracks: TrackData) => {
Expand All @@ -19,8 +18,10 @@ const transformTrackData = (tracks: TrackData) => {
// Display the most recent tracks from the user's Spotify history
export const RecentTracks = ({
spotifyAccessToken,
handleTrackData,
}: {
spotifyAccessToken: string;
handleTrackData: (data: TrackData) => void;
}) => {
const trackData = useRecentTracks(spotifyAccessToken);

Expand All @@ -31,6 +32,11 @@ export const RecentTracks = ({
if (trackData) mutate({ songs: transformTrackData(trackData) });
}, [trackData, mutate]);

// Send the data to the parent component
useEffect(() => {
if (trackData) handleTrackData(trackData);
}, [trackData, handleTrackData]);

if (!trackData)
return (
<div>
Expand All @@ -52,20 +58,9 @@ export const RecentTracks = ({
);
}

const songsString = trackData
.map((song, index) => `${index + 1}. ${song.name} by ${song.artist}`)
.join("; ");

return (
<div className="flex h-screen w-screen flex-col items-center justify-center overflow-hidden">
<TracksCarousel tracks={trackData} />

{trackData.length > 0 && (
<FetchMovieRecommendationsButton
songs={songsString}
trackData={trackData}
/>
)}
</div>
);
};
47 changes: 44 additions & 3 deletions src/pages/recommendations/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import { useUser } from "@clerk/nextjs";
import type { NextPage } from "next";
import Head from "next/head";
import { useEffect } from "react";
import { useCallback, useEffect, useState } from "react";
import MainFooter from "~/components/main-footer";
import MainHeader from "~/components/main-header";
import { RecentTracks } from "~/components/recent-tracks";
import SignInSpotifyButton from "~/components/signin-spotify";
import { api } from "~/utils/api";
import useSpotifyAccessToken from "~/utils/hooks/use-spotify-access-token";
import { getRandomFetchTracksMessage } from "~/utils/loading-messages";
import FetchMovieRecommendationsButton from "~/components/movie-recommendations-button";
import MovieRecommendations from "~/components/movie-recommendation";
import type { TrackData } from "~/utils/hooks/use-recent-tracks";
import type { MovieData } from "~/components/movie-recommendations-button";
import type { NextPage } from "next";

const Recommendations: NextPage = () => {
// Get track data from RecentTracks component
const [trackData, setTrackData] = useState<TrackData>([]);
const handleTrackData = (data: TrackData) => setTrackData(data);

const [movieData, setMovieData] = useState<MovieData | null>(null);
const handleMovieData = useCallback((data: MovieData) => {
setMovieData(data);
}, []);

const user = useUser();
const spotifyAccessToken = useSpotifyAccessToken(user);
const { mutate: cacheUserRole } = api.user.setRoleInRedis.useMutation();
Expand All @@ -21,6 +34,10 @@ const Recommendations: NextPage = () => {
}
}, [user.isSignedIn, cacheUserRole]);

const songsString = trackData
.map((song, index) => `${index + 1}. ${song.name} by ${song.artist}`)
.join("; ");

return (
<>
<Head>
Expand All @@ -44,8 +61,32 @@ const Recommendations: NextPage = () => {
{getRandomFetchTracksMessage()}
</p>
)}

{spotifyAccessToken && (
<RecentTracks spotifyAccessToken={spotifyAccessToken} />
<>
<RecentTracks
spotifyAccessToken={spotifyAccessToken}
handleTrackData={handleTrackData}
/>

{trackData.length > 0 && (
<>
<FetchMovieRecommendationsButton
songs={songsString}
trackData={trackData}
handleMovieData={handleMovieData}
/>

{movieData && (
<MovieRecommendations
key={movieData.uniqueKey}
movies={movieData.recommendedMovies}
recommendationId={movieData.recommendationId}
/>
)}
</>
)}
</>
)}
</div>
</section>
Expand Down

0 comments on commit 1ceb6d9

Please sign in to comment.