🎬 Content Details
The Content Details page displays rich metadata, trailers, watch actions, seasons, and recommended content for a movie or series. It is implemented using the DetailsContent component, backed by powerful React Query hooks and dynamic SSR logic.
Built using:
- ✅
@zezosoft/react-ui-kit→ContentDetails,SkeletonLoader, etc. - ✅ React Query → For favorites, seasons, recommendations
- ✅ App Router →
app/detail/[...slug]/page.tsxwith server functions
🗂️ Folder Structure
app/
├── detail/
│ └── [...slug]/
│ └── page.tsx # SSR route for fetching content by slug
├── components/
│ └── content/
│ ├── Content.tsx # Lists homepage sections
│ └── DetailsContent.tsx # Main detailed view component📋 Props
| Prop | Type | Description |
|---|---|---|
content | IContentData | Main movie/series object with metadata |
userSession | ISession | null | Current authenticated user session |
isBuyOrRent | boolean | Indicates if the content is TVOD (buy/rent) and already purchased |
seasons | ISeasonData[] | Season data for series content |
selectedSeason | ISeasonData | Currently active season (usually seasons[0]) |
seasonsData | ISeasonData[] | Optional – Pass complete season info separately |
isTabSwitcher | boolean | Enable/disable season tab switching |
buttons | ActionButton[] | List of UI actions like play, trailer, favorite, share |
moreData | MoreDetailsConfig | Nested data like description, crew, language, genres, etc. |
🧠 Feature Summary
| Feature | Behavior |
|---|---|
| ⭐ Favorite | Optimistically updates UI using React Query mutations |
| ▶️ Play | Trigger onClick() from button prop |
| 🎞️ Trailer | Same as above — hook into trailer modal or overlay |
| 📺 Seasons | If content.type === "series", show episodes tab |
| 🔁 Recommendations | Uses backend section ID for similar or trending titles |
| 🔄 TVOD | If BUY_OR_RENT, verify entitlement before allowing playback |
| 🔗 Share | Custom button, supports navigator.share() or custom dialog |
⚠️ Please make sure
zezoClientis properly configured — otherwise, the Content Details page won’t be able to load the required data.
🧩 Component: DetailsContent.tsx
This component renders a complete content detail page using the following key props:
<ZezoOttContentDetails
content={content} // Full content data object
userSession={userSession} // Current logged-in session
isBuyOrRent={isBuyOrRent} // Indicates if TVOD (buy/rent) is active
seasons={seasons} // Array of seasons (for series)
selectedSeason={seasons?.[0]} // Initially selected season
seasonsData={seasons} // Redundant but required for tab switcher
isTabSwitcher={true} // Show season/episode tabs if true
buttons={[
// List of action buttons to show
{
type: "play",
label: "Watch Now",
icon: <Play />,
onClick: () => {},
},
{
type: "trailer",
label: "Watch Trailer",
icon: <TbMovie size={36} />,
onClick: () => {},
},
{
type: "faverite",
label: isFavorite ? "Added to Watchlist" : "Add to Watchlist",
icon: isFavoriting ? (
<LucideLoader className="animate-spin" />
) : isFavorite ? (
<LucideCheck />
) : (
<LucidePlus />
),
onClick: () => handleAddToFavorite(),
isLoadingFavorite: isFavoriting,
},
{
type: "share",
label: "Share",
icon: <Share />,
onClick: () => {},
},
]}
moreData={{
relatedContent: recommendedContent, // More like this
moreDetails: {
description: content.description,
cast: content.cast,
crew: content.crew,
genres: content.genres,
language: content.language,
},
episodeTab: {
onClick: (season) => season, // Handle episode tab switch
},
}}
/>🔁 Favorite Logic with React Query
const { data: isFavorite = false } = useQuery({
queryKey: ["favorites", content._id],
queryFn: () => zezoClient().favorites.getIsFavorite(content._id),
enabled: !!content?._id,
});
const { mutate: handleAddToFavorite, isPending: isFavoriting } = useMutation({
mutationFn: () => zezoClient().favorites.addToFavorites(content),
onMutate: () => queryClient.setQueryData(["favorites", content._id], true),
onSuccess: () => queryClient.invalidateQueries(["favorites", content._id]),
onError: () => queryClient.setQueryData(["favorites", content._id], false),
});📦 Server-side Data: page.tsx
const slug = (await params).slug?.[1] ?? (await params).slug?.[0] ?? "";
const content = await getContent(slug); // fetch by slug
const contentRecommended = await recommendedContent(); // recommended section
const seasons = content?.type === "series" ? await getSeasons(query) : null;
const isBuyOrRent =
content?.content_offering_type === "BUY_OR_RENT"
? await getIsTvodContentPurchased(content._id)
: false;
return (
<DetailsContent
content={content}
seasons={seasons}
userSession={session}
recommendedContent={contentRecommended}
isBuyOrRent={isBuyOrRent}
/>
);🧠 Behavior Summary
| Feature | Behavior |
|---|---|
| Favorite Toggle | Uses React Query for optimistic updates and sync |
| Season Selector | Auto-selects first season if content is a series |
| Trailer / Play | Customizable onClick handlers passed as props |
| Recommendations | Dynamically fetched from “recommended-movies” section |
| Share Button | You can integrate navigator.share() or a custom modal |
| TVOD Support | Checks if content is already purchased/rented before showing buy prompt |
✅ Final Notes
DetailsContentis the main UI wrapper for your content detail page.- It supports series, movies, TVOD content, and integrates favorite logic using React Query.
- You can fully customize action buttons (
play,trailer,favorite,share) via thebuttonsprop. - Series data (seasons, episodes) is shown only if the content type is
"series". - Recommendations are fetched using the “recommended-movies” section — but you can plug any section ID.
- Skeletons and fallbacks are handled in
page.tsx, not inDetailsContent.
💡 Best Practice: Use
Suspense,error boundaries, and conditional rendering to ensure graceful fallback ifcontentoruserSessionis not available.
⚠️ Required Packages
Ensure these packages are installed to use DetailsContent and supporting components:
pnpm
Terminal
pnpm add @zezosoft/zezo-ott-api-client @zezosoft/zezo-ott-react-ui-kitLast updated on