2024-08-21 03:27:03 +03:00
|
|
|
import type { RecommendationDto } from '@jellyfin/sdk/lib/generated-client/models/recommendation-dto';
|
|
|
|
import { RecommendationType } from '@jellyfin/sdk/lib/generated-client/models/recommendation-type';
|
2024-02-28 22:47:36 +03:00
|
|
|
import React, { type FC } from 'react';
|
2024-01-12 21:08:06 +03:00
|
|
|
import {
|
|
|
|
useGetMovieRecommendations,
|
|
|
|
useGetSuggestionSectionsWithItems
|
|
|
|
} from 'hooks/useFetchItems';
|
|
|
|
import { appRouter } from 'components/router/appRouter';
|
2024-08-14 13:31:34 -04:00
|
|
|
import globalize from 'lib/globalize';
|
2024-01-12 21:08:06 +03:00
|
|
|
import Loading from 'components/loading/LoadingComponent';
|
2024-09-23 02:53:44 +03:00
|
|
|
import NoItemsMessage from 'components/common/NoItemsMessage';
|
|
|
|
import SectionContainer from '../../../../components/common/SectionContainer';
|
2024-02-28 22:47:36 +03:00
|
|
|
import { CardShape } from 'utils/card';
|
|
|
|
import type { ParentId } from 'types/library';
|
|
|
|
import type { Section, SectionType } from 'types/sections';
|
2024-08-21 03:27:03 +03:00
|
|
|
import type { ItemDto } from 'types/base/models/item-dto';
|
2024-01-12 21:08:06 +03:00
|
|
|
|
|
|
|
interface SuggestionsSectionViewProps {
|
|
|
|
parentId: ParentId;
|
|
|
|
sectionType: SectionType[];
|
|
|
|
isMovieRecommendationEnabled: boolean | undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
const SuggestionsSectionView: FC<SuggestionsSectionViewProps> = ({
|
|
|
|
parentId,
|
|
|
|
sectionType,
|
|
|
|
isMovieRecommendationEnabled = false
|
|
|
|
}) => {
|
|
|
|
const { isLoading, data: sectionsWithItems } =
|
|
|
|
useGetSuggestionSectionsWithItems(parentId, sectionType);
|
|
|
|
|
|
|
|
const {
|
|
|
|
isLoading: isRecommendationsLoading,
|
|
|
|
data: movieRecommendationsItems
|
|
|
|
} = useGetMovieRecommendations(isMovieRecommendationEnabled, parentId);
|
|
|
|
|
|
|
|
if (isLoading || isRecommendationsLoading) {
|
|
|
|
return <Loading />;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sectionsWithItems?.length && !movieRecommendationsItems?.length) {
|
2024-09-23 02:53:44 +03:00
|
|
|
return <NoItemsMessage />;
|
2024-01-12 21:08:06 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
const getRouteUrl = (section: Section) => {
|
|
|
|
return appRouter.getRouteUrl('list', {
|
|
|
|
serverId: window.ApiClient.serverId(),
|
|
|
|
itemTypes: section.itemTypes,
|
|
|
|
parentId: parentId
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const getRecommendationTittle = (recommendation: RecommendationDto) => {
|
|
|
|
let title = '';
|
|
|
|
|
|
|
|
switch (recommendation.RecommendationType) {
|
|
|
|
case RecommendationType.SimilarToRecentlyPlayed:
|
|
|
|
title = globalize.translate(
|
|
|
|
'RecommendationBecauseYouWatched',
|
|
|
|
recommendation.BaselineItemName
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecommendationType.SimilarToLikedItem:
|
|
|
|
title = globalize.translate(
|
|
|
|
'RecommendationBecauseYouLike',
|
|
|
|
recommendation.BaselineItemName
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecommendationType.HasDirectorFromRecentlyPlayed:
|
|
|
|
case RecommendationType.HasLikedDirector:
|
|
|
|
title = globalize.translate(
|
|
|
|
'RecommendationDirectedBy',
|
|
|
|
recommendation.BaselineItemName
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RecommendationType.HasActorFromRecentlyPlayed:
|
|
|
|
case RecommendationType.HasLikedActor:
|
|
|
|
title = globalize.translate(
|
|
|
|
'RecommendationStarring',
|
|
|
|
recommendation.BaselineItemName
|
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
2024-02-28 22:47:36 +03:00
|
|
|
return title;
|
2024-01-12 21:08:06 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{sectionsWithItems?.map(({ section, items }) => (
|
|
|
|
<SectionContainer
|
|
|
|
key={section.type}
|
2024-09-23 02:53:44 +03:00
|
|
|
sectionHeaderProps={{
|
|
|
|
title: globalize.translate(section.name),
|
|
|
|
url: getRouteUrl(section)
|
|
|
|
}}
|
|
|
|
itemsContainerProps={{
|
|
|
|
queryKey: ['SuggestionSectionWithItems']
|
|
|
|
}}
|
|
|
|
items={items}
|
2024-01-12 21:08:06 +03:00
|
|
|
cardOptions={{
|
|
|
|
...section.cardOptions,
|
2024-01-31 04:32:54 +03:00
|
|
|
queryKey: ['SuggestionSectionWithItems'],
|
2024-01-12 21:08:06 +03:00
|
|
|
showTitle: true,
|
|
|
|
centerText: true,
|
|
|
|
cardLayout: false,
|
|
|
|
overlayText: false
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
|
|
|
|
{movieRecommendationsItems?.map((recommendation, index) => (
|
|
|
|
<SectionContainer
|
|
|
|
// eslint-disable-next-line react/no-array-index-key
|
|
|
|
key={`${recommendation.CategoryId}-${index}`} // use a unique id return value may have duplicate id
|
2024-09-23 02:53:44 +03:00
|
|
|
sectionHeaderProps={{
|
|
|
|
title: getRecommendationTittle(recommendation)
|
|
|
|
}}
|
|
|
|
itemsContainerProps={{
|
|
|
|
queryKey: ['MovieRecommendations']
|
|
|
|
}}
|
|
|
|
items={recommendation.Items as ItemDto[]}
|
2024-01-12 21:08:06 +03:00
|
|
|
cardOptions={{
|
2024-01-31 04:32:54 +03:00
|
|
|
queryKey: ['MovieRecommendations'],
|
2024-02-28 22:47:36 +03:00
|
|
|
shape: CardShape.PortraitOverflow,
|
2024-01-12 21:08:06 +03:00
|
|
|
showYear: true,
|
|
|
|
scalable: true,
|
|
|
|
overlayPlayButton: true,
|
|
|
|
showTitle: true,
|
|
|
|
centerText: true,
|
|
|
|
cardLayout: false
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default SuggestionsSectionView;
|