78 lines
2.0 KiB
TypeScript
78 lines
2.0 KiB
TypeScript
import { useCallback, useState } from "preact/hooks";
|
|
import { IconWand } from "@components/icons.tsx";
|
|
|
|
type RecommendationState = "disabled" | "loading";
|
|
|
|
export function Recommendations(
|
|
{ id, type, load = false }: {
|
|
id: string;
|
|
type: string;
|
|
load?: boolean;
|
|
},
|
|
) {
|
|
const [state, setState] = useState<RecommendationState>("disabled");
|
|
const [results, setResults] = useState();
|
|
|
|
const startFetch = useCallback(
|
|
async () => {
|
|
if (state === "loading") return;
|
|
setState("loading");
|
|
const res = await fetch(`/api/recommendation/${type}/${id}`);
|
|
const json = await res.json();
|
|
setResults(json);
|
|
},
|
|
[id, type],
|
|
);
|
|
|
|
if (load) {
|
|
startFetch();
|
|
}
|
|
|
|
return (
|
|
<span>
|
|
{results && (
|
|
<div
|
|
style={{ boxShadow: "0px 49px 33px #1412183b inset" }}
|
|
class="relative w-full bg-white -mt-10 pt-10 -z-50 rounded-2xl p-5"
|
|
>
|
|
<h3 class="text-2xl my-5 flex items-center gap-2">
|
|
Similar Movies
|
|
</h3>
|
|
<ul class="gap-5">
|
|
{results.map((res) => {
|
|
return (
|
|
<div class="flex gap-5 items-center mb-4">
|
|
<img
|
|
class="w-12 h-12 rounded-full object-cover"
|
|
src={`https://image.tmdb.org/t/p/original${res.poster_path}`}
|
|
/>
|
|
<p>{res.title}</p>
|
|
</div>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
)}
|
|
|
|
{state === "loading" && !results && (
|
|
<div
|
|
style={{ boxShadow: "0px 49px 33px #1412183b inset" }}
|
|
class="relative w-full bg-white -mt-10 pt-10 -z-50 rounded-2xl p-5"
|
|
>
|
|
<p class="mt-5">Loading...</p>
|
|
</div>
|
|
)}
|
|
|
|
{!results && state === "disabled" &&
|
|
(
|
|
<button
|
|
onClick={startFetch}
|
|
class="ml-8 mt-2 font-thin flex items-center gap-2 text-white my-2"
|
|
>
|
|
<IconWand class="w-4" /> Similar
|
|
</button>
|
|
)}
|
|
</span>
|
|
);
|
|
}
|