diff --git a/src/components/EpisodeHeader.tsx b/src/components/EpisodeHeader.tsx index 7ac93ea068070a7b3f204f87d4d1d299e4833320..84c58672ef21d6c66229df6a72da8b3c42443bca 100644 --- a/src/components/EpisodeHeader.tsx +++ b/src/components/EpisodeHeader.tsx @@ -9,6 +9,7 @@ export type headerProps = { description: string; url_thumbnail: string; id_episode: number; + premium: boolean; }; export default function EpisodeHeader({ @@ -16,8 +17,11 @@ export default function EpisodeHeader({ description, url_thumbnail, id_episode, + premium, }: headerProps): JSX.Element { - const urlPrefix = "http://localhost:3000/images/"; + const urlPrefix = premium + ? "http://localhost:3000/images/" + : "http://localhost:8080/app/storage"; const queue = useQueue(); const dispatchQueue = useQueueDispatch(); @@ -108,39 +112,41 @@ export default function EpisodeHeader({ </div> </div> - <div className="block mt-[20px]"> - <button - onClick={handlePlay} - data-te-toggle="tooltip" - title="play episode" - className=" w-[225px] h-[50px] bg-NAVY-5 text-white rounded-[32px] h4 leading-4" - > - Play Episode - <img - className="inline ml-[45px]" - width={16} - height={16} - src={PlayIcon} - alt="" - /> - </button> - - <button - onClick={handleAddToQueue} - data-te-toggle="tooltip" - title="add episode to queue" - className=" w-[225px] h-[50px] bg-NAVY-5 text-white rounded-[32px] h4 leading-4 ml-[30px]" - > - Add To Queue - <img - className="inline ml-[45px]" - width={16} - height={16} - src={PlusIcon} - alt="" - /> - </button> - </div> + {premium ? ( + <div className="block mt-[20px]"> + <button + onClick={handlePlay} + data-te-toggle="tooltip" + title="play episode" + className=" w-[225px] h-[50px] bg-NAVY-5 text-white rounded-[32px] h4 leading-4" + > + Play Episode + <img + className="inline ml-[45px]" + width={16} + height={16} + src={PlayIcon} + alt="" + /> + </button> + + <button + onClick={handleAddToQueue} + data-te-toggle="tooltip" + title="add episode to queue" + className=" w-[225px] h-[50px] bg-NAVY-5 text-white rounded-[32px] h4 leading-4 ml-[30px]" + > + Add To Queue + <img + className="inline ml-[45px]" + width={16} + height={16} + src={PlusIcon} + alt="" + /> + </button> + </div> + ) : null} </div> ); } diff --git a/src/components/EpisodeList.tsx b/src/components/EpisodeList.tsx index 500091a71b9611c0b299064b2be558dfe01baac8..d54493a5c1d43874f687bacc8fb10d2dc96360e6 100644 --- a/src/components/EpisodeList.tsx +++ b/src/components/EpisodeList.tsx @@ -11,6 +11,7 @@ export type episodeProps = { title: string; description: string; url_thumbnail: string; + premium: boolean; }; export default function EpisodeList({ @@ -19,15 +20,18 @@ export default function EpisodeList({ description, url_thumbnail, id_episode, + premium, }: episodeProps): JSX.Element { - const urlPrefix = "http://localhost:3000/images/"; + const urlPrefix = premium + ? "http://localhost:3000/images/" + : "http://localhost:8080/app/storage"; const dispatchQueue = useQueueDispatch(); const queue = useQueue(); const navigate = useNavigate(); const handleNavigate = () => { - navigate(`/episode/${id_episode}`); + navigate(`/episode/${id_episode}?premium=${premium}`); }; const handlePlay = async (e: React.MouseEvent<HTMLElement>) => { @@ -115,34 +119,38 @@ export default function EpisodeList({ {description} </p> </div> - <button - onClick={handlePlay} - data-te-toggle="tooltip" - title="play episode" - className="invisible hover:scale-110 group-hover/item:visible flex items-center justify-center rounded-full bg-black w-[48px] h-[48px] ml-[70px] hover:bg-gray-600" - > - <img - className="ml-[5px]" - width={18} - height={18} - src={PlayIcon} - alt="play episode" - /> - </button> - <button - onClick={handleAddToQueue} - data-te-toggle="tooltip" - title="add to queue" - className="invisible hover:scale-110 group-hover/item:visible flex items-center justify-center rounded-full bg-black w-[48px] h-[48px] ml-[30px] hover:bg-gray-600" - > - <img - className="" - width={18} - height={18} - src={PlusIcon} - alt="play episode" - /> - </button> + {premium ? ( + <> + <button + onClick={handlePlay} + data-te-toggle="tooltip" + title="play episode" + className="invisible hover:scale-110 group-hover/item:visible flex items-center justify-center rounded-full bg-black w-[48px] h-[48px] ml-[70px] hover:bg-gray-600" + > + <img + className="ml-[5px]" + width={18} + height={18} + src={PlayIcon} + alt="play episode" + /> + </button> + <button + onClick={handleAddToQueue} + data-te-toggle="tooltip" + title="add to queue" + className="invisible hover:scale-110 group-hover/item:visible flex items-center justify-center rounded-full bg-black w-[48px] h-[48px] ml-[30px] hover:bg-gray-600" + > + <img + className="" + width={18} + height={18} + src={PlusIcon} + alt="play episode" + /> + </button> + </> + ) : null} </div> ); } diff --git a/src/components/PodcastCard.tsx b/src/components/PodcastCard.tsx index c95a0380323d96d32fb717d76215953782698ad4..52f763d96604b6ed8e3521886fc7915f527acd96 100644 --- a/src/components/PodcastCard.tsx +++ b/src/components/PodcastCard.tsx @@ -10,6 +10,7 @@ export type cardProps = { title: string; description: string; imageurl: string; + premium: boolean; }; export default function PodcastCard({ @@ -17,14 +18,19 @@ export default function PodcastCard({ title, description, imageurl, + premium, }: cardProps): JSX.Element { + const urlPrefix = premium + ? "http://localhost:3000/images/" + : "http://localhost:8080/app/storage"; + const dispatchQueue = useQueueDispatch(); const queue = useQueue(); const navigate = useNavigate(); const handleNavigate = () => { - navigate(`/podcast/${idpodcast}`); + navigate(`/podcast/${idpodcast}?premium=${premium}`); }; const handleAddToQueue = async (e: React.MouseEvent<HTMLElement>) => { @@ -70,11 +76,7 @@ export default function PodcastCard({ > <img className="w-[160px] h-[140px] object-cover object-center xl:w-[200px] xl:h-[175px]" - src={ - imageurl - ? `${import.meta.env.VITE_REST_URL}/images/${imageurl}` - : Placeholder - } + src={urlPrefix + imageurl || Placeholder} width={200} height={175} alt="podcast-thumbnail" diff --git a/src/components/PodcastHeader.tsx b/src/components/PodcastHeader.tsx index bd571a3c8a1b51f91b9a6bb2272325493ccaa118..4ff290a5347a0f0249e557703fd80d692f1b5bf8 100644 --- a/src/components/PodcastHeader.tsx +++ b/src/components/PodcastHeader.tsx @@ -11,6 +11,7 @@ export type headerProps = { description: string; url_thumbnail: string; id_podcast: number; + premium: boolean; }; export default function PodcastHeader({ @@ -20,8 +21,11 @@ export default function PodcastHeader({ description, url_thumbnail, id_podcast, + premium, }: headerProps): JSX.Element { - const urlPrefix = "http://localhost:3000/images/"; + const urlPrefix = premium + ? "http://localhost:3000/images/" + : "http://localhost:8080/app/storage"; const queue = useQueue(); const dispatchQueue = useQueueDispatch(); @@ -98,37 +102,39 @@ export default function PodcastHeader({ </div> </div> - <div className="block mt-[20px]"> - <button - data-te-toggle="tooltip" - title="add episode to library" - className=" w-[225px] h-[50px] bg-NAVY-5 text-white rounded-[32px] h4 leading-4" - > - Add To Library - <img - className="inline ml-[45px]" - width={16} - height={16} - src={PlusIcon} - alt="plus icon" - /> - </button> - - <button - onClick={handleAddToQueue} - data-te-toggle="tooltip" - title="play episode" - className=" w-[48px] h-[48px] bg-black text-white rounded-[32px] h4 leading-4 ml-[30px] hover:bg-gray-600" - > - <img - className="inline ml-[5px]" - width={18} - height={18} - src={PlayIcon} - alt="play podcast" - /> - </button> - </div> + {premium ? ( + <div className="block mt-[20px]"> + <button + data-te-toggle="tooltip" + title="add episode to library" + className=" w-[225px] h-[50px] bg-NAVY-5 text-white rounded-[32px] h4 leading-4" + > + Add To Library + <img + className="inline ml-[45px]" + width={16} + height={16} + src={PlusIcon} + alt="plus icon" + /> + </button> + + <button + onClick={handleAddToQueue} + data-te-toggle="tooltip" + title="play episode" + className=" w-[48px] h-[48px] bg-black text-white rounded-[32px] h4 leading-4 ml-[30px] hover:bg-gray-600" + > + <img + className="inline ml-[5px]" + width={18} + height={18} + src={PlayIcon} + alt="play podcast" + /> + </button> + </div> + ) : null} </div> ); } diff --git a/src/components/layouts/Player.tsx b/src/components/layouts/Player.tsx index 6032b13ce4cbc931fa478a43214d9ebbf31029ab..afb0110652ad73afe417ca2f5d917b3bf548686a 100644 --- a/src/components/layouts/Player.tsx +++ b/src/components/layouts/Player.tsx @@ -153,7 +153,7 @@ export default function Player() { } ); - if (res.data.messsage === "success") { + if (res.data.message === "success") { const prev = await axios.get( `${import.meta.env.VITE_REST_URL}/queue/previous`, { diff --git a/src/components/layouts/SidebarLayout.tsx b/src/components/layouts/SidebarLayout.tsx index 85bd6ebbb7c00e54fccc9d580252ddb78376a517..2c1df9d258532815f1828a99d255c5c423cca0b5 100644 --- a/src/components/layouts/SidebarLayout.tsx +++ b/src/components/layouts/SidebarLayout.tsx @@ -45,7 +45,7 @@ export default function SidebarLayout(): JSX.Element { } return ( - <div className="w-full h-screen hidden md:flex"> + <div className="w-full h-screen overflow-hidden hidden md:flex"> <aside className="w-[30vw] h-screen bg-WHITE flex flex-col justify-between items-center shadow-[2px_0_20px_0_rgba(0,0,0,0.25)] lg:w-[25vw]"> <div className="w-full"> <Navigation /> diff --git a/src/pages/episode/index.tsx b/src/pages/episode/index.tsx index b8e2799e66ea996629db285caa090465a4d747aa..be31dd781d8d7c34ca72da06037d4d8720910dce 100644 --- a/src/pages/episode/index.tsx +++ b/src/pages/episode/index.tsx @@ -1,17 +1,25 @@ import EpisodeHeader, { headerProps } from "../../components/EpisodeHeader"; import { useEffect, useState } from "react"; import axios from "axios"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams, useSearchParams } from "react-router-dom"; export default function PodcastPage(): JSX.Element { const { episodeId } = useParams(); + const [searchParams] = useSearchParams(); + const navigate = useNavigate(); const [episodeHeader, setEpisodeHeader] = useState<headerProps>(); useEffect(() => { (async () => { + if (searchParams.get("premium") === null) { + navigate(`/episode/${episodeId}?premium=true`); + } + const resEpisodeHeader = await axios.get( - `http://localhost:3000/episode/${episodeId}`, + `http://localhost:3000/episode/${episodeId}?premium=${searchParams.get( + "premium" + )}`, { headers: { Authorization: `Bearer ${localStorage.getItem("token")}`, @@ -20,12 +28,12 @@ export default function PodcastPage(): JSX.Element { ); setEpisodeHeader(resEpisodeHeader.data.episode); })(); - }, [episodeId]); + }, [episodeId, searchParams, navigate]); return ( <div className="ml-[100px]"> {episodeHeader ? ( - <EpisodeHeader {...episodeHeader} /> + <EpisodeHeader {...episodeHeader} premium={searchParams.get("premium") == "true"} /> ) : ( <h1 className="h1"></h1> )} diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 491f3b2ef1bc7a7f036865b5cd7c0dff66bbbd89..f9ef30de447eceb05e967b8b66c2a0c567988a36 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -55,9 +55,18 @@ export default function HomePage(): JSX.Element { ), ]); - setTechPodcasts(resTech.data.podcasts); - setComedyPodcasts(resComedy.data.podcasts); - setHorrorPodcasts(resHorror.data.podcasts); + setTechPodcasts([ + ...resTech.data.premiumPodcasts, + ...resTech.data.regularPodcasts, + ]); + setComedyPodcasts([ + ...resComedy.data.premiumPodcasts, + ...resComedy.data.regularPodcasts, + ]); + setHorrorPodcasts([ + ...resHorror.data.premiumPodcasts, + ...resHorror.data.regularPodcasts, + ]); })(); }, []); diff --git a/src/pages/podcast/index.tsx b/src/pages/podcast/index.tsx index be02d379eb85fb139f3ff92a4cc9491133ff1d41..a140d5e2ce2477be5ec5231b569c9317a4634281 100644 --- a/src/pages/podcast/index.tsx +++ b/src/pages/podcast/index.tsx @@ -2,40 +2,47 @@ import { useEffect, useState } from "react"; import Episode, { episodeProps } from "../../components/EpisodeList"; import PodcastHeader, { headerProps } from "../../components/PodcastHeader"; import axios from "axios"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams, useSearchParams } from "react-router-dom"; export default function PodcastPage(): JSX.Element { const { podcastId } = useParams(); + const [searchParams] = useSearchParams(); + const navigate = useNavigate(); + // component states const [episodes, setEpisodes] = useState<episodeProps[]>([]); const [podcastHeader, setPodcastHeader] = useState<headerProps>(); useEffect(() => { (async () => { + if (searchParams.get("premium") === null) { + navigate(`/podcast/${podcastId}?premium=true`); + } + const axiosInstance = axios.create({ headers: { Authorization: `Bearer ${localStorage.getItem("token")}`, }, }); - const [resPodcastHeader, resEpisodes] = await Promise.all([ - axiosInstance.get( - `${import.meta.env.VITE_REST_URL}/podcast/${podcastId}` - ), - axiosInstance.get( - `${import.meta.env.VITE_REST_URL}/podcast/episode/${podcastId}` - ), - ]); - - setPodcastHeader(resPodcastHeader.data.podcast); - setEpisodes(resEpisodes.data.episodes); + const resPodcast = await axiosInstance.get( + `${ + import.meta.env.VITE_REST_URL + }/podcast/${podcastId}?premium=${searchParams.get("premium")}` + ); + + setPodcastHeader(resPodcast.data.podcast); + setEpisodes(resPodcast.data.podcast.PremiumEpisodes); })(); - }, [podcastId]); + }, [podcastId, searchParams, navigate]); return ( <div className="ml-[100px]"> {podcastHeader ? ( - <PodcastHeader {...podcastHeader} /> + <PodcastHeader + {...podcastHeader} + premium={searchParams.get("premium") == "true"} + /> ) : ( <h1 className="h1"></h1> )} @@ -52,6 +59,7 @@ export default function PodcastPage(): JSX.Element { description={episode.description} url_thumbnail={episode.url_thumbnail} order={idx + 1} + premium={searchParams.get("premium") == "true"} /> ))} </section> diff --git a/src/pages/queue/index.tsx b/src/pages/queue/index.tsx index f8806a1465bf8bd2367507ae2800b9aacf2cfa46..6bfa7342589b9c4497213f963621be9c06269e33 100644 --- a/src/pages/queue/index.tsx +++ b/src/pages/queue/index.tsx @@ -55,7 +55,9 @@ export default function QueuePage() { </p> <img className="object-cover object-center ml-4 rounded-lg w-[50px] h-[50px]" - src={item.Episode.url_thumbnail} + src={`${import.meta.env.VITE_REST_URL}/images/${ + item.Episode.url_thumbnail + }`} width={50} height={50} alt="episode thumbnail"