109 lines
3.5 KiB
TypeScript
109 lines
3.5 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { useParams, Link } from "react-router-dom";
|
|
// import { DefaultService } from "../../api/services/DefaultService";
|
|
import { getTitle, type Title } from "../../api";
|
|
import { TitleStatusControls } from "../../components/TitleStatusControls/TitleStatusControls";
|
|
|
|
export default function TitlePage() {
|
|
const params = useParams();
|
|
const titleId = Number(params.id);
|
|
|
|
const [title, setTitle] = useState<Title | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
// ---------------------------
|
|
// LOAD TITLE INFO
|
|
// ---------------------------
|
|
useEffect(() => {
|
|
const fetchTitle = async () => {
|
|
setLoading(true);
|
|
try {
|
|
// const data = await DefaultService.getTitle(titleId, "all");
|
|
const data = await getTitle({path: {title_id: titleId}})
|
|
setTitle(data?.data ?? null);
|
|
setError(null);
|
|
} catch (err: any) {
|
|
console.error(err);
|
|
setError(err?.message || "Failed to fetch title");
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
fetchTitle();
|
|
}, [titleId]);
|
|
|
|
const getTagsString = () =>
|
|
title?.tags?.map(tag => tag.en).filter(Boolean).join(", ");
|
|
|
|
if (loading) return <div className="mt-20 font-medium text-black">Loading title...</div>;
|
|
if (error) return <div className="mt-20 text-red-600 font-medium">{error}</div>;
|
|
if (!title) return null;
|
|
|
|
return (
|
|
<div className="w-full min-h-screen bg-gray-50 p-6 flex justify-center">
|
|
<div className="flex flex-col md:flex-row bg-white shadow-lg rounded-xl max-w-4xl w-full p-6 gap-6">
|
|
{/* Poster + status buttons */}
|
|
<div className="flex flex-col items-center">
|
|
<img
|
|
src={title.poster?.image_path || "/default-poster.png"}
|
|
alt={title.title_names?.en?.[0] || "Title poster"}
|
|
className="w-48 h-72 object-cover rounded-lg mb-4"
|
|
/>
|
|
|
|
{/* Status buttons */}
|
|
<TitleStatusControls titleId={titleId} />
|
|
</div>
|
|
|
|
{/* Title info */}
|
|
<div className="flex-1 flex flex-col">
|
|
<h1 className="text-3xl font-bold mb-2">
|
|
{title.title_names?.en?.[0] || "Untitled"}
|
|
</h1>
|
|
|
|
{title.studio && (
|
|
<p className="text-gray-700 mb-1">
|
|
Studio:{" "}
|
|
{title.studio.id ? (
|
|
<Link
|
|
to={`/studios/${title.studio.id}`}
|
|
className="text-blue-600 hover:underline"
|
|
>
|
|
{title.studio.name}
|
|
</Link>
|
|
) : (
|
|
title.studio.name
|
|
)}
|
|
</p>
|
|
)}
|
|
|
|
{title.title_status && <p className="text-gray-700 mb-1">Status: {title.title_status}</p>}
|
|
|
|
{title.rating !== undefined && (
|
|
<p className="text-gray-700 mb-1">
|
|
Rating: {title.rating} ({title.rating_count} votes)
|
|
</p>
|
|
)}
|
|
|
|
{title.release_year && (
|
|
<p className="text-gray-700 mb-1">
|
|
Released: {title.release_year} {title.release_season || ""}
|
|
</p>
|
|
)}
|
|
|
|
{title.episodes_aired !== undefined && (
|
|
<p className="text-gray-700 mb-1">
|
|
Episodes: {title.episodes_aired}/{title.episodes_all}
|
|
</p>
|
|
)}
|
|
|
|
{title.tags && title.tags.length > 0 && (
|
|
<p className="text-gray-700 mb-1">
|
|
Tags: {getTagsString()}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|