diff --git a/src/components/Nav/Header/Header.tsx b/src/components/Nav/Header/Header.tsx index b294d75a..9c88d968 100644 --- a/src/components/Nav/Header/Header.tsx +++ b/src/components/Nav/Header/Header.tsx @@ -155,11 +155,13 @@ export const Header = (props: Props) => { const loc = useLocation() const handleToggleMenuByLink = (event: MouseEvent, route: string) => { event.preventDefault() - console.debug(loc.pathname, route) + // console.debug('[Header] toggle menu link from', loc.pathname) + // console.debug('to', route) if (!fixed()) return if (loc.pathname.startsWith(route) || loc.pathname.startsWith(`/${route}`)) { toggleFixed() } + navigate(route) } return (
{ routeName="home" active={isZineVisible()} body={t('journal')} - onClick={(event) => handleToggleMenuByLink(event, 'home')} + onClick={(event) => handleToggleMenuByLink(event, '/')} /> toggleSubnavigation(true, setIsFeedVisible)} @@ -221,7 +223,7 @@ export const Header = (props: Props) => { routeName="feed" active={isFeedVisible()} body={t('feed')} - onClick={(event) => handleToggleMenuByLink(event, 'feed')} + onClick={(event) => handleToggleMenuByLink(event, '/feed')} /> toggleSubnavigation(true, setIsTopicsVisible)} @@ -229,14 +231,14 @@ export const Header = (props: Props) => { routeName="topics" active={isTopicsVisible()} body={t('topics')} - onClick={(event) => handleToggleMenuByLink(event, 'topics')} + onClick={(event) => handleToggleMenuByLink(event, '/topics')} /> hideSubnavigation(0)} onMouseOut={() => hideSubnavigation(0)} routeName="authors" body={t('authors')} - onClick={(event) => handleToggleMenuByLink(event, 'authors')} + onClick={(event) => handleToggleMenuByLink(event, '/authors')} /> toggleSubnavigation(true, setIsKnowledgeBaseVisible)} @@ -244,7 +246,7 @@ export const Header = (props: Props) => { routeName="guide" body={t('Knowledge base')} active={isKnowledgeBaseVisible()} - onClick={(event) => handleToggleMenuByLink(event, 'guide')} + onClick={(event) => handleToggleMenuByLink(event, '/guide')} /> diff --git a/src/components/Views/AllTopics/AllTopics.tsx b/src/components/Views/AllTopics/AllTopics.tsx index 532e406d..dd1bcb29 100644 --- a/src/components/Views/AllTopics/AllTopics.tsx +++ b/src/components/Views/AllTopics/AllTopics.tsx @@ -1,8 +1,9 @@ -import { clsx } from 'clsx' -import { For, Show, createMemo, createSignal } from 'solid-js' - import { Meta } from '@solidjs/meta' import { useSearchParams } from '@solidjs/router' +import { clsx } from 'clsx' +import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js' + +import { useTopics } from '~/context/topics' import { useLocalize } from '../../../context/localize' import type { Topic } from '../../../graphql/schema/core.gen' import { capitalize } from '../../../utils/capitalize' @@ -12,14 +13,13 @@ import { scrollHandler } from '../../../utils/scroll' import { TopicBadge } from '../../Topic/TopicBadge' import { Loading } from '../../_shared/Loading' import { SearchField } from '../../_shared/SearchField' - import styles from './AllTopics.module.scss' type Props = { topics: Topic[] } -export const TOPICS_PER_PAGE = 20 +export const TOPICS_PER_PAGE = 50 export const ABC = { ru: 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ#', en: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ#' @@ -28,12 +28,14 @@ export const ABC = { export const AllTopics = (props: Props) => { const { t, lang } = useLocalize() const alphabet = createMemo(() => ABC[lang()]) - const [searchParams] = useSearchParams<{ by?: string }>() - const sortedTopics = createMemo(() => props.topics) - + const { setTopicsSort, sortedTopics } = useTopics() + const topics = createMemo(() => sortedTopics() || props.topics) + const [searchParams, ] = useSearchParams<{ by?: string }>() + createEffect(on(() => searchParams?.by || 'shouts', setTopicsSort, {defer: true})) + onMount(() => setTopicsSort('shouts')) // sorted derivative const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => { - return sortedTopics().reduce( + return topics().reduce( (acc, topic) => { let letter = lang() === 'en' ? topic.slug[0].toUpperCase() : (topic?.title?.[0] || '').toUpperCase() if (/[^ËА-яё]/.test(letter) && lang() === 'ru') letter = '#' @@ -63,9 +65,8 @@ export const AllTopics = (props: Props) => { // filter const [searchQuery, setSearchQuery] = createSignal('') - const filteredResults = createMemo(() => { - return dummyFilter(sortedTopics(), searchQuery(), lang()) - }) + const [filteredResults, setFilteredResults] = createSignal([]) + createEffect(() => setFilteredResults((_prev: Topic[]) => dummyFilter(topics(), searchQuery(), lang()) as Topic[])) // subcomponent const AllTopicsHead = () => ( @@ -113,7 +114,7 @@ export const AllTopics = (props: Props) => { - }> + }>
diff --git a/src/context/session.tsx b/src/context/session.tsx index b68a7027..276dc499 100644 --- a/src/context/session.tsx +++ b/src/context/session.tsx @@ -281,9 +281,9 @@ export const SessionProvider = (props: { const updateProfile = async (params: UpdateProfileInput) => { const resp = await authenticate(authorizer().updateProfile, params as UpdateProfileInput) - console.debug('[context.session] updateProfile:', resp) + console.debug('[context.session] updateProfile response:', resp) if (resp?.data) { - console.debug(resp.data) + // console.debug('[context.session] response data ', resp.data) // FIXME: renew updated profile return true } @@ -292,12 +292,12 @@ export const SessionProvider = (props: { const signOut = async () => { const authResult: ApiResponse = await authorizer().logout() - console.debug(authResult) + // console.debug('[context.session] sign out', authResult) if (authResult) { setSession({} as AuthToken) setIsSessionLoaded(true) showSnackbar({ body: t("You've successfully logged out") }) - console.debug(session()) + // console.debug(session()) return true } return false diff --git a/src/context/topics.tsx b/src/context/topics.tsx index 796238d3..7099421b 100644 --- a/src/context/topics.tsx +++ b/src/context/topics.tsx @@ -106,13 +106,15 @@ const saveTopicsToIndexedDB = async (db: IDBDatabase, topics: Topic[]) => { await tx.done } } - +export type TopicSort = 'shouts' | 'followers' | 'authors' | 'title' | '' export const TopicsProvider = (props: { children: JSX.Element }) => { const [topicEntities, setTopicEntities] = createSignal<{ [topicSlug: string]: Topic }>({}) - const [sortAllBy, setSortAllBy] = createSignal<'shouts' | 'followers' | 'authors' | 'title'>('shouts') + const [sortedTopics, setSortedTopics] = createSignal([]) + const [sortAllBy, setSortAllBy] = createSignal('') - const sortedTopics = createLazyMemo(() => { + createEffect(() => { const topics = Object.values(topicEntities()) + console.debug('[context.topics] effect trig', topics) switch (sortAllBy()) { case 'followers': { topics.sort(byTopicStatDesc('followers')) @@ -134,8 +136,7 @@ export const TopicsProvider = (props: { children: JSX.Element }) => { topics.sort(byTopicStatDesc('shouts')) } } - - return topics + setSortedTopics(topics as Topic[]) }) const topTopics = createMemo(() => { @@ -188,7 +189,7 @@ export const TopicsProvider = (props: { children: JSX.Element }) => { const isCacheValid = now - timestamp < CACHE_LIFETIME const topics = isCacheValid ? req : await loadAllTopics() - console.info(`[context.topics] got ${(topics as Topic[]).length || 0} topics`) + console.info(`[context.topics] got ${(topics as Topic[]).length || 0} topics from idb`) addTopics(topics as Topic[]) setRandomTopic(getRandomTopicsFromArray(topics || [], 1).pop()) } diff --git a/src/routes/[...slug].tsx b/src/routes/[...slug].tsx index bee9c52e..7507de40 100644 --- a/src/routes/[...slug].tsx +++ b/src/routes/[...slug].tsx @@ -33,9 +33,9 @@ export const ArticlePage = (props: RouteSectionProps<{ article: Shout }>) => { console.info('[routes.slug] mounted, connecting ga...') await loadGAScript(gaIdentity) initGA(gaIdentity) - console.debug('Google Analytics connected successfully') + console.debug('[routes.slug] Google Analytics connected successfully') } catch (error) { - console.warn('Failed to connect Google Analytics:', error) + console.warn('[routes.slug] Failed to connect Google Analytics:', error) } } }) diff --git a/src/routes/topics.tsx b/src/routes/topics.tsx index f051bef3..f13d6bb5 100644 --- a/src/routes/topics.tsx +++ b/src/routes/topics.tsx @@ -1,8 +1,8 @@ -import { type RouteDefinition, type RouteSectionProps, createAsync, useSearchParams } from '@solidjs/router' -import { Suspense, createEffect, createSignal, on } from 'solid-js' -import { Topic, TopicStat } from '~/graphql/schema/core.gen' +import { type RouteDefinition, type RouteSectionProps, createAsync } from '@solidjs/router' +import { Suspense, createEffect} from 'solid-js' +import { useTopics } from '~/context/topics' +import { Topic } from '~/graphql/schema/core.gen' import { loadTopics } from '~/lib/api' -import { byTopicStatDesc } from '~/utils/sortby' import { AllTopics } from '../components/Views/AllTopics' import { Loading } from '../components/_shared/Loading' import { PageLayout } from '../components/_shared/PageLayout' @@ -16,18 +16,16 @@ const fetchData = async () => { export const route = { load: loadTopics } satisfies RouteDefinition -export default function HomePage(props: RouteSectionProps<{ topics: Topic[] }>) { +export default function AllTopicsPage(props: RouteSectionProps<{ topics: Topic[] }>) { const { t } = useLocalize() const topics = createAsync(async () => props.data.topics || (await fetchData()) || []) - const [topicsSort, setTopicsSort] = createSignal('shouts') - const [searchParams] = useSearchParams<{ by?: string }>() - createEffect(on(() => searchParams?.by || 'shouts', setTopicsSort)) - + const { addTopics } = useTopics() + createEffect(() => addTopics(topics()||[])) return ( }> - +