feat: implement API for podcasts/[slug]

This commit is contained in:
jinhojang6 2023-08-18 12:49:22 +09:00
parent c80c3c8eec
commit 028aa01682
6 changed files with 111 additions and 40 deletions

View File

@ -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'};
`

View File

@ -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));
`

View File

@ -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>
)

View File

@ -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;

View File

@ -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,
},
}
}

View File

@ -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, '""'),
)