webapp/src/routes/topic/[slug]/[...tab].tsx

115 lines
3.7 KiB
TypeScript
Raw Normal View History

2024-07-13 09:36:23 +00:00
import { RouteSectionProps, createAsync } from '@solidjs/router'
2024-07-09 17:41:14 +00:00
import { HttpStatusCode } from '@solidjs/start'
import { Show, Suspense, createEffect, createMemo, createSignal } from 'solid-js'
2024-07-01 13:27:45 +00:00
import { FourOuFourView } from '~/components/Views/FourOuFour'
2024-07-13 10:32:27 +00:00
import { TopicFeedSortBy, TopicView } from '~/components/Views/Topic'
2024-07-01 13:27:45 +00:00
import { Loading } from '~/components/_shared/Loading'
import { PageLayout } from '~/components/_shared/PageLayout'
import { useLocalize } from '~/context/localize'
import { useTopics } from '~/context/topics'
2024-07-09 17:41:14 +00:00
import { loadShouts, loadTopics } from '~/graphql/api/public'
2024-07-13 10:32:27 +00:00
import { Author, LoadShoutsOptions, Shout, Topic } from '~/graphql/schema/core.gen'
2024-07-09 09:13:13 +00:00
import { getImageUrl } from '~/lib/getImageUrl'
2024-07-13 09:06:49 +00:00
import { descFromBody } from '~/utils/meta'
2024-07-13 10:32:27 +00:00
import { SHOUTS_PER_PAGE } from '../../(main)'
2024-07-01 13:27:45 +00:00
2024-07-03 17:38:43 +00:00
const fetchTopicShouts = async (slug: string, offset?: number) => {
const opts: LoadShoutsOptions = { filters: { topic: slug }, limit: SHOUTS_PER_PAGE, offset }
2024-07-01 13:27:45 +00:00
const shoutsLoader = loadShouts(opts)
return await shoutsLoader()
}
2024-07-09 17:41:14 +00:00
const fetchAllTopics = async () => {
const topicsFetcher = loadTopics()
return await topicsFetcher()
}
2024-07-01 13:27:45 +00:00
export const route = {
2024-07-03 17:38:43 +00:00
load: async ({ params, location: { query } }: RouteSectionProps<{ articles: Shout[] }>) => {
const offset: number = Number.parseInt(query.offset, 10)
const result = await fetchTopicShouts(params.slug, offset)
2024-07-09 17:41:14 +00:00
return {
articles: result,
topics: await fetchAllTopics()
}
2024-07-03 17:38:43 +00:00
}
2024-07-01 13:27:45 +00:00
}
2024-07-13 10:33:49 +00:00
export type TopicPageProps = { articles?: Shout[]; topics: Topic[]; authors?: Author[] }
2024-07-01 13:27:45 +00:00
2024-07-13 10:32:27 +00:00
export default function TopicPage(props: RouteSectionProps<TopicPageProps>) {
2024-07-09 17:41:14 +00:00
const { t } = useLocalize()
const { addTopics } = useTopics()
const [loadingError, setLoadingError] = createSignal(false)
const topic = createAsync(async () => {
try {
const ttt: Topic[] = props.data.topics || (await fetchAllTopics()) || []
addTopics(ttt)
console.debug('[route.topic] all topics loaded')
2024-07-13 09:36:23 +00:00
const t = ttt.find((x) => x.slug === props.params.slug)
2024-07-09 17:41:14 +00:00
return t
} catch (_error) {
setLoadingError(true)
return null
}
})
2024-07-09 14:13:36 +00:00
const articles = createAsync(
2024-07-13 09:36:23 +00:00
async () => props.data.articles || (await fetchTopicShouts(props.params.slug)) || []
2024-07-09 14:13:36 +00:00
)
2024-07-09 17:41:14 +00:00
2024-07-05 08:11:57 +00:00
const title = createMemo(() => `${t('Discours')} :: ${topic()?.title || ''}`)
2024-07-09 17:41:14 +00:00
2024-07-06 06:41:16 +00:00
createEffect(() => {
if (topic() && window) {
window?.gtag?.('event', 'page_view', {
2024-07-01 13:27:45 +00:00
page_title: topic()?.title,
2024-07-06 06:41:16 +00:00
page_location: window?.location.href,
page_path: window?.location.pathname
2024-07-01 13:27:45 +00:00
})
}
})
2024-07-09 17:41:14 +00:00
2024-07-09 09:13:13 +00:00
const desc = createMemo(() =>
topic()?.body
2024-07-13 09:06:49 +00:00
? descFromBody(topic()?.body || '')
2024-07-09 09:13:13 +00:00
: t('The most interesting publications on the topic', { topicName: title() })
)
2024-07-09 17:41:14 +00:00
2024-07-09 09:13:13 +00:00
const cover = createMemo(() =>
topic()?.pic
? getImageUrl(topic()?.pic || '', { width: 1200 })
: getImageUrl('production/image/logo_image.png')
)
2024-07-09 17:41:14 +00:00
2024-07-01 13:27:45 +00:00
return (
2024-07-09 17:41:14 +00:00
<Suspense fallback={<Loading />}>
<Show
when={!loadingError()}
fallback={
<PageLayout isHeaderFixed={false} hideFooter={true} title={t('Nothing is here')}>
<FourOuFourView />
<HttpStatusCode code={404} />
</PageLayout>
}
>
2024-07-01 13:27:45 +00:00
<PageLayout
2024-07-09 09:13:13 +00:00
key="topic"
2024-07-01 13:27:45 +00:00
title={title()}
2024-07-09 09:13:13 +00:00
desc={desc()}
2024-07-01 13:27:45 +00:00
headerTitle={topic()?.title || ''}
slug={topic()?.slug}
2024-07-09 09:13:13 +00:00
cover={cover()}
2024-07-01 13:27:45 +00:00
>
2024-07-09 12:27:50 +00:00
<TopicView
topic={topic() as Topic}
topicSlug={props.params.slug}
shouts={articles() as Shout[]}
2024-07-13 10:32:27 +00:00
selectedTab={props.params.tab as TopicFeedSortBy}
2024-07-09 12:27:50 +00:00
/>
2024-07-01 13:27:45 +00:00
</PageLayout>
2024-07-09 17:41:14 +00:00
</Show>
</Suspense>
2024-07-01 13:27:45 +00:00
)
}