refac to put data handling on server
This commit is contained in:
parent
6d2090eea9
commit
be6aa96e1b
10
index.js
10
index.js
@ -1,16 +1,19 @@
|
|||||||
import { h, render } from 'preact'
|
import { h, render } from 'preact'
|
||||||
import { useState } from 'preact/hooks'
|
import { useState } from 'preact/hooks'
|
||||||
|
import { ThemeProvider } from 'styled-components'
|
||||||
import { BrowserRouter, Route, Switch } from 'react-router-dom'
|
import { BrowserRouter, Route, Switch } from 'react-router-dom'
|
||||||
|
|
||||||
import Main from './app'
|
import Main from './app'
|
||||||
import SeriesPage from './src/pages/SeriesPage'
|
import SeriesPage from './src/pages/SeriesPage'
|
||||||
import { useEventApi, useEventCalendar } from './src/hooks/data'
|
import { useEventApi, useEventCalendar } from './src/hooks/data'
|
||||||
|
import { useTheme } from './src/store'
|
||||||
import { useTimeout } from './src/hooks/timerHooks'
|
import { useTimeout } from './src/hooks/timerHooks'
|
||||||
import LoaderLayout from './src/pages/LoaderLayout'
|
import LoaderLayout from './src/pages/LoaderLayout'
|
||||||
import FourOhFour from './src/pages/404'
|
import FourOhFour from './src/pages/404'
|
||||||
import Series from './src/pages/Series'
|
import Series from './src/pages/Series'
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
const { theme } = useTheme((store) => store)
|
||||||
const { data: calData, calLoading } = useEventCalendar()
|
const { data: calData, calLoading } = useEventCalendar()
|
||||||
const { data: seriesDataArray, loading: eventsLoading } = useEventApi()
|
const { data: seriesDataArray, loading: eventsLoading } = useEventApi()
|
||||||
const [minLoadTimePassed, setMinTimeUp] = useState(false)
|
const [minLoadTimePassed, setMinTimeUp] = useState(false)
|
||||||
@ -22,7 +25,9 @@ const App = () => {
|
|||||||
|
|
||||||
const seriesData = Object.values(seriesDataArray)
|
const seriesData = Object.values(seriesDataArray)
|
||||||
|
|
||||||
return calLoading || eventsLoading || !minLoadTimePassed ? (
|
return (
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
|
{calLoading || eventsLoading || !minLoadTimePassed ? (
|
||||||
<LoaderLayout />
|
<LoaderLayout />
|
||||||
) : (
|
) : (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
@ -38,7 +43,8 @@ const App = () => {
|
|||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)
|
)}
|
||||||
|
</ThemeProvider>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,66 +1,80 @@
|
|||||||
import { h } from 'preact'
|
import { h } from 'preact'
|
||||||
import { Link as ReactLink } from 'react-router-dom'
|
import { Link as ReactLink } from 'react-router-dom'
|
||||||
import { RightBox, StyledRow as Row, Modal } from './styles'
|
import { RightBox, StyledRow as Row, Modal, PositionedCross as CrossSvg } from './styles'
|
||||||
import { ImageLogo } from '../Logo'
|
import { ImageLogo } from '../Logo'
|
||||||
import { useWindowSize } from '../../hooks/dom'
|
import { useWindowSize } from '../../hooks/dom'
|
||||||
import Link from '../Link'
|
import Link from '../Link'
|
||||||
import { Span } from '../Text'
|
import { Span } from '../Text'
|
||||||
import CrossSvg from '../Svg/Cross'
|
|
||||||
|
|
||||||
import navigation from '../../data/navigation'
|
import navigation from '../../data/navigation'
|
||||||
import { colours, screenSizes, textSizes } from '../../assets/theme'
|
import { colours, screenSizes, textSizes } from '../../assets/theme'
|
||||||
import { useToggle } from '../../hooks/utility'
|
import { useTheme, useUiStore } from '../../store'
|
||||||
|
|
||||||
const Navigation = ({ theme = {}, lang = 'en', headerTheme }) => navigation[lang].map(navItem => (
|
const Navigation = ({ theme = {}, lang = 'en', miniHeader, toggleMobileMenu }) => navigation[lang].map(navItem => (
|
||||||
<Link
|
<Link
|
||||||
navLink
|
navLink
|
||||||
to={navItem.to}
|
to={navItem.to}
|
||||||
href={navItem.href}
|
href={navItem.href}
|
||||||
|
onClick={toggleMobileMenu}
|
||||||
textProps={{
|
textProps={{
|
||||||
size: textSizes.xl,
|
size: textSizes.xl,
|
||||||
colour: headerTheme.foreground || theme.foreground || colours.rose
|
colour: miniHeader ? theme.background : theme.foreground || colours.rose
|
||||||
}}>
|
}}>
|
||||||
{navItem.label}
|
{navItem.label}
|
||||||
</Link>
|
</Link>
|
||||||
))
|
))
|
||||||
|
|
||||||
const NavigationModal = ({ theme = {}, lang = 'en', headerTheme, toggleMenuOpen, ...rest }) => (
|
export const NavigationModal = ({ theme = {}, lang = 'en', headerTheme, ...rest }) => {
|
||||||
<Modal theme={theme} {...rest}>
|
const { toggleMobileMenu } = useUiStore(store => store)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal {...rest}>
|
||||||
<ReactLink to="/">
|
<ReactLink to="/">
|
||||||
<ImageLogo />
|
<ImageLogo />
|
||||||
</ReactLink>
|
</ReactLink>
|
||||||
<CrossSvg size={32} colour={theme.foreground} onClick={toggleMenuOpen} />
|
<CrossSvg size={32} colour={theme.foreground} onClick={toggleMobileMenu} />
|
||||||
<div>
|
<div>
|
||||||
<Navigation theme={theme} lang={lang} headerTheme={theme} {...rest} />
|
<Navigation theme={theme} lang={lang} headerTheme={theme} toggleMobileMenu={toggleMobileMenu} {...rest} />
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const FullHeader = ({ theme = {}, headerTheme = {}, lang = 'en', miniHeader, isMobile, toggleMenuOpen, ...rest }) => (
|
const FullHeader = ({ theme = {}, lang = 'en', miniHeader, isMobile, ...rest }) => (
|
||||||
<Row theme={headerTheme} align="center" justify="space-between" miniHeader={miniHeader} {...rest}>
|
<Row align="center" justify="space-between" miniHeader={miniHeader} {...rest}>
|
||||||
{!miniHeader ? <ReactLink to="/">
|
{!miniHeader ? <ReactLink to="/">
|
||||||
<ImageLogo />
|
<ImageLogo />
|
||||||
</ReactLink> : null}
|
</ReactLink> : null}
|
||||||
{!isMobile ? (
|
{!isMobile ? (
|
||||||
<RightBox as="nav">
|
<RightBox as="nav">
|
||||||
<Navigation theme={theme} lang={lang} headerTheme={headerTheme} {...rest} />
|
<Navigation theme={theme} lang={lang} miniHeader={miniHeader} {...rest} />
|
||||||
</RightBox>
|
</RightBox>
|
||||||
) : <Span onClick={toggleMenuOpen} size={textSizes.xl} colour={headerTheme.foreground || theme.foreground || colours.rose} fontFamily="Lunchtype24"
|
) : <MobileMenuToggle miniHeader={miniHeader} />}
|
||||||
>Menu</Span>}
|
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const MobileMenuToggle = ({ miniHeader, ...props }) => {
|
||||||
|
const { toggleMobileMenu } = useUiStore(store => store)
|
||||||
|
const { theme } = useTheme(store => store)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Span
|
||||||
|
onClick={toggleMobileMenu}
|
||||||
|
size={textSizes.xl}
|
||||||
|
colour={miniHeader ? theme.background : theme.foreground || colours.rose}
|
||||||
|
fontFamily="Lunchtype24"
|
||||||
|
{...props}
|
||||||
|
> Menu</Span>)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Header = ({ miniHeader, theme, ...rest }) => {
|
const Header = ({ miniHeader, theme, ...rest }) => {
|
||||||
const headerTheme = { foreground: theme.background, background: 'transparent', }
|
|
||||||
const { width: screenWidth } = useWindowSize()
|
const { width: screenWidth } = useWindowSize()
|
||||||
const [menuOpen, toggleMenuOpen] = useToggle(false)
|
const { menuOpen } = useUiStore(store => store)
|
||||||
const isMobile = screenWidth < screenSizes.lg
|
const isMobile = screenWidth < screenSizes.lg
|
||||||
|
|
||||||
if (menuOpen) return <NavigationModal toggleMenuOpen={toggleMenuOpen} theme={theme} headerTheme={headerTheme} {...rest} />
|
return <FullHeader menuOpen={menuOpen} miniHeader={miniHeader} isMobile={isMobile} theme={theme} {...rest} />
|
||||||
|
|
||||||
return <FullHeader toggleMenuOpen={toggleMenuOpen} menuOpen={menuOpen} miniHeader={miniHeader} isMobile={isMobile} theme={theme} headerTheme={headerTheme} {...rest} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Header
|
export default Header
|
||||||
|
@ -7,7 +7,7 @@ import CrossSvg from '../Svg/Cross'
|
|||||||
export const StyledRow = styled(Row)`
|
export const StyledRow = styled(Row)`
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
background-color: ${({ theme }) => theme.background};
|
background-color: transparent;
|
||||||
color: ${({ theme }) => theme.foreground};
|
color: ${({ theme }) => theme.foreground};
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: ${({ miniHeader }) => miniHeader ? 'initial' : '0'};
|
left: ${({ miniHeader }) => miniHeader ? 'initial' : '0'};
|
||||||
@ -71,6 +71,7 @@ export const Modal = styled.div`
|
|||||||
`
|
`
|
||||||
export const PositionedCross = styled(CrossSvg)`
|
export const PositionedCross = styled(CrossSvg)`
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 1em;
|
right: 2.5em;
|
||||||
top: 1em;
|
top: 2em;
|
||||||
|
cursor: pointer;
|
||||||
`
|
`
|
@ -3,7 +3,7 @@ import { Link } from 'react-router-dom'
|
|||||||
import { colours } from '../../assets/theme'
|
import { colours } from '../../assets/theme'
|
||||||
|
|
||||||
export const RRLink = styled(Link)`
|
export const RRLink = styled(Link)`
|
||||||
color: ${props => { console.log({ col: props.$colour }); return props.$colour || colours.highlight }};
|
color: ${props => props.$colour || colours.highlight};
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
${props => props.$navLink ? `
|
${props => props.$navLink ? `
|
||||||
font-family: Lunchtype24;
|
font-family: Lunchtype24;
|
||||||
|
@ -99,7 +99,7 @@ export const useEventCalendar = () => {
|
|||||||
|
|
||||||
|
|
||||||
export const useEventApi = () => {
|
export const useEventApi = () => {
|
||||||
const [series, setSeries] = useSeriesStore(store => [store.series, store.setSeries])
|
const [series, episodes, setSeries, setEpisodes] = useSeriesStore(store => [store.series, store.episodes, store.setSeries, store.setEpisodes])
|
||||||
const [loading, setLoading] = useState(!!series.length)
|
const [loading, setLoading] = useState(!!series.length)
|
||||||
|
|
||||||
|
|
||||||
@ -112,6 +112,9 @@ export const useEventApi = () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
setSeries(responseData)
|
setSeries(responseData)
|
||||||
|
// setEpisodes()
|
||||||
|
|
||||||
|
// console.log({ episodes })
|
||||||
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,10 @@ export const LoaderWrapper = styled.div`
|
|||||||
export const Content = styled.div`
|
export const Content = styled.div`
|
||||||
padding-top: 80px;
|
padding-top: 80px;
|
||||||
|
|
||||||
|
@media screen and (max-width: ${screenSizes.md}px) {
|
||||||
|
padding-top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
img.img-logo {
|
img.img-logo {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
mix-blend-mode: exclusion;
|
mix-blend-mode: exclusion;
|
||||||
@ -122,6 +126,10 @@ export const PositionedLink = styled(Link)`
|
|||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
mix-blend-mode: exclusion;
|
mix-blend-mode: exclusion;
|
||||||
padding: 0.5em 2em 0;
|
padding: 0.5em 2em 0;
|
||||||
|
|
||||||
|
@media screen and (max-width: ${screenSizes.md}px) {
|
||||||
|
padding-left: 1em
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -1,14 +1,27 @@
|
|||||||
import { Fragment, h } from 'preact'
|
import { Fragment, h } from 'preact'
|
||||||
import PropTypes, { oneOfType, shape, string } from 'prop-types'
|
import PropTypes, { oneOfType, shape, string } from 'prop-types'
|
||||||
|
import { useEffect } from 'preact/hooks'
|
||||||
|
|
||||||
import SEO from '../../components/Seo'
|
import SEO from '../../components/Seo'
|
||||||
|
|
||||||
import Header from '../../components/Header'
|
import Header, { NavigationModal as MenuModal } from '../../components/Header'
|
||||||
import { capitaliseFirstLetter } from '../../helpers/string'
|
import { capitaliseFirstLetter } from '../../helpers/string'
|
||||||
import { defaultTheme } from '../../assets/theme'
|
import { defaultTheme } from '../../assets/theme'
|
||||||
import { ThemedBlock } from './styles'
|
import { ThemedBlock } from './styles'
|
||||||
|
import { useTheme, useUiStore } from '../../store'
|
||||||
|
|
||||||
const Page = ({ children, title = '', description, metaImg, backTo, noindex, withHeader = true, theme = defaultTheme }) => (
|
const Page = ({ children, title = '', description, metaImg, backTo, noindex, withHeader = true, theme = defaultTheme }) => {
|
||||||
|
const { setTheme } = useTheme(store => store)
|
||||||
|
const { mobileMenuOpen: menuOpen, toggleMenuOpen } = useUiStore(store => store)
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (theme) {
|
||||||
|
setTheme(theme)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SEO
|
<SEO
|
||||||
title={title.toLowerCase() === 'index' ? title : capitaliseFirstLetter(title)}
|
title={title.toLowerCase() === 'index' ? title : capitaliseFirstLetter(title)}
|
||||||
@ -17,11 +30,13 @@ const Page = ({ children, title = '', description, metaImg, backTo, noindex, wit
|
|||||||
noindex={noindex}
|
noindex={noindex}
|
||||||
/>
|
/>
|
||||||
{withHeader ? <Header theme={theme} /> : null}
|
{withHeader ? <Header theme={theme} /> : null}
|
||||||
|
{menuOpen ? <MenuModal theme={theme} toggleMenuOpen={toggleMenuOpen} /> : null}
|
||||||
<ThemedBlock theme={theme} withHeader={withHeader}>
|
<ThemedBlock theme={theme} withHeader={withHeader}>
|
||||||
{children}
|
{children}
|
||||||
</ThemedBlock>
|
</ThemedBlock>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Page.propTypes = {
|
Page.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* eslint-disable react/prop-types */
|
/* eslint-disable react/prop-types */
|
||||||
import { h, Fragment } from 'preact'
|
import { h, Fragment } from 'preact'
|
||||||
|
import { useEffect } from 'preact/hooks'
|
||||||
import striptags from 'striptags'
|
import striptags from 'striptags'
|
||||||
|
|
||||||
import { H1 } from '../../components/Text'
|
import { H1 } from '../../components/Text'
|
||||||
@ -18,8 +19,11 @@ import {
|
|||||||
|
|
||||||
import Page from '../../layouts/Page'
|
import Page from '../../layouts/Page'
|
||||||
import { splitArray } from '../../helpers/utils'
|
import { splitArray } from '../../helpers/utils'
|
||||||
|
import { defaultTheme } from '../../assets/theme'
|
||||||
|
|
||||||
const SeriesPage = ({ data }) => {
|
const SeriesPage = ({ data }) => {
|
||||||
|
const theme = data.theme || defaultTheme
|
||||||
|
|
||||||
const credits = data.credits ? `
|
const credits = data.credits ? `
|
||||||
## Credits
|
## Credits
|
||||||
${data.credits}
|
${data.credits}
|
||||||
@ -43,12 +47,12 @@ const SeriesPage = ({ data }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title={data.title} theme={data.theme} withHeader={false}>
|
<Page title={data.title} theme={data.theme} withHeader={false}>
|
||||||
<InfoLayout title={data.title} subtitle={data.subtitle} image={data.image} theme={data.theme}>
|
<InfoLayout title={data.title} subtitle={data.subtitle} image={data.image} theme={theme}>
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<InfoContent>
|
<InfoContent>
|
||||||
<H1>{data.title}:</H1>
|
<H1>{data.title}:</H1>
|
||||||
<H1>{data.subtitle}</H1>
|
<H1>{data.subtitle}</H1>
|
||||||
{data.description ? <Markdown withLinebreaks theme={data.theme}>{data.description}</Markdown> : null}
|
{data.description ? <Markdown withLinebreaks theme={theme}>{data.description}</Markdown> : null}
|
||||||
|
|
||||||
{data.trailer ? (
|
{data.trailer ? (
|
||||||
<TrailerContainer>
|
<TrailerContainer>
|
||||||
@ -75,7 +79,7 @@ const SeriesPage = ({ data }) => {
|
|||||||
<Title>{translations.en.program}:</Title>
|
<Title>{translations.en.program}:</Title>
|
||||||
{data.episodes.future.map(feeditem => (
|
{data.episodes.future.map(feeditem => (
|
||||||
<EpisodeCard
|
<EpisodeCard
|
||||||
theme={data.theme}
|
theme={theme}
|
||||||
key={feeditem.start}
|
key={feeditem.start}
|
||||||
tzShort={tzShort}
|
tzShort={tzShort}
|
||||||
{...feeditem}
|
{...feeditem}
|
||||||
@ -88,7 +92,7 @@ const SeriesPage = ({ data }) => {
|
|||||||
<Title>Past streams:</Title>
|
<Title>Past streams:</Title>
|
||||||
{data.episodes.past.map(feeditem => (
|
{data.episodes.past.map(feeditem => (
|
||||||
<EpisodeCard
|
<EpisodeCard
|
||||||
theme={data.theme}
|
theme={theme}
|
||||||
key={feeditem.beginsOn}
|
key={feeditem.beginsOn}
|
||||||
hasPassed
|
hasPassed
|
||||||
onClickButton={() => null} // todo: fix this
|
onClickButton={() => null} // todo: fix this
|
||||||
@ -99,7 +103,7 @@ const SeriesPage = ({ data }) => {
|
|||||||
) : null}
|
) : null}
|
||||||
{credits ? <InfoContent>
|
{credits ? <InfoContent>
|
||||||
<Title>Credits</Title>
|
<Title>Credits</Title>
|
||||||
<Markdown theme={data.theme}>{credits}</Markdown>
|
<Markdown theme={theme}>{credits}</Markdown>
|
||||||
</InfoContent> : null}
|
</InfoContent> : null}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
export const getMetadataByKey = (episode, key, firstItem = true) => {
|
|
||||||
const filteredItems = episode.metadata.length ? episode.metadata.filter(
|
|
||||||
meta => meta.key.includes(key)
|
|
||||||
) : null
|
|
||||||
|
|
||||||
if (filteredItems) {
|
|
||||||
return firstItem ? filteredItems[0].value : filteredItems
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getPostByKey = (posts, key) => {
|
|
||||||
const filteredPostItems = posts.elements.length ? posts.elements.filter(post => post.title === key) : []
|
|
||||||
return filteredPostItems.length ? filteredPostItems[0].body : null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getResourcesByKey = (resources, key, lookup = 'title') => {
|
|
||||||
const filteredResources = resources.elements.length ? resources.elements.filter(resource => resource[lookup].includes(key)) : []
|
|
||||||
|
|
||||||
if (!filteredResources.length) return null
|
|
||||||
|
|
||||||
return filteredResources
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getPeertubeIDfromUrl = (string) => string && string.includes('https://tv.undersco.re') ? string.split('/').pop() : string
|
|
||||||
|
|
||||||
export const getEpisodeCode = (episode) => {
|
|
||||||
const metaItems = getMetadataByKey(episode, 'mz:plain:', false)
|
|
||||||
if (metaItems && metaItems.length) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'TODO'
|
|
||||||
}
|
|
@ -1,56 +1,26 @@
|
|||||||
import create from 'zustand'
|
import create from 'zustand'
|
||||||
import striptags from 'striptags'
|
import { defaultTheme } from '../assets/theme'
|
||||||
import { isFuture, isPast } from 'date-fns'
|
|
||||||
import { slugify } from '../helpers/string'
|
|
||||||
import { getMetadataByKey, getPostByKey, getResourcesByKey, getPeertubeIDfromUrl, getEpisodeCode } from './helpers'
|
|
||||||
import { colours, defaultTheme } from '../assets/theme'
|
|
||||||
|
|
||||||
export const [useSeriesStore] = create(set => ({
|
export const useSeriesStore = create((set, get) => ({
|
||||||
series: [],
|
series: [],
|
||||||
|
episodes: [],
|
||||||
setSeries: seriesArray => {
|
setSeries: series => set({ series }),
|
||||||
const allSeries = seriesArray.map(({ name, organizedEvents, posts, resources, banner, summary, members }) => {
|
setEpisodes: () => {
|
||||||
|
if (get().series) {
|
||||||
|
set({
|
||||||
const allEpisodes = organizedEvents.elements.length ? organizedEvents.elements.map(ep => ({
|
episodes: get().series.map(series => series.episodes)
|
||||||
title: ep.title,
|
|
||||||
beginsOn: ep.beginsOn,
|
|
||||||
endsOn: ep.endsOn,
|
|
||||||
description: ep.description,
|
|
||||||
media: ep.media,
|
|
||||||
image: ep.picture ? ep.picture.url : null,
|
|
||||||
peertubeId: getPeertubeIDfromUrl(getMetadataByKey(ep, 'peertube:url')),
|
|
||||||
code: getEpisodeCode(ep)
|
|
||||||
})) : []
|
|
||||||
|
|
||||||
const trailer = getResourcesByKey(resources, 'SERIES_TRAILER')?.[0]?.resourceUrl ?? null
|
|
||||||
const theme = striptags(getPostByKey(posts, 'THEME'))
|
|
||||||
const orgLinks = getResourcesByKey(resources, 'ORG_LINK:')?.map(link => link.title)
|
|
||||||
|
|
||||||
console.log({ orgLinks })
|
|
||||||
|
|
||||||
|
|
||||||
const series = {
|
|
||||||
title: name,
|
|
||||||
subtitle: striptags(summary),
|
|
||||||
description: getPostByKey(posts, 'SERIES_INFO'),
|
|
||||||
posts: posts.elements,
|
|
||||||
resources: resources.elements,
|
|
||||||
image: banner ? banner.url : '',
|
|
||||||
episodes: {
|
|
||||||
future: allEpisodes.filter(ep => isFuture(new Date(ep.endsOn))).sort((a, b) => new Date(a.beginsOn) - new Date(b.beginsOn)),
|
|
||||||
past: allEpisodes.filter(ep => isPast(new Date(ep.endsOn))).sort((a, b) => new Date(a.beginsOn) - new Date(b.beginsOn))
|
|
||||||
},
|
|
||||||
slug: slugify(name),
|
|
||||||
credits: getPostByKey(posts, 'SERIES_CREDITS'),
|
|
||||||
trailer,
|
|
||||||
links: getResourcesByKey(resources, 'SERIES_LINK') || [],
|
|
||||||
theme: theme ? JSON.parse(theme) : defaultTheme,
|
|
||||||
hosts: members.elements.filter(({ actor }) => actor.name !== 'streamappbot')
|
|
||||||
}
|
|
||||||
return series
|
|
||||||
})
|
})
|
||||||
|
} else set({})
|
||||||
set({ series: allSeries })
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
export const [useTheme] = create(set => ({
|
||||||
|
theme: defaultTheme,
|
||||||
|
setTheme: (theme) => set({ theme }),
|
||||||
|
setDefaultTheme: () => set({ theme: defaultTheme })
|
||||||
|
}))
|
||||||
|
|
||||||
|
export const [useUiStore] = create((set, get) => ({
|
||||||
|
mobileMenuOpen: false,
|
||||||
|
toggleMobileMenu: () => set({ mobileMenuOpen: !get().mobileMenuOpen }),
|
||||||
|
}))
|
Loading…
Reference in New Issue
Block a user