webapp/src/routes/(main).tsx

138 lines
4.0 KiB
TypeScript
Raw Normal View History

2024-06-24 17:50:27 +00:00
import { type RouteDefinition, type RouteSectionProps, createAsync } from '@solidjs/router'
2024-07-15 14:28:08 +00:00
import { Show, createEffect } from 'solid-js'
import { LoadMoreWrapper } from '~/components/_shared/LoadMoreWrapper'
import { useFeed } from '~/context/feed'
2024-07-05 22:45:42 +00:00
import { useTopics } from '~/context/topics'
import { loadShouts, loadTopics } from '~/graphql/api/public'
2024-07-13 07:53:35 +00:00
import { LoadShoutsOptions, Shout } from '~/graphql/schema/core.gen'
2024-07-13 11:47:31 +00:00
import { byStat } from '~/lib/sort'
2024-07-13 17:22:32 +00:00
import { SortFunction } from '~/types/common'
2024-06-24 17:50:27 +00:00
import { HomeView, HomeViewProps } from '../components/Views/Home'
import { Loading } from '../components/_shared/Loading'
import { PageLayout } from '../components/_shared/PageLayout'
import { useLocalize } from '../context/localize'
export const SHOUTS_PER_PAGE = 20
2024-07-15 14:28:08 +00:00
const featuredLoader = (offset?: number) => {
const SHOUTS_PER_PAGE = 20
return loadShouts({
filters: { featured: true },
limit: SHOUTS_PER_PAGE,
offset
})
}
2024-07-05 22:45:42 +00:00
const fetchAllTopics = async () => {
const allTopicsLoader = loadTopics()
return await allTopicsLoader()
}
2024-06-24 17:50:27 +00:00
const fetchHomeTopData = async () => {
const topCommentedLoader = loadShouts({
filters: { featured: true },
2024-06-28 07:47:38 +00:00
order_by: 'comments_stat',
limit: 10
2024-06-24 17:50:27 +00:00
})
2024-06-28 07:47:38 +00:00
const daysago = Date.now() - 30 * 24 * 60 * 60 * 1000
const after = Math.floor(daysago / 1000)
const options: LoadShoutsOptions = {
filters: {
featured: true,
after
},
order_by: 'likes_stat',
limit: 10
}
const topMonthLoader = loadShouts({ ...options })
2024-06-24 17:50:27 +00:00
const topRatedLoader = loadShouts({
filters: { featured: true },
2024-06-28 07:47:38 +00:00
order_by: 'likes_stat',
limit: 10
2024-06-24 17:50:27 +00:00
})
return {
topRatedShouts: await topRatedLoader(),
2024-06-28 07:47:38 +00:00
topMonthShouts: await topMonthLoader(),
topCommentedShouts: await topCommentedLoader()
2024-06-24 17:50:27 +00:00
} as Partial<HomeViewProps>
}
export const route = {
load: async () => {
const limit = 20
const featuredLoader = loadShouts({
filters: { featured: true },
2024-06-26 08:22:05 +00:00
limit
2024-06-24 17:50:27 +00:00
})
2024-07-05 22:46:07 +00:00
return {
...(await fetchHomeTopData()),
featuredShouts: await featuredLoader(),
topics: await fetchAllTopics()
}
2024-06-26 08:22:05 +00:00
}
2024-06-24 17:50:27 +00:00
} satisfies RouteDefinition
export default function HomePage(props: RouteSectionProps<HomeViewProps>) {
2024-07-05 22:45:42 +00:00
const { addTopics } = useTopics()
2024-06-24 17:50:27 +00:00
const { t } = useLocalize()
2024-07-15 14:28:08 +00:00
const {
setFeaturedFeed,
featuredFeed,
topMonthFeed,
topViewedFeed,
topCommentedFeed,
topFeed: topRatedFeed
} = useFeed()
2024-06-24 17:50:27 +00:00
const data = createAsync(async (prev?: HomeViewProps) => {
2024-07-05 22:46:07 +00:00
const topics = props.data?.topics || (await fetchAllTopics())
2024-07-15 14:28:08 +00:00
const offset = prev?.featuredShouts?.length || 0
const featuredShoutsLoader = featuredLoader(offset)
const loaded = await featuredShoutsLoader()
2024-06-28 07:47:38 +00:00
const featuredShouts = [
...(prev?.featuredShouts || []),
2024-07-15 14:28:08 +00:00
...(loaded || props.data?.featuredShouts || [])
2024-06-28 07:47:38 +00:00
]
const sortFn = byStat('viewed')
2024-07-15 14:28:08 +00:00
const topViewedShouts = featuredShouts.sort(sortFn as SortFunction<Shout>)
return {
2024-06-24 17:50:27 +00:00
...prev,
...props.data,
2024-06-28 07:47:38 +00:00
topViewedShouts,
2024-07-05 22:45:42 +00:00
featuredShouts,
topics
2024-06-24 17:50:27 +00:00
}
})
2024-07-15 14:28:08 +00:00
createEffect(() => {
if (data()?.topics) {
console.debug('[routes.main] topics update')
addTopics(data()?.topics || [])
}
})
2024-06-24 17:50:27 +00:00
2024-07-15 14:28:08 +00:00
const loadMoreFeatured = async (offset?: number) => {
const shoutsLoader = featuredLoader(offset)
const loaded = await shoutsLoader()
loaded && setFeaturedFeed((prev: Shout[]) => [...prev, ...loaded])
}
const SHOUTS_PER_PAGE = 20
2024-06-24 17:50:27 +00:00
return (
2024-07-15 14:28:08 +00:00
<PageLayout withPadding={true} title={t('Discours')} key="home">
<Show when={(featuredFeed() || []).length > 0} fallback={<Loading />}>
<LoadMoreWrapper loadFunction={loadMoreFeatured} pageSize={SHOUTS_PER_PAGE}>
<HomeView
featuredShouts={featuredFeed() as Shout[]}
topMonthShouts={topMonthFeed() as Shout[]}
topViewedShouts={topViewedFeed() as Shout[]}
topRatedShouts={topRatedFeed() as Shout[]}
topCommentedShouts={topCommentedFeed() as Shout[]}
/>
</LoadMoreWrapper>
</Show>
2024-06-24 17:50:27 +00:00
</PageLayout>
)
}