From 62a2eee14ea3ccadcdb4a545aa37a7ea32e8521b Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Tue, 22 Aug 2023 23:29:12 +0900 Subject: [PATCH 01/13] chore: update episode header --- .../Episode/Header/Episode.Header.tsx | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/components/Episode/Header/Episode.Header.tsx b/src/components/Episode/Header/Episode.Header.tsx index b0612f8..e8ec748 100644 --- a/src/components/Episode/Header/Episode.Header.tsx +++ b/src/components/Episode/Header/Episode.Header.tsx @@ -6,6 +6,8 @@ import { LogosCircleIcon } from '@/components/Icons/LogosCircleIcon' import EpisodeChannels from './Episode.Channels' import EpisodeStats from '../Episode.Stats' import EpisodePlayer from './Episode.Player' +import Image from 'next/image' +import Link from 'next/link' export type EpisodeHeaderProps = LPE.Podcast.Document & { channel: LPE.Podcast.Channel @@ -37,10 +39,19 @@ const EpisodeHeader = ({ {title} - - - Network State Podcast - + {show && ( + + + {show.logo.alt} + {show?.title} + + + )} {tags && } {channels && } {description && ( @@ -86,31 +97,16 @@ const EpisodeSubtitle = styled(CustomTypography)` } ` -const PodcastName = styled.div` +const Show = styled.div` display: flex; align-items: center; gap: 12px; margin-bottom: 20px; + text-decoration: none; ` -// 16:9 responsive aspect ratio -const PlayerContainer = styled.div` - margin-bottom: 32px; - position: relative; - padding-bottom: 56.25%; - padding-top: 30px; - height: 0; - overflow: hidden; - - iframe, - object, - embed { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - } +const CustomLink = styled(Link)` + text-decoration: none; ` export default EpisodeHeader From 0a21941ec9f111e331a52e4b607213a8b3d40270 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Wed, 23 Aug 2023 14:03:52 +0900 Subject: [PATCH 02/13] feat: implement persistent global audio player --- .env | 6 +- .../Episode/Header/Episode.Header.tsx | 1 - .../Episode/Header/Episode.Player.tsx | 81 ++++++++++++++----- .../Header/Episode.SimplecastPlayer.tsx | 14 ++-- .../GlobalAudioPlayer/GlobalAudioPlayer.tsx | 11 ++- .../GlobalAudioPlayer/episode.state.ts | 2 - 6 files changed, 77 insertions(+), 38 deletions(-) diff --git a/.env b/.env index facb74b..512521c 100644 --- a/.env +++ b/.env @@ -1,4 +1,4 @@ -UNBODY_API_KEY= -UNBODY_LPE_PROJECT_ID= -SIMPLECAST_ACCESS_TOKEN= +UNBODY_API_KEY=04A427B28187C872D7ADB2E724E2474E +UNBODY_LPE_PROJECT_ID=0d770f21-dca1-441f-9e32-5cf5058aed9d +SIMPLECAST_ACCESS_TOKEN=eyJhcGlfa2V5IjoiOWR0Yzh0b2lBYkM3ZEdkOW5Nalo4LzJxNW54UUFEbHZvUlVaNjhGdzltMD0ifQ== NEXT_PUBLIC_SITE_URL=https://press.logos.co \ No newline at end of file diff --git a/src/components/Episode/Header/Episode.Header.tsx b/src/components/Episode/Header/Episode.Header.tsx index e8ec748..02f9c57 100644 --- a/src/components/Episode/Header/Episode.Header.tsx +++ b/src/components/Episode/Header/Episode.Header.tsx @@ -2,7 +2,6 @@ import { Tags } from '@/components/Tags' import { Typography } from '@acid-info/lsd-react' import styled from '@emotion/styled' import { LPE } from '../../../types/lpe.types' -import { LogosCircleIcon } from '@/components/Icons/LogosCircleIcon' import EpisodeChannels from './Episode.Channels' import EpisodeStats from '../Episode.Stats' import EpisodePlayer from './Episode.Player' diff --git a/src/components/Episode/Header/Episode.Player.tsx b/src/components/Episode/Header/Episode.Player.tsx index b77d85f..6f829be 100644 --- a/src/components/Episode/Header/Episode.Player.tsx +++ b/src/components/Episode/Header/Episode.Player.tsx @@ -2,10 +2,11 @@ import styled from '@emotion/styled' import ReactPlayer from 'react-player' import { useHookstate } from '@hookstate/core' import { playerState } from '@/components/GlobalAudioPlayer/globalAudioPlayer.state' -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import { episodeState } from '@/components/GlobalAudioPlayer/episode.state' import SimplecastPlayer from './Episode.SimplecastPlayer' import { LPE } from '@/types/lpe.types' +import { useRouter } from 'next/router' export type EpisodePlayerProps = { channel: LPE.Podcast.Channel @@ -20,9 +21,14 @@ const EpisodePlayer = ({ title, showTitle, }: EpisodePlayerProps) => { + const router = useRouter() + const state = useHookstate(playerState) const epState = useHookstate(episodeState) + const playerContainerRef = useRef(null) + const playerRef = useRef(null) + const isSimplecast = channel?.name === LPE.Podcast.ChannelNames.Simplecast const url = @@ -35,16 +41,32 @@ const EpisodePlayer = ({ > ).data.audioFileUrl - const playerContainerRef = useRef(null) - const playerRef = useRef(null) + const keepPlaying = + state.value.url !== url && state.value.isEnabled && state.value.playing + + const [keepGlobalPlay, setKeepGlobalPlay] = useState(keepPlaying) + + useEffect(() => { + if (keepPlaying) { + setKeepGlobalPlay(true) + playerRef.current?.seekTo(0) + } + }, [keepPlaying]) useEffect(() => { const observer = new IntersectionObserver((entries) => { if (entries[0].isIntersecting) { - state.set((prev) => ({ - ...prev, - isEnabled: false, - })) + if (keepPlaying) { + state.set((prev) => ({ + ...prev, + isEnabled: true, + })) + } else { + state.set((prev) => ({ + ...prev, + isEnabled: false, + })) + } } else { state.set((prev) => ({ ...prev, @@ -57,22 +79,32 @@ const EpisodePlayer = ({ return () => { observer.disconnect() } + }, [keepGlobalPlay]) + + useEffect(() => { + const handleLeave = () => { + if (state.value.playing) { + state.set((prev) => ({ + ...prev, + isEnabled: true, + })) + } + } + router.events.on('routeChangeStart', handleLeave) + + return () => { + router.events.off('routeChangeStart', handleLeave) + } }, []) useEffect(() => { epState.set({ - episodeId: 'aaa', title: title, podcast: showTitle, - url: url, + url: url as string, coverImage: coverImage ?? null, }) - - state.set((prev) => ({ - ...prev, - url: url, - })) - }, [url, title, showTitle, coverImage]) + }, [title, showTitle, coverImage]) useEffect(() => { if (!state.value.isEnabled) { @@ -96,7 +128,18 @@ const EpisodePlayer = ({ } const handlePlay = () => { - state.set((prev) => ({ ...prev, playing: true })) + if (keepGlobalPlay) { + setKeepGlobalPlay(false) + state.set((prev) => ({ + ...prev, + isEnabled: false, + played: 0, + url: url, + playing: true, + })) + } else { + state.set((prev) => ({ ...prev, url: url, playing: true })) + } } const handlePause = () => state.set((prev) => ({ ...prev, playing: false })) @@ -108,6 +151,8 @@ const EpisodePlayer = ({ <> {isSimplecast && ( coverImage: LPE.Podcast.Document['coverImage'] handlePlay: () => void @@ -20,6 +16,8 @@ export type SimplecastPlayerProps = { } const SimplecastPlayer = ({ + playing, + played, playerRef, coverImage, handlePlay, @@ -64,8 +62,8 @@ const SimplecastPlayer = ({ console.log('onReady')} - onStart={() => console.log('onStart')} onPlay={handlePlay} onPause={handlePause} - onBuffer={() => console.log('onBuffer')} onPlaybackRateChange={handleOnPlaybackRateChange} - onSeek={(e) => console.log('onSeek', e)} onEnded={handleEnded} - onError={(e) => console.log('onError', e)} onDuration={handleDuration} onProgress={handleProgress} + // onReady={() => console.log('onReady')} + // onStart={() => console.log('onStart')} + // onBuffer={() => console.log('onBuffer')} + // onSeek={(e) => console.log('onSeek', e)} + // onError={(e) => console.log('onError', e)} /> {!!epState.value.coverImage && ( diff --git a/src/components/GlobalAudioPlayer/episode.state.ts b/src/components/GlobalAudioPlayer/episode.state.ts index 11a63e5..8c6063f 100644 --- a/src/components/GlobalAudioPlayer/episode.state.ts +++ b/src/components/GlobalAudioPlayer/episode.state.ts @@ -2,7 +2,6 @@ import { LPE } from '@/types/lpe.types' import { hookstate } from '@hookstate/core' export type EpisodeState = { - episodeId: string title: string podcast: string url: string @@ -10,7 +9,6 @@ export type EpisodeState = { } export const defaultEpisodeState: EpisodeState = { - episodeId: '', title: '', podcast: '', url: '', From c7c91b953063b002602a04193959d36f147ef1bb Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Wed, 23 Aug 2023 16:02:38 +0900 Subject: [PATCH 03/13] feat: implement youtube volume sync --- .env | 4 ---- .../Episode/Header/Episode.Player.tsx | 20 +++++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index 512521c..0000000 --- a/.env +++ /dev/null @@ -1,4 +0,0 @@ -UNBODY_API_KEY=04A427B28187C872D7ADB2E724E2474E -UNBODY_LPE_PROJECT_ID=0d770f21-dca1-441f-9e32-5cf5058aed9d -SIMPLECAST_ACCESS_TOKEN=eyJhcGlfa2V5IjoiOWR0Yzh0b2lBYkM3ZEdkOW5Nalo4LzJxNW54UUFEbHZvUlVaNjhGdzltMD0ifQ== -NEXT_PUBLIC_SITE_URL=https://press.logos.co \ No newline at end of file diff --git a/src/components/Episode/Header/Episode.Player.tsx b/src/components/Episode/Header/Episode.Player.tsx index 6f829be..e451de3 100644 --- a/src/components/Episode/Header/Episode.Player.tsx +++ b/src/components/Episode/Header/Episode.Player.tsx @@ -112,6 +112,21 @@ const EpisodePlayer = ({ } }, [state.value.isEnabled]) + useEffect(() => { + if (channel?.name === LPE.Podcast.ChannelNames.Youtube) { + window.addEventListener('message', function (event) { + if (event.origin == 'https://www.youtube.com') { + const data = JSON.parse(event.data) + const volume = data.info.volume + + if (typeof volume !== 'undefined') { + state.set((prev) => ({ ...prev, volume: volume / 100 })) + } + } + }) + } + }, []) + const handleProgress = (newState: { playedSeconds: number played: number @@ -174,6 +189,11 @@ const EpisodePlayer = ({ onPlay={handlePlay} onPause={handlePause} onDuration={handleDuration} + config={{ + youtube: { + playerVars: { enablejsapi: 1 }, + }, + }} /> From 2de4d1fcbda3f1c3995c587c35b4f77ab950007e Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 03:12:25 +0900 Subject: [PATCH 04/13] fix: fix audio player volumes --- .env | 4 ++++ .gitignore | 2 +- src/components/Episode/Header/Episode.Player.tsx | 9 ++++++--- .../Episode/Header/Episode.SimplecastPlayer.tsx | 9 +++++++-- .../GlobalAudioPlayer/GlobalAudioPlayer.tsx | 7 +++++-- src/components/Icons/MuteIcon/MuteIcon.tsx | 3 ++- src/components/LpePlayer/Controls/Controls.tsx | 15 ++++++++++++--- src/components/LpePlayer/LpeAudioPlayer.tsx | 7 ------- 8 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..facb74b --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +UNBODY_API_KEY= +UNBODY_LPE_PROJECT_ID= +SIMPLECAST_ACCESS_TOKEN= +NEXT_PUBLIC_SITE_URL=https://press.logos.co \ No newline at end of file diff --git a/.gitignore b/.gitignore index fb30cbd..436eb65 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,4 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -.idea +.idea \ No newline at end of file diff --git a/src/components/Episode/Header/Episode.Player.tsx b/src/components/Episode/Header/Episode.Player.tsx index e451de3..3d2f2ec 100644 --- a/src/components/Episode/Header/Episode.Player.tsx +++ b/src/components/Episode/Header/Episode.Player.tsx @@ -116,8 +116,8 @@ const EpisodePlayer = ({ if (channel?.name === LPE.Podcast.ChannelNames.Youtube) { window.addEventListener('message', function (event) { if (event.origin == 'https://www.youtube.com') { - const data = JSON.parse(event.data) - const volume = data.info.volume + const data = JSON.parse(event?.data) + const volume = data?.info?.volume if (typeof volume !== 'undefined') { state.set((prev) => ({ ...prev, volume: volume / 100 })) @@ -167,6 +167,7 @@ const EpisodePlayer = ({ {isSimplecast && ( coverImage: LPE.Podcast.Document['coverImage'] handlePlay: () => void @@ -18,6 +19,7 @@ export type SimplecastPlayerProps = { const SimplecastPlayer = ({ playing, played, + playedSeconds, playerRef, coverImage, handlePlay, @@ -61,14 +63,17 @@ const SimplecastPlayer = ({ - state.set((prev) => ({ ...prev, muted: !prev.muted })) + state.set((prev) => ({ + ...prev, + muted: !prev.muted, + })) } timeTrackProps={{ onValueChange: handleSeekChange, diff --git a/src/components/GlobalAudioPlayer/GlobalAudioPlayer.tsx b/src/components/GlobalAudioPlayer/GlobalAudioPlayer.tsx index 1c1360c..87af732 100644 --- a/src/components/GlobalAudioPlayer/GlobalAudioPlayer.tsx +++ b/src/components/GlobalAudioPlayer/GlobalAudioPlayer.tsx @@ -102,7 +102,10 @@ export default function GlobalAudioPlayer() { - state.set((prev) => ({ ...prev, muted: !prev.muted })), + state.set((prev) => ({ + ...prev, + muted: !prev.muted, + })), duration: state.value.duration, played: state.value.played, muted: state.value.muted, @@ -132,7 +135,7 @@ export default function GlobalAudioPlayer() { loop={state.value.loop} playbackRate={state.value.playbackRate} volume={state.value.volume} - muted={state.value.isEnabled ? false : true} + muted={state.value.muted ? true : state.value.isEnabled ? false : true} onPlay={handlePlay} onPause={handlePause} onPlaybackRateChange={handleOnPlaybackRateChange} diff --git a/src/components/Icons/MuteIcon/MuteIcon.tsx b/src/components/Icons/MuteIcon/MuteIcon.tsx index f3e910a..6f08732 100644 --- a/src/components/Icons/MuteIcon/MuteIcon.tsx +++ b/src/components/Icons/MuteIcon/MuteIcon.tsx @@ -8,10 +8,11 @@ export const MuteIcon = LsdIcon( viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" + {...props} > ), diff --git a/src/components/LpePlayer/Controls/Controls.tsx b/src/components/LpePlayer/Controls/Controls.tsx index 06bf309..e009e3b 100644 --- a/src/components/LpePlayer/Controls/Controls.tsx +++ b/src/components/LpePlayer/Controls/Controls.tsx @@ -48,7 +48,7 @@ export const LpeAudioPlayerControls = (props: LpeAudioPlayerControlsProps) => { {playing ? : } - + / @@ -71,7 +71,11 @@ export const LpeAudioPlayerControls = (props: LpeAudioPlayerControlsProps) => { ) } -const Container = styled.div`` +const Container = styled.div` + display: flex; + flex-direction: column; + gap: 16px; +` const Buttons = styled.div` display: flex; @@ -100,6 +104,7 @@ const PlayPause = styled.button` border: none; background: none; margin-right: 8px; + padding: 0; ` const Row = styled.div` @@ -108,8 +113,12 @@ const Row = styled.div` white-space: pre-wrap; ` -const TimeContainer = styled(Row)` +const TimeContainer = styled(Row)<{ color: string }>` gap: 8px; + + span { + color: ${({ color }) => color || 'black'}; + } ` const Time = styled(Typography)` diff --git a/src/components/LpePlayer/LpeAudioPlayer.tsx b/src/components/LpePlayer/LpeAudioPlayer.tsx index 973a39e..c7dd0ad 100644 --- a/src/components/LpePlayer/LpeAudioPlayer.tsx +++ b/src/components/LpePlayer/LpeAudioPlayer.tsx @@ -1,10 +1,3 @@ -import { PauseIcon } from '@/components/Icons/PauseIcon' -import { PlayIcon } from '@/components/Icons/PlayIcon' -import { convertSecToMinAndSec } from '@/utils/string.utils' -import { Typography } from '@acid-info/lsd-react' -import { MuteIcon } from '@/components/Icons/MuteIcon' -import { VolumeIcon } from '@/components/Icons/VolumeIcon' -import styles from '@/components/GlobalAudioPlayer/GlobalAudioPlayer.module.css' import React from 'react' import styled from '@emotion/styled' import { From eb5a40ba6758a51bba5c32155cc82bbe7352fa40 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 03:13:37 +0900 Subject: [PATCH 05/13] chore: remove .env --- .env | 4 ---- .gitignore | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index facb74b..0000000 --- a/.env +++ /dev/null @@ -1,4 +0,0 @@ -UNBODY_API_KEY= -UNBODY_LPE_PROJECT_ID= -SIMPLECAST_ACCESS_TOKEN= -NEXT_PUBLIC_SITE_URL=https://press.logos.co \ No newline at end of file diff --git a/.gitignore b/.gitignore index 436eb65..29fc8f4 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,5 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -.idea \ No newline at end of file +.idea +.env \ No newline at end of file From 78d42923683f50429bae6f376336f37ba7237ebb Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 03:40:20 +0900 Subject: [PATCH 06/13] style: update simplecast player design --- .../Header/Episode.SimplecastPlayer.tsx | 1 + .../Icons/FullscreenIcon/FullscreenIcon.tsx | 27 +++++++++++++++++++ src/components/Icons/FullscreenIcon/index.ts | 1 + src/components/Icons/MuteIcon/MuteIcon.tsx | 17 +++++++----- .../Icons/VolumeIcon/VolumeIcon.tsx | 22 ++++++++++----- .../LpePlayer/Controls/Controls.tsx | 25 ++++++++++++----- 6 files changed, 73 insertions(+), 20 deletions(-) create mode 100644 src/components/Icons/FullscreenIcon/FullscreenIcon.tsx create mode 100644 src/components/Icons/FullscreenIcon/index.ts diff --git a/src/components/Episode/Header/Episode.SimplecastPlayer.tsx b/src/components/Episode/Header/Episode.SimplecastPlayer.tsx index ee986a7..fd90e24 100644 --- a/src/components/Episode/Header/Episode.SimplecastPlayer.tsx +++ b/src/components/Episode/Header/Episode.SimplecastPlayer.tsx @@ -80,6 +80,7 @@ const SimplecastPlayer = ({ onMouseUp: handleSeekMouseUp, onMouseDown: handleSeekMouseDown, }} + allowFullScreen={true} color={'white'} /> diff --git a/src/components/Icons/FullscreenIcon/FullscreenIcon.tsx b/src/components/Icons/FullscreenIcon/FullscreenIcon.tsx new file mode 100644 index 0000000..ac62645 --- /dev/null +++ b/src/components/Icons/FullscreenIcon/FullscreenIcon.tsx @@ -0,0 +1,27 @@ +import { LsdIcon } from '@acid-info/lsd-react' + +export const FullscreenIcon = LsdIcon( + (props) => ( + + + + + + + + + + + ), + { filled: true }, +) diff --git a/src/components/Icons/FullscreenIcon/index.ts b/src/components/Icons/FullscreenIcon/index.ts new file mode 100644 index 0000000..ed19f1b --- /dev/null +++ b/src/components/Icons/FullscreenIcon/index.ts @@ -0,0 +1 @@ +export * from './FullscreenIcon' diff --git a/src/components/Icons/MuteIcon/MuteIcon.tsx b/src/components/Icons/MuteIcon/MuteIcon.tsx index 6f08732..c0e3c55 100644 --- a/src/components/Icons/MuteIcon/MuteIcon.tsx +++ b/src/components/Icons/MuteIcon/MuteIcon.tsx @@ -3,17 +3,20 @@ import { LsdIcon } from '@acid-info/lsd-react' export const MuteIcon = LsdIcon( (props) => ( - + + + ), { filled: true }, diff --git a/src/components/Icons/VolumeIcon/VolumeIcon.tsx b/src/components/Icons/VolumeIcon/VolumeIcon.tsx index 4916435..f514c6f 100644 --- a/src/components/Icons/VolumeIcon/VolumeIcon.tsx +++ b/src/components/Icons/VolumeIcon/VolumeIcon.tsx @@ -3,16 +3,24 @@ import { LsdIcon } from '@acid-info/lsd-react' export const VolumeIcon = LsdIcon( (props) => ( - + + + + + + + + ), { filled: true }, diff --git a/src/components/LpePlayer/Controls/Controls.tsx b/src/components/LpePlayer/Controls/Controls.tsx index e009e3b..23645c0 100644 --- a/src/components/LpePlayer/Controls/Controls.tsx +++ b/src/components/LpePlayer/Controls/Controls.tsx @@ -11,6 +11,7 @@ import { ControlsTimeTrackProps, TimeTrack, } from '@/components/LpePlayer/Controls/Controls.TimeTrack' +import { FullscreenIcon } from '@/components/Icons/FullscreenIcon' export interface LpeAudioPlayerControlsProps { duration: number @@ -21,7 +22,7 @@ export interface LpeAudioPlayerControlsProps { onPause: () => void onPlay: () => void onVolumeToggle: () => void - + allowFullScreen?: boolean color?: string timeTrackProps: ControlsTimeTrackProps @@ -38,6 +39,7 @@ export const LpeAudioPlayerControls = (props: LpeAudioPlayerControlsProps) => { onPlay, color = 'rgba(var(--lsd-surface-secondary), 1)', onVolumeToggle, + allowFullScreen = false, timeTrackProps: { onValueChange, onMouseDown, onMouseUp }, } = props @@ -46,7 +48,11 @@ export const LpeAudioPlayerControls = (props: LpeAudioPlayerControlsProps) => { - {playing ? : } + {playing ? ( + + ) : ( + + )} @@ -54,9 +60,16 @@ export const LpeAudioPlayerControls = (props: LpeAudioPlayerControlsProps) => { - - {muted ? : } - + + + {muted ? ( + + ) : ( + + )} + + + ` From 9290b9c7a04607413051483954ddd2cc49bb5b36 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 04:07:19 +0900 Subject: [PATCH 07/13] feat: add 404 page --- src/components/NotFound/NotFound.tsx | 45 +++++++++++++++++++ src/components/NotFound/index.ts | 1 + .../NotFoundLayout/NotFound.layout.tsx | 25 +++++++++++ src/layouts/NotFoundLayout/index.ts | 1 + src/pages/404.tsx | 24 ++++++++++ 5 files changed, 96 insertions(+) create mode 100644 src/components/NotFound/NotFound.tsx create mode 100644 src/components/NotFound/index.ts create mode 100644 src/layouts/NotFoundLayout/NotFound.layout.tsx create mode 100644 src/layouts/NotFoundLayout/index.ts create mode 100644 src/pages/404.tsx diff --git a/src/components/NotFound/NotFound.tsx b/src/components/NotFound/NotFound.tsx new file mode 100644 index 0000000..97cb7e9 --- /dev/null +++ b/src/components/NotFound/NotFound.tsx @@ -0,0 +1,45 @@ +import { uiConfigs } from '@/configs/ui.configs' +import { Button, Typography } from '@acid-info/lsd-react' +import styled from '@emotion/styled' +import Link from 'next/link' + +const NotFound = () => { + return ( + + + Page not found + + + Sorry, the page you are looking for doesn’t exist or has been moved. +
+ Try searching our site. +
+ + Go to search + +
+ ) +} + +export default NotFound + +const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + margin-top: calc(120px + ${uiConfigs.navbarRenderedHeight}px); +` + +const Title = styled(Typography)` + margin-bottom: 16px; +` + +const Description = styled(Typography)` + margin-bottom: 48px; + max-width: 510px; + text-align: center; +` + +const SearchButton = styled(Button)` + width: fit-content; +` diff --git a/src/components/NotFound/index.ts b/src/components/NotFound/index.ts new file mode 100644 index 0000000..bdd8d42 --- /dev/null +++ b/src/components/NotFound/index.ts @@ -0,0 +1 @@ +export { default as NotFound } from './NotFound' diff --git a/src/layouts/NotFoundLayout/NotFound.layout.tsx b/src/layouts/NotFoundLayout/NotFound.layout.tsx new file mode 100644 index 0000000..c38c78f --- /dev/null +++ b/src/layouts/NotFoundLayout/NotFound.layout.tsx @@ -0,0 +1,25 @@ +import { Main } from '@/components/Main' +import { NavBarProps } from '@/components/NavBar/NavBar' +import { PropsWithChildren, useMemo } from 'react' +import { MainProps } from '../../components/Main/Main' +import { AppBar } from '../../components/NavBar' + +interface Props { + navbarProps?: NavBarProps + mainProps?: Partial +} + +export default function DefaultLayout(props: PropsWithChildren) { + const { mainProps = {}, navbarProps = {} } = props + const navbarDefaultState = useMemo( + () => navbarProps.defaultState ?? { showTitle: true }, + [navbarProps], + ) + + return ( + <> + +
{props.children}
+ + ) +} diff --git a/src/layouts/NotFoundLayout/index.ts b/src/layouts/NotFoundLayout/index.ts new file mode 100644 index 0000000..898a557 --- /dev/null +++ b/src/layouts/NotFoundLayout/index.ts @@ -0,0 +1 @@ +export { default as DefaultLayout } from './NotFound.layout' diff --git a/src/pages/404.tsx b/src/pages/404.tsx new file mode 100644 index 0000000..1943bc2 --- /dev/null +++ b/src/pages/404.tsx @@ -0,0 +1,24 @@ +import { NotFound } from '@/components/NotFound' +import { SEO } from '@/components/SEO' +import NotFoundLayout from '@/layouts/NotFoundLayout/NotFound.layout' +import { ReactNode } from 'react' + +const NotFoundPage = () => { + return ( + <> + + + + ) +} + +NotFoundPage.getLayout = function getLayout(page: ReactNode) { + return {page} +} + +export default NotFoundPage From a9c5544e26e1d41eb218bd8fba8ac5cf55daf4c4 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 04:14:31 +0900 Subject: [PATCH 08/13] chore: restore .env --- .env | 4 ++++ .gitignore | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..facb74b --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +UNBODY_API_KEY= +UNBODY_LPE_PROJECT_ID= +SIMPLECAST_ACCESS_TOKEN= +NEXT_PUBLIC_SITE_URL=https://press.logos.co \ No newline at end of file diff --git a/.gitignore b/.gitignore index 29fc8f4..fb30cbd 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,3 @@ yarn-error.log* next-env.d.ts .idea -.env \ No newline at end of file From 8d03fb3ce600c8e338807eee9c98e09ff2fdd063 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 20:42:29 +0900 Subject: [PATCH 09/13] chore: remove fullscreen icon --- src/components/LpePlayer/Controls/Controls.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/LpePlayer/Controls/Controls.tsx b/src/components/LpePlayer/Controls/Controls.tsx index 23645c0..079a923 100644 --- a/src/components/LpePlayer/Controls/Controls.tsx +++ b/src/components/LpePlayer/Controls/Controls.tsx @@ -11,7 +11,6 @@ import { ControlsTimeTrackProps, TimeTrack, } from '@/components/LpePlayer/Controls/Controls.TimeTrack' -import { FullscreenIcon } from '@/components/Icons/FullscreenIcon' export interface LpeAudioPlayerControlsProps { duration: number @@ -68,7 +67,6 @@ export const LpeAudioPlayerControls = (props: LpeAudioPlayerControlsProps) => { )} - From f494d610cf12985760d5ffa8056da27cac514f79 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 21:18:15 +0900 Subject: [PATCH 10/13] style: responsiveness for show page --- src/components/Podcasts/PodcastShowCard.tsx | 11 ++++++- src/containers/PodcastShowContainer.tsx | 32 ++++++++++++++------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/components/Podcasts/PodcastShowCard.tsx b/src/components/Podcasts/PodcastShowCard.tsx index 0661a83..e326c0f 100644 --- a/src/components/Podcasts/PodcastShowCard.tsx +++ b/src/components/Podcasts/PodcastShowCard.tsx @@ -21,7 +21,7 @@ export default function PodcastShowCard({ }: PodcastShowCardProps) { return ( - + {show.title} @@ -53,4 +53,13 @@ const ShowData = styled.div` const Description = styled(Typography)` margin-top: 16px; + + @media (min-width: 768px) and (max-width: 1200px) { + margin-top: 12px; + } + + @media (max-width: 768px) { + text-align: center; + margin-top: 8px; + } ` diff --git a/src/containers/PodcastShowContainer.tsx b/src/containers/PodcastShowContainer.tsx index 99cfad2..f78840e 100644 --- a/src/containers/PodcastShowContainer.tsx +++ b/src/containers/PodcastShowContainer.tsx @@ -6,6 +6,8 @@ import { Button, Typography } from '@acid-info/lsd-react' import styled from '@emotion/styled' import { useRecentEpisodes } from '../queries/useRecentEpisodes.query' import { LPE } from '../types/lpe.types' +import { uiConfigs } from '@/configs/ui.configs' +import { useWindowSize } from 'react-use' interface Props { show: LPE.Podcast.Show @@ -15,6 +17,9 @@ interface Props { const PodcastShowContainer = (props: Props) => { const { show, latestEpisodes, highlightedEpisodes } = props + const { width } = useWindowSize() + + const isMobile = width < 768 // TODO : use global breakpoint + use media query if cols is not needed const query = useRecentEpisodes({ limit: 8, @@ -25,11 +30,11 @@ const PodcastShowContainer = (props: Props) => { return ( <> - + - + { /> { ) } -const PodcastsBodyContainer = styled(GridItem)`` +const PodcastsGrid = styled(Grid)` + width: 100%; + margin-top: -15px; // offset for postSectionMargin + + @media (max-width: 768px) { + margin-top: ${uiConfigs.navbarRenderedHeight + 48}px; + } +` + +const PodcastsBodyContainer = styled(GridItem)` + grid-column: span 16; +` const SeeMoreButton = styled(Button)` display: block; @@ -65,10 +81,4 @@ const SeeMoreButton = styled(Button)` margin: 24px auto; ` -const PodcastsGrid = styled(Grid)` - width: 100%; - @media (min-width: 768px) and (max-width: 1200px) { - } -` - export default PodcastShowContainer From b4993f6e95d2361492f6893e15cc0dec706de8fd Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 22:06:11 +0900 Subject: [PATCH 11/13] style: podcasts page responsiveness --- src/components/Podcasts/Podcast.Section.tsx | 5 + src/components/Podcasts/Podcasts.Lists.tsx | 138 ++++++++++++++++---- src/containers/PodcastsContainer.tsx | 21 ++- 3 files changed, 135 insertions(+), 29 deletions(-) diff --git a/src/components/Podcasts/Podcast.Section.tsx b/src/components/Podcasts/Podcast.Section.tsx index 64c608b..5420a19 100644 --- a/src/components/Podcasts/Podcast.Section.tsx +++ b/src/components/Podcasts/Podcast.Section.tsx @@ -13,4 +13,9 @@ export default function PodcastSection({ children, marginTop = 140 }: Props) { const Section = styled.div<{ marginTop: number }>` margin-top: ${(props) => props.marginTop}px; border-top: 1px solid rgb(var(--lsd-border-primary)); + + @media (max-width: 768px) { + margin-top: 80px; + margin-bottom: 80px; + } ` diff --git a/src/components/Podcasts/Podcasts.Lists.tsx b/src/components/Podcasts/Podcasts.Lists.tsx index 66afe48..73031a6 100644 --- a/src/components/Podcasts/Podcasts.Lists.tsx +++ b/src/components/Podcasts/Podcasts.Lists.tsx @@ -1,8 +1,7 @@ import styled from '@emotion/styled' import { LPE } from '../../types/lpe.types' -import { Button, Typography } from '@acid-info/lsd-react' +import { ArrowDownIcon, Badge, Button, Typography } from '@acid-info/lsd-react' import Link from 'next/link' -import PodcastHost from './Podcast.Host' import Image from 'next/image' import { Grid, GridItem } from '../Grid/Grid' @@ -17,27 +16,46 @@ export default function PodcastsLists({ shows }: Props) { shows.map((show) => ( - {show.logo.alt} - {show.title} - - - - - {show.numberOfEpisodes} EP - - - - - - + + + {show.logo.alt} + + {show.title} + + {show.numberOfEpisodes} EP + + + + + + + Podcast page + + + + + + + + {/* @ts-ignore */} + {shows?.tags && ( + + {/* @ts-ignore */} + {show.tags.map((tag) => ( + + {tag} + + ))} + + )} + ))} @@ -50,6 +68,7 @@ const PodcastListsContainer = styled(Grid)` @media (max-width: 768px) { flex-direction: column; + gap: 24px; } ` @@ -62,12 +81,81 @@ const ShowCard = styled.div` border: 1px solid rgb(var(--lsd-text-primary)); ` +const ShowInfoContainer = styled.div` + display: flex; + gap: 8px; +` + +const ShowInfo = styled.div` + display: flex; + flex-direction: column; + gap: 2px; +` + const Row = styled.div` display: flex; gap: 8px; margin-bottom: 16px; ` -const Description = styled(Typography)` - margin-bottom: 16px; +const Top = styled(Row)` + justify-content: space-between; +` + +const Bottom = styled.div` + margin-top: 88px; + + @media (max-width: 768px) { + margin-top: 64px; + } +` + +const Description = styled(Typography)` + font-size: var(--lsd-h6-fontSize); + + @media (max-width: 768px) { + font-size: var(--lsd-body1-fontSize); + } +` + +const ShowButtonLink = styled(Link)` + text-decoration: none; +` + +const ShowButton = styled(Button)` + display: flex; + align-items: center; + padding: 6px 10px 6px 12px; + width: 122px; + height: 28px; + gap: 12px; + + > span { + width: 100%; + display: flex; + align-items: center; + justify-content: space-between; + } + + svg { + transform: rotate(-90deg); + } + + @media (max-width: 768px) { + width: 28px; + height: 28px; + padding: 7px; + } +` + +const ShowButtonText = styled(Typography)` + @media (max-width: 768px) { + display: none; + } +` + +const BadgeContainer = styled.div` + margin-top: 24px; + display: flex; + gap: 8px; ` diff --git a/src/containers/PodcastsContainer.tsx b/src/containers/PodcastsContainer.tsx index 707bd44..eb5e503 100644 --- a/src/containers/PodcastsContainer.tsx +++ b/src/containers/PodcastsContainer.tsx @@ -7,6 +7,9 @@ import { Button, Typography } from '@acid-info/lsd-react' import styled from '@emotion/styled' import Link from 'next/link' import { LPE } from '../types/lpe.types' +import { uiConfigs } from '@/configs/ui.configs' +import { useWindowSize } from 'react-use' +import Image from 'next/image' interface Props { shows: LPE.Podcast.Show[] @@ -16,6 +19,9 @@ interface Props { const PodcastsContainer = (props: Props) => { const { shows, highlightedEpisodes } = props + const { width } = useWindowSize() + const isMobile = width < 768 // TODO : use global breakpoint + use media query if cols is not needed + return ( @@ -23,13 +29,13 @@ const PodcastsContainer = (props: Props) => { Latest Episodes} /> { header={ - + {show.logo.alt} {show.title} @@ -55,6 +66,7 @@ const PodcastsContainer = (props: Props) => { } + cols={isMobile ? 1 : 4} shows={[show]} displayShow={false} episodes={show.episodes as LPE.Podcast.Document[]} @@ -70,7 +82,8 @@ const PodcastsBodyContainer = styled(GridItem)`` const PodcastsGrid = styled(Grid)` width: 100%; - @media (min-width: 768px) and (max-width: 1200px) { + @media (max-width: 768px) { + margin-top: ${uiConfigs.navbarRenderedHeight + 80}px; } ` From 7021dab7468f69642cd2dd126e406ac6dbcf0d0b Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Thu, 24 Aug 2023 23:03:48 +0900 Subject: [PATCH 12/13] style: update episode responsiveness --- src/components/Episode/Episode.Block.tsx | 11 +++-- src/components/Episode/Episode.Body.tsx | 7 +-- .../Episode/Footer/Episode.Credits.tsx | 38 ++++++++++------ .../Episode/Footer/Episode.Footnotes.tsx | 45 +++++++++++-------- .../Episode/Header/Episode.Channels.tsx | 15 +++++-- .../Episode/Header/Episode.Header.tsx | 10 ++--- .../Episode/Header/Episode.Player.tsx | 6 ++- src/containers/EpisodeContainer.tsx | 12 ++--- src/utils/string.utils.ts | 9 ++++ 9 files changed, 97 insertions(+), 56 deletions(-) diff --git a/src/components/Episode/Episode.Block.tsx b/src/components/Episode/Episode.Block.tsx index b352e86..a94ad50 100644 --- a/src/components/Episode/Episode.Block.tsx +++ b/src/components/Episode/Episode.Block.tsx @@ -1,12 +1,12 @@ import { extractClassFromFirstTag, extractIdFromFirstTag, - extractInnerHtml, } from '@/utils/html.utils' import { Typography } from '@acid-info/lsd-react' import styled from '@emotion/styled' import ReactPlayer from 'react-player' import { LPE } from '../../types/lpe.types' +import { parseText, parseTimestamp } from '@/utils/string.utils' export const RenderEpisodeBlock = ({ block, @@ -24,19 +24,24 @@ export const RenderEpisodeBlock = ({ ) : ( + {parseTimestamp(block.text)} + > + {parseText(block.text)} + ) } const TranscriptionItem = styled.div` + display: flex; + flex-direction: column; + gap: var(--lsd-body2-lineHeight); margin-bottom: calc(var(--lsd-body2-lineHeight) * 2); ` diff --git a/src/components/Episode/Episode.Body.tsx b/src/components/Episode/Episode.Body.tsx index 6f8f93e..980547b 100644 --- a/src/components/Episode/Episode.Body.tsx +++ b/src/components/Episode/Episode.Body.tsx @@ -5,6 +5,7 @@ import EpisodeHeader from './Header/Episode.Header' import EpisodeTranscript from './Episode.Transcript' import { playerState } from '../GlobalAudioPlayer/globalAudioPlayer.state' import { useHookstate } from '@hookstate/core' +import { uiConfigs } from '@/configs/ui.configs' interface Props { episode: LPE.Podcast.Document @@ -39,9 +40,9 @@ const EpisodeContainer = styled.article` display: flex; position: relative; flex-direction: column; - gap: 16px; - max-width: 700px; + max-width: 696px; - @media (min-width: 768px) and (max-width: 1200px) { + @media (max-width: 768px) { + margin-top: ${uiConfigs.navbarRenderedHeight - 16}px; } ` diff --git a/src/components/Episode/Footer/Episode.Credits.tsx b/src/components/Episode/Footer/Episode.Credits.tsx index d29f3e4..59c9be0 100644 --- a/src/components/Episode/Footer/Episode.Credits.tsx +++ b/src/components/Episode/Footer/Episode.Credits.tsx @@ -17,17 +17,19 @@ const EpisodeCredits = ({ open={open} onChange={() => setOpen((prev) => !prev)} > - {credits?.map((credit, idx) => ( - - - {credit.text} - - - ))} + + {credits?.map((credit, idx) => ( + + + {credit.text} + + + ))} + ) : null @@ -41,10 +43,18 @@ const Container = styled.div` } ` -const Reference = styled.div` +const Credits = styled.div` display: flex; - padding: 8px 14px; - gap: 8px; + flex-direction: column; + justify-content: center; + gap: var(--lsd-body3-lineHeight); + padding: 12px 14px; +` + +const Credit = styled.div` + display: flex; + flex-direction: flex; + align-items: center; ` export default EpisodeCredits diff --git a/src/components/Episode/Footer/Episode.Footnotes.tsx b/src/components/Episode/Footer/Episode.Footnotes.tsx index 28d5fce..b9d56f6 100644 --- a/src/components/Episode/Footer/Episode.Footnotes.tsx +++ b/src/components/Episode/Footer/Episode.Footnotes.tsx @@ -17,20 +17,22 @@ const EpisodeFootnotes = ({ open={open} onChange={() => setOpen((prev) => !prev)} > - {footnotes.map((footnote, idx) => ( - - - {footnote.refValue} - -

- - ))} + + {footnotes.map((footnote, idx) => ( + + + {footnote.refValue} + +

+ + ))} + ) : null @@ -44,11 +46,18 @@ const Container = styled.div` } ` -const Reference = styled.div` +const Footnotes = styled.div` display: flex; - align-items: center; - padding: 8px 14px; - gap: 8px; + flex-direction: column; + justify-content: center; + gap: var(--lsd-body3-lineHeight); + padding: 12px 14px; +` + +const Footnote = styled.div` + display: flex; + flex-direction: flex; + align-items: baseline; ` const P = styled.p` diff --git a/src/components/Episode/Header/Episode.Channels.tsx b/src/components/Episode/Header/Episode.Channels.tsx index 3a38b1b..7544b68 100644 --- a/src/components/Episode/Header/Episode.Channels.tsx +++ b/src/components/Episode/Header/Episode.Channels.tsx @@ -16,21 +16,21 @@ const renderChannel = (channel: LPE.Podcast.Channel) => { return ( - Spotify + Spotify ) case LPE.Podcast.ChannelNames.ApplePodcasts: return ( - Apple Podcasts + Apple Podcasts ) case LPE.Podcast.ChannelNames.GooglePodcasts: return ( - Google Podcasts + Google Podcasts ) default: @@ -53,7 +53,7 @@ const EpisodeChannelContainer = styled.header` margin-top: 32px; @media (max-width: 768px) { - padding-top: 32px; + margin-top: 24px; } ` @@ -64,4 +64,11 @@ const Channel = styled(Link)` text-decoration: none; ` +const ChannelName = styled(Typography)` + @media (max-width: 768px) { + font-size: var(--lsd-body3-fontSize) !important; + line-height: var(--lsd-body3-lineHeight) !important; + } +` + export default EpisodeChannels diff --git a/src/components/Episode/Header/Episode.Header.tsx b/src/components/Episode/Header/Episode.Header.tsx index 02f9c57..a9732d9 100644 --- a/src/components/Episode/Header/Episode.Header.tsx +++ b/src/components/Episode/Header/Episode.Header.tsx @@ -69,10 +69,6 @@ const EpisodeHeader = ({ const EpisodeHeaderContainer = styled.header` display: flex; flex-direction: column; - - @media (max-width: 768px) { - padding-top: 32px; - } ` const CustomTypography = styled(Typography)` @@ -85,6 +81,8 @@ const EpisodeTitle = styled(Typography)` margin-bottom: 16px; @media (max-width: 768px) { margin-bottom: 8px; + font-size: var(--lsd-h4-fontSize) !important; + line-height: var(--lsd-h4-lineHeight) !important; } ` @@ -92,7 +90,9 @@ const EpisodeSubtitle = styled(CustomTypography)` margin-top: 32px; @media (max-width: 768px) { - font-size: var(--lsd-subtitle1-fontSize); + font-size: var(--lsd-subtitle1-fontSize) !important; + line-height: var(--lsd-subtitle1-lineHeight) !important; + margin-top: 24px; } ` diff --git a/src/components/Episode/Header/Episode.Player.tsx b/src/components/Episode/Header/Episode.Player.tsx index 3d2f2ec..3d14afb 100644 --- a/src/components/Episode/Header/Episode.Player.tsx +++ b/src/components/Episode/Header/Episode.Player.tsx @@ -207,7 +207,7 @@ const PlayerContainer = styled.div<{ isAudio: boolean }>` margin-bottom: ${(props) => (props.isAudio ? '0' : '32px')}; position: relative; padding-bottom: ${(props) => (props.isAudio ? '0' : '56.25%')}; - padding-top: 30px; + padding-top: 32px; height: 0; overflow: hidden; @@ -220,6 +220,10 @@ const PlayerContainer = styled.div<{ isAudio: boolean }>` width: 100%; height: 100%; } + + @media (max-width: 768px) { + padding-top: 24px; + } ` export default EpisodePlayer diff --git a/src/containers/EpisodeContainer.tsx b/src/containers/EpisodeContainer.tsx index 4a8b5ef..be9e797 100644 --- a/src/containers/EpisodeContainer.tsx +++ b/src/containers/EpisodeContainer.tsx @@ -13,11 +13,11 @@ const EpisodeContainer = (props: Props) => { return ( - + - + ) } @@ -26,14 +26,10 @@ const EpisodeBodyContainer = styled(GridItem)`` const EpisodeGrid = styled(Grid)` width: 100%; + margin-top: -47px; // offset for uiConfig.postSectionMargin + @media (min-width: 768px) and (max-width: 1200px) { } ` -const Gap = styled(GridItem)` - @media (max-width: 550px) { - display: none; - } -` - export default EpisodeContainer diff --git a/src/utils/string.utils.ts b/src/utils/string.utils.ts index fcd3f28..c9026a9 100644 --- a/src/utils/string.utils.ts +++ b/src/utils/string.utils.ts @@ -65,3 +65,12 @@ export function convertToIframe(url: string) { return `` } + +export function parseText(text: string) { + return text.replace(/^\d{2}:\d{2}\s|\[\d+\]/g, '') +} + +export function parseTimestamp(text: string) { + const time = text.match(/^\d{2}:\d{2}/g) + return time ? time[0] : '' +} From 1498382776ca3f55e96e9fb99a95f742f6e848e8 Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 25 Aug 2023 00:08:06 +0330 Subject: [PATCH 13/13] refactor: use PostsGrid for rendering related episodes --- .../Footer/Episode.RelatedEpisodes.tsx | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/components/Episode/Footer/Episode.RelatedEpisodes.tsx b/src/components/Episode/Footer/Episode.RelatedEpisodes.tsx index 901a312..d73769f 100644 --- a/src/components/Episode/Footer/Episode.RelatedEpisodes.tsx +++ b/src/components/Episode/Footer/Episode.RelatedEpisodes.tsx @@ -1,9 +1,8 @@ +import { LPE } from '@/types/lpe.types' import { Button, Typography } from '@acid-info/lsd-react' import styled from '@emotion/styled' import { useState } from 'react' -import { LPE } from '@/types/lpe.types' -import { PostCard } from '@/components/PostCard' -import { Grid, GridItem } from '@/components/Grid/Grid' +import { PostsGrid } from '../../PostsGrid' type props = { podcastSlug: string @@ -24,18 +23,25 @@ const RelatedEpisodes = ({ podcastSlug, relatedEpisodes }: props) => { return ( More Episodes - - {relatedEpisodes.slice(0, showIndex).map((episode, idx: number) => ( - - - - ))} - + {relatedEpisodes?.length > 4 && ( {showMore ? 'Show less' : 'Show more'} @@ -53,17 +59,9 @@ const Container = styled.div` flex-direction: column; ` -const EpisodeCards = styled(Grid)` - gap: 0 16px; -` - const ShowButton = styled(Button)` height: 40px; margin-top: 24px; ` -const PostCardContainer = styled(GridItem)` - padding-top: 24px; -` - export default RelatedEpisodes