diff --git a/src/components/Discover/RecentlyAddedSlider/index.tsx b/src/components/Discover/RecentlyAddedSlider/index.tsx
index e291b3410..faeb91e1e 100644
--- a/src/components/Discover/RecentlyAddedSlider/index.tsx
+++ b/src/components/Discover/RecentlyAddedSlider/index.tsx
@@ -2,6 +2,7 @@ import Slider from '@app/components/Slider';
import MusicTitleCard from '@app/components/TitleCard/MusicTitleCard';
import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
import { Permission, useUser } from '@app/hooks/useUser';
+import type { SecondaryType } from '@server/constants/media';
import type { MediaResultsResponse } from '@server/interfaces/api/mediaInterfaces';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
@@ -79,7 +80,8 @@ const RecentlyAddedSlider = ({
key={`media-slider-item-${item.id}`}
id={item.id}
mbId={item.mbId ?? ''}
- //type={item.secondaryType as SecondaryType}
+ type={item.secondaryType as SecondaryType}
+ displayType={item.secondaryType as SecondaryType}
/>
))}
/>
diff --git a/src/components/MusicDetails/index.tsx b/src/components/MusicDetails/index.tsx
index c7bf07d04..e748608f7 100644
--- a/src/components/MusicDetails/index.tsx
+++ b/src/components/MusicDetails/index.tsx
@@ -24,7 +24,7 @@ import type {
} from '@server/models/Search';
import 'country-flag-icons/3x2/flags.css';
import { useRouter } from 'next/router';
-import { useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import useSWR from 'swr';
@@ -46,6 +46,7 @@ const messages = defineMessages({
eps: 'EPs',
broadcasts: 'Broadcasts',
others: 'Others',
+ feats: 'Featured In',
});
interface MusicDetailsProps {
@@ -118,10 +119,6 @@ const MusicDetails = ({
iOSPlexUrl: data?.mediaInfo?.iOSPlexUrl,
});
- if (!data) {
- return ;
- }
-
const mediaLinks: PlayButtonLink[] = [];
if (
@@ -137,23 +134,29 @@ const MusicDetails = ({
});
}
- const title =
- data.mediaType !== SecondaryType.ARTIST ? data.title : data.name;
+ const cleanDate = (date: Date | string | undefined) => {
+ date = date ?? '';
+ return new Date(date).toLocaleDateString('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ });
+ };
const mainDateDisplay: string =
type === SecondaryType.ARTIST &&
- (data as ArtistResult).beginDate &&
+ cleanDate((data as ArtistResult).beginDate) &&
(data as ArtistResult).endDate
- ? `${(data as ArtistResult).beginDate} - ${
+ ? `${cleanDate((data as ArtistResult).beginDate)} - ${cleanDate(
(data as ArtistResult).endDate
- }`
+ )}`
: type === SecondaryType.ARTIST && (data as ArtistResult).beginDate
- ? `${(data as ArtistResult).beginDate}`
+ ? `${cleanDate((data as ArtistResult).beginDate)}`
: type === SecondaryType.RELEASE && (data as ReleaseResult).date
- ? `${(data as ReleaseResult).date}`
+ ? `${cleanDate((data as ReleaseResult).date)}`
: type === SecondaryType.RECORDING &&
(data as RecordingResult).firstReleased
- ? `${(data as RecordingResult).firstReleased}`
+ ? `${cleanDate((data as RecordingResult).firstReleased)}`
: '';
const releaseGroups: ReleaseGroupResult[] = to_explore.includes(
@@ -175,11 +178,91 @@ const MusicDetails = ({
{}
);
- const albums = categorizedReleaseGroupsType['Album'] ?? [];
- const singles = categorizedReleaseGroupsType['Single'] ?? [];
- const eps = categorizedReleaseGroupsType['EP'] ?? [];
- const broadcasts = categorizedReleaseGroupsType['Broadcast'] ?? [];
- const others = categorizedReleaseGroupsType['Other'] ?? [];
+ const [albums, setAlbums] = useState(
+ categorizedReleaseGroupsType['Album'] ?? []
+ );
+ const [singles, setSingles] = useState(
+ categorizedReleaseGroupsType['Single'] ?? []
+ );
+ const [eps, setEps] = useState(categorizedReleaseGroupsType['EP'] ?? []);
+ const [broadcasts, setBroadcasts] = useState(
+ categorizedReleaseGroupsType['Broadcast'] ?? []
+ );
+ const [others, setOthers] = useState(
+ categorizedReleaseGroupsType['Other'] ?? []
+ );
+
+ const [currentOffset, setCurrentOffset] = useState(0);
+
+ const [isLoading, setLoading] = useState(false);
+
+ const getMore = useCallback(() => {
+ if (data?.mediaType === SecondaryType.ARTIST) {
+ if (isLoading) {
+ return;
+ }
+ setLoading(true);
+ fetch(
+ `/api/v1/music/${router.query.type}/${
+ router.query.mbId
+ }?full=true&offset=${currentOffset + 25}`
+ )
+ .then((res) => res.json())
+ .then((res) => {
+ if (res) {
+ res = (res as ArtistResult).releaseGroups;
+ res = res.reduce(
+ ((
+ group: { [key: string]: ReleaseGroupResult[] },
+ item: ReleaseGroupResult
+ ) => {
+ if (!group[item.type]) {
+ group[item.type] = [];
+ }
+ group[item.type].push(item);
+ return group;
+ }) ?? {},
+ {}
+ );
+ setAlbums((prev) => [...prev, ...(res['Album'] ?? [])]);
+ setSingles((prev) => [...prev, ...(res.Single ?? [])]);
+ setEps((prev) => [...prev, ...(res.EP ?? [])]);
+ setBroadcasts((prev) => [...prev, ...(res.Broadcast ?? [])]);
+ setOthers((prev) => [...prev, ...(res.Other ?? [])]);
+ setCurrentOffset(currentOffset + 25);
+ setLoading(false);
+ }
+ });
+ }
+ }, [
+ currentOffset,
+ data?.mediaType,
+ isLoading,
+ router.query.mbId,
+ router.query.type,
+ ]);
+
+ useEffect(() => {
+ const handleScroll = () => {
+ const bottom =
+ document.body.scrollHeight - window.scrollY - window.outerHeight <= 1;
+ if (bottom) {
+ getMore();
+ }
+ };
+ window.addEventListener('scroll', handleScroll);
+
+ return () => {
+ window.removeEventListener('scroll', handleScroll);
+ };
+ }, [getMore]);
+
+ if (!data) {
+ return ;
+ }
+
+ const title =
+ data.mediaType !== SecondaryType.ARTIST ? data.title : data.name;
const tags: string[] = data.tags ?? [];
diff --git a/src/components/TitleCard/MusicTitleCard.tsx b/src/components/TitleCard/MusicTitleCard.tsx
index b6658f621..15ef056fb 100644
--- a/src/components/TitleCard/MusicTitleCard.tsx
+++ b/src/components/TitleCard/MusicTitleCard.tsx
@@ -1,6 +1,7 @@
import TitleCard from '@app/components/TitleCard';
import { Permission, useUser } from '@app/hooks/useUser';
-import { MediaType, SecondaryType } from '@server/constants/media';
+import type { SecondaryType } from '@server/constants/media';
+import { MediaType } from '@server/constants/media';
import type {
ArtistResult,
RecordingResult,
@@ -29,9 +30,10 @@ const MusicTitleCard = ({
id,
mbId,
canExpand,
- type = SecondaryType.ARTIST,
+ type,
displayType,
}: MusicBrainTitleCardProps) => {
+ console.log(type);
const { hasPermission } = useUser();
const { ref, inView } = useInView({