Skip to content

Commit

Permalink
Merge pull request #15 from nnivxix/fix/loading-image
Browse files Browse the repository at this point in the history
Fix/loading image
  • Loading branch information
nnivxix authored Mar 25, 2024
2 parents 67dee13 + 851d67d commit c376303
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 14 deletions.
6 changes: 4 additions & 2 deletions src/components/CardItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Link } from "react-router-dom";
import { MovieTv } from "@/types/response";
import { Button } from "./ui/button";
import imageUrl from "@/utils/image-url";
import Image from "./Image";

interface CardItemProps {
movie: MovieTv;
Expand Down Expand Up @@ -33,9 +34,10 @@ export default function CardItem({ movie, media }: CardItemProps) {
</div>
<div className="relative">
<Link to={`/show/${mediaType}/${movie.id}`}>
<img
<Image
src={imageUrl({ path: movie.poster_path, type: "poster" })}
alt={movieTitle}
alt={movieTitle!}
type="poster"
/>
</Link>
<div className="absolute bottom-1 left-3 ">
Expand Down
28 changes: 28 additions & 0 deletions src/components/Image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { ImgHTMLAttributes, SyntheticEvent } from "react";
import type { TypeImage } from "@/hooks/useImageFallback";
import useImageFallback from "@/hooks/useImageFallback";

interface ImageProps extends ImgHTMLAttributes<HTMLImageElement> {
src: string;
alt: string;
type: TypeImage;
}
export default function Image({ src, alt, type, ...props }: ImageProps) {
const { fallback } = useImageFallback(type);
const imageFallback = (event: SyntheticEvent<HTMLImageElement, Event>) => {
event.currentTarget.src = fallback;
};
const imageLoaded = (event: SyntheticEvent<HTMLImageElement, Event>) => {
event.currentTarget.src = src;
};

return (
<img
{...props}
src={fallback}
alt={alt}
onError={imageFallback}
onLoad={imageLoaded}
/>
);
}
6 changes: 4 additions & 2 deletions src/components/SeasonCardItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Season } from "@/types/tv";
import getYear from "@/utils/get-year";
import imageUrl from "@/utils/image-url";
import { Star } from "lucide-react";
import Image from "./Image";

interface SeasonCardItemProps {
season: Season;
Expand All @@ -12,9 +13,10 @@ export default function SeasonCardItem({ season }: SeasonCardItemProps) {
<div className="z-30 p-2 text-white absolute hidden group-hover:grid grid-cols-1 bg-black/50 backdrop-blur-sm w-full h-full">
<p>{season.overview ?? ""}</p>
</div>
<img
src={imageUrl({ path: season.poster_path })}
<Image
src={imageUrl({ path: season.poster_path, type: "poster" })}
alt={season.overview ?? ""}
type="poster"
/>
<h1 className="text-lg mt-2 font-bold text-white px-3 lg:py-2">
{season.name} (E:{season.episode_count})
Expand Down
10 changes: 5 additions & 5 deletions src/components/SimilarCardItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Star } from "lucide-react";
import { Link } from "react-router-dom";
import { Button } from "./ui/button";
import imageUrl from "@/utils/image-url";
import Image from "./Image";

interface SimilarCardItemProps<SimilarType> {
card: SimilarType;
Expand Down Expand Up @@ -36,11 +37,10 @@ export default function SimilarCardItem<
</div>
<div className="relative">
<Link to={`/show/${mediaType}/${card.id}`}>
<img
src={imageUrl({
path: card.poster_path,
})}
alt={movieTitle}
<Image
src={imageUrl({ path: card.poster_path, type: "poster" })}
alt={movieTitle!}
type="poster"
/>
</Link>
<div className="absolute bottom-1 left-3 ">
Expand Down
26 changes: 26 additions & 0 deletions src/hooks/useImageFallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect, useState } from "react";

export type TypeImage = "poster" | "backdrop";

const useImageFallback = (type: TypeImage) => {
const [fallback, setFallback] = useState<string>("");

useEffect(() => {
switch (type) {
case "poster":
setFallback("/poster-fallback.png");
break;
case "backdrop":
setFallback("/backdrop-fallback.png");
break;
default:
setFallback("/poster-fallback.png");
}
}, [setFallback, type]);

return {
fallback,
};
};

export default useImageFallback;
9 changes: 6 additions & 3 deletions src/pages/Show/Movie.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import SimilarCardItem from "@/components/SimilarCardItem";
import WatchProviderContainer from "@/components/WatchProviderContainer";
import PopupYoutubeTrailer from "@/components/PopupYoutubeTrailer";
import Image from "@/components/Image";

export default function Movie() {
const params = useParams();
Expand Down Expand Up @@ -83,13 +84,14 @@ export default function Movie() {
key={image.file_path}
className="basis-1/2 lg:basis-1/3"
>
<img
<Image
height={200}
src={imageUrl({
path: image.file_path,
size: "w500",
type: "backdrop",
})}
type="backdrop"
alt={image.file_path}
/>
</CarouselItem>
Expand All @@ -114,13 +116,14 @@ export default function Movie() {
</div>

<div className="bg-black/50 w-full -z-10 h-full absolute"></div>
<img
<Image
src={imageUrl({
path: movie.backdrop_path,
size: "w500",
type: "backdrop",
})}
alt=""
type="backdrop"
alt={movie.title}
className="-z-20 w-full h-full overflow-clip absolute inset-0 bg-fixed bg-left lg:bg-center object-cover object-left lg:object-center"
/>
</div>
Expand Down
8 changes: 6 additions & 2 deletions src/pages/Show/Tv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import pickRandomImages from "@/utils/pick-random-images";
import SeasonCardItem from "@/components/SeasonCardItem";
import WatchProviderContainer from "@/components/WatchProviderContainer";
import PopupYoutubeTrailer from "@/components/PopupYoutubeTrailer";
import Image from "@/components/Image";

export default function Tv() {
const params = useParams();
Expand Down Expand Up @@ -76,12 +77,14 @@ export default function Tv() {
key={image.file_path}
className="basis-1/2 lg:basis-1/3"
>
<img
<Image
height={200}
src={imageUrl({
path: image.file_path,
size: "w500",
type: "backdrop",
})}
type="backdrop"
alt={image.file_path}
/>
</CarouselItem>
Expand All @@ -107,13 +110,14 @@ export default function Tv() {

{/* Backgroud */}
<div className="bg-black/50 w-full -z-10 h-full absolute"></div>
<img
<Image
src={imageUrl({
path: tv.backdrop_path,
size: "w500",
type: "backdrop",
})}
alt=""
type="backdrop"
className="-z-20 w-full h-full overflow-clip absolute inset-0 bg-fixed bg-left lg:bg-center object-cover object-left lg:object-center"
/>
</div>
Expand Down

0 comments on commit c376303

Please sign in to comment.