feat: implement API for podcasts/[slug]
This commit is contained in:
parent
c80c3c8eec
commit
028aa01682
|
@ -6,34 +6,43 @@ interface Props {
|
|||
header?: React.ReactNode
|
||||
episodes: LPE.Podcast.Document[]
|
||||
show?: LPE.Podcast.Show
|
||||
divider?: boolean
|
||||
}
|
||||
|
||||
export default function EpisodesList({ header, episodes, show }: Props) {
|
||||
export default function EpisodesList({
|
||||
header,
|
||||
episodes,
|
||||
show,
|
||||
divider = false,
|
||||
}: Props) {
|
||||
return (
|
||||
<EpisodeListContainer>
|
||||
{header}
|
||||
<EpisodesContainer>
|
||||
{episodes.slice(0, 2).map((episode) => (
|
||||
<PostCard
|
||||
key={episode.id}
|
||||
contentType={LPE.PostTypes.Podcast}
|
||||
data={{
|
||||
authors: episode.authors,
|
||||
date: episode.publishedAt ? new Date(episode.publishedAt) : null,
|
||||
slug: episode.show?.slug
|
||||
? `${episode.show?.slug}/${episode.slug}`
|
||||
: `${show?.slug}/${episode.slug}`,
|
||||
title: episode.title,
|
||||
coverImage: episode.coverImage,
|
||||
tags: episode.tags,
|
||||
podcastShowDetails: {
|
||||
<PostCardContainer key={episode.id} divider={divider}>
|
||||
<PostCard
|
||||
contentType={LPE.PostTypes.Podcast}
|
||||
data={{
|
||||
authors: episode.authors,
|
||||
date: episode.publishedAt
|
||||
? new Date(episode.publishedAt)
|
||||
: null,
|
||||
slug: episode.show?.slug
|
||||
? `${episode.show?.slug}/${episode.slug}`
|
||||
: `${show?.slug}/${episode.slug}`,
|
||||
title: episode.title,
|
||||
slug: `${episode.show?.slug}`,
|
||||
episodeNumber: episode.episodeNumber,
|
||||
podcast: episode.show as LPE.Podcast.Show,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
coverImage: episode.coverImage,
|
||||
tags: episode.tags,
|
||||
podcastShowDetails: {
|
||||
title: episode.title,
|
||||
slug: `${episode.show?.slug}`,
|
||||
episodeNumber: episode.episodeNumber,
|
||||
podcast: episode.show as LPE.Podcast.Show,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</PostCardContainer>
|
||||
))}
|
||||
</EpisodesContainer>
|
||||
</EpisodeListContainer>
|
||||
|
@ -43,12 +52,16 @@ export default function EpisodesList({ header, episodes, show }: Props) {
|
|||
const EpisodeListContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid rgb(var(--lsd-border-primary));
|
||||
padding-top: 16px;
|
||||
`
|
||||
|
||||
const EpisodesContainer = styled.div`
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding-top: 24px;
|
||||
`
|
||||
|
||||
const PostCardContainer = styled.div<{ divider: boolean }>`
|
||||
padding-top: 24px;
|
||||
border-top: ${({ divider }) =>
|
||||
divider ? '1px solid rgb(var(--lsd-border-primary))' : 'none'};
|
||||
`
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import styled from '@emotion/styled'
|
||||
import React from 'react'
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode
|
||||
marginTop?: number
|
||||
}
|
||||
|
||||
export default function PodcastSection({ children, marginTop = 140 }: Props) {
|
||||
return <Section marginTop={marginTop}>{children}</Section>
|
||||
}
|
||||
|
||||
const Section = styled.div<{ marginTop: number }>`
|
||||
margin-top: ${(props) => props.marginTop}px;
|
||||
border-top: 1px solid rgb(var(--lsd-border-primary));
|
||||
`
|
|
@ -5,23 +5,29 @@ import EpisodesList from '@/components/Podcasts/Episodes.List'
|
|||
import { Typography } from '@acid-info/lsd-react'
|
||||
import PodcastShowCard from '@/components/Podcasts/PodcastShowCard'
|
||||
import { PodcastType } from '@/components/PostCard/PostCard'
|
||||
import PodcastSection from '@/components/Podcasts/Podcast.Section'
|
||||
|
||||
interface Props {
|
||||
show: LPE.Podcast.Show
|
||||
latestEpisodes: LPE.Podcast.Document[]
|
||||
highlightedEpisodes: LPE.Podcast.Document[]
|
||||
}
|
||||
|
||||
const PodcastShowContainer = (props: Props) => {
|
||||
const { show, latestEpisodes } = props
|
||||
const { show, latestEpisodes, highlightedEpisodes } = props
|
||||
|
||||
return (
|
||||
<PodcastsGrid>
|
||||
<PodcastsBodyContainer className={'w-16'}>
|
||||
<PodcastShowCard show={show} />
|
||||
<EpisodesList
|
||||
header={<Typography variant="body2">Latest Episodes</Typography>}
|
||||
episodes={latestEpisodes}
|
||||
/>
|
||||
<PodcastSection>
|
||||
<EpisodesList
|
||||
header={<Typography variant="body2">All episodes</Typography>}
|
||||
episodes={highlightedEpisodes}
|
||||
/>
|
||||
</PodcastSection>
|
||||
|
||||
<EpisodesList episodes={latestEpisodes} divider={true} />
|
||||
</PodcastsBodyContainer>
|
||||
</PodcastsGrid>
|
||||
)
|
||||
|
|
|
@ -6,6 +6,7 @@ import EpisodesList from '@/components/Podcasts/Episodes.List'
|
|||
import { Button, Typography } from '@acid-info/lsd-react'
|
||||
import { LogosCircleIcon } from '@/components/Icons/LogosCircleIcon'
|
||||
import Link from 'next/link'
|
||||
import PodcastSection from '@/components/Podcasts/Podcast.Section'
|
||||
|
||||
interface Props {
|
||||
shows: LPE.Podcast.Show[]
|
||||
|
@ -20,15 +21,15 @@ const PodcastsContainer = (props: Props) => {
|
|||
<PodcastsBodyContainer className={'w-16'}>
|
||||
<PodcastsLists shows={shows} />
|
||||
|
||||
<Section>
|
||||
<PodcastSection>
|
||||
<EpisodesList
|
||||
header={<EpisodeListHeader>Latest Episodes</EpisodeListHeader>}
|
||||
episodes={highlightedEpisodes}
|
||||
/>
|
||||
</Section>
|
||||
</PodcastSection>
|
||||
|
||||
{shows.map((show) => (
|
||||
<Section key={show.id}>
|
||||
<PodcastSection key={show.id}>
|
||||
<EpisodesList
|
||||
header={
|
||||
<EpisodeListHeader>
|
||||
|
@ -49,7 +50,7 @@ const PodcastsContainer = (props: Props) => {
|
|||
episodes={show.episodes as LPE.Podcast.Document[]}
|
||||
show={show}
|
||||
/>
|
||||
</Section>
|
||||
</PodcastSection>
|
||||
))}
|
||||
</PodcastsBodyContainer>
|
||||
</PodcastsGrid>
|
||||
|
@ -68,10 +69,6 @@ const PodcastsGrid = styled(Grid)`
|
|||
}
|
||||
`
|
||||
|
||||
const Section = styled.div`
|
||||
margin-top: 140px;
|
||||
`
|
||||
|
||||
const EpisodeListHeader = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -5,18 +5,20 @@ import { ReactNode } from 'react'
|
|||
import { LPE } from '../../../types/lpe.types'
|
||||
import PodcastsLayout from '@/layouts/PodcastsLayout/Podcasts.layout'
|
||||
|
||||
import TEMP_DATA from '../podcasts-temp-data.json'
|
||||
import PodcastShowContainer from '@/containers/PodcastShowContainer'
|
||||
import unbodyApi from '@/services/unbody/unbody.service'
|
||||
|
||||
interface PodcastShowProps {
|
||||
show: LPE.Podcast.Show
|
||||
latestEpisodes: LPE.Podcast.Document[]
|
||||
highlightedEpisodes: LPE.Podcast.Document[]
|
||||
errors: string | null
|
||||
}
|
||||
|
||||
const PodcastShowPage = ({
|
||||
show,
|
||||
latestEpisodes,
|
||||
highlightedEpisodes,
|
||||
errors,
|
||||
}: PodcastShowProps) => {
|
||||
const {
|
||||
|
@ -35,7 +37,11 @@ const PodcastShowPage = ({
|
|||
pagePath={`/podcasts/${showSlug}`}
|
||||
tags={[]}
|
||||
/>
|
||||
<PodcastShowContainer show={show} latestEpisodes={latestEpisodes} />
|
||||
<PodcastShowContainer
|
||||
show={show}
|
||||
latestEpisodes={latestEpisodes}
|
||||
highlightedEpisodes={highlightedEpisodes}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -49,7 +55,6 @@ export async function getStaticPaths() {
|
|||
}
|
||||
|
||||
export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
||||
const { shows, latestEpisodes } = TEMP_DATA
|
||||
const { showSlug } = params!
|
||||
|
||||
if (!showSlug) {
|
||||
|
@ -59,11 +64,43 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
}
|
||||
}
|
||||
|
||||
const { data: showData, errors: podcastShowDataErrors } =
|
||||
await unbodyApi.getPodcastShow({
|
||||
showSlug: showSlug as string,
|
||||
})
|
||||
|
||||
const { data: latestEpisodesData, errors: latestEpisodesErros } =
|
||||
await unbodyApi.getLatestEpisodes({
|
||||
showSlug: showSlug as string,
|
||||
page: 1,
|
||||
limit: 12,
|
||||
})
|
||||
|
||||
const { data: highlightedEpisodesData, errors: highlightedEpisodesErrors } =
|
||||
await unbodyApi.getHighlightedEpisodes({
|
||||
showSlug: showSlug as string,
|
||||
page: 1,
|
||||
limit: 9,
|
||||
})
|
||||
|
||||
// TODO : handle undefined values in JSON
|
||||
const show = JSON.parse(JSON.stringify(showData).replace(/null/g, '""'))
|
||||
|
||||
// TODO : handle undefined values in JSON
|
||||
const latestEpisodes = JSON.parse(
|
||||
JSON.stringify(latestEpisodesData).replace(/null/g, '""'),
|
||||
)
|
||||
|
||||
// TODO : handle undefined values in JSON
|
||||
const highlightedEpisodes = JSON.parse(
|
||||
JSON.stringify(highlightedEpisodesData).replace(/null/g, '""'),
|
||||
)
|
||||
|
||||
return {
|
||||
props: {
|
||||
show: shows[0],
|
||||
show,
|
||||
latestEpisodes,
|
||||
error: null,
|
||||
highlightedEpisodes,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,10 +55,12 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO : handle undefined values in JSON
|
||||
const podcastShows = JSON.parse(
|
||||
JSON.stringify(podcastShowsData).replace(/null/g, '""'),
|
||||
)
|
||||
|
||||
// TODO : handle undefined values in JSON
|
||||
const highlightedEpisodes = JSON.parse(
|
||||
JSON.stringify(highlightedEpisodesData).replace(/null/g, '""'),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue