my feed with auth guard (#245)
* my feed with auth guard * header links css fix * don't create history record when reseting lng param --------- Co-authored-by: Igor Lobanov <igor.lobanov@onetwotrip.com>
This commit is contained in:
parent
18ec665bb2
commit
aadc9677a0
25
package-lock.json
generated
25
package-lock.json
generated
|
@ -64,6 +64,7 @@
|
|||
"@tiptap/extension-text": "2.0.3",
|
||||
"@tiptap/extension-underline": "2.0.3",
|
||||
"@tiptap/extension-youtube": "2.0.3",
|
||||
"@types/js-cookie": "3.0.4",
|
||||
"@types/node": "20.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.3",
|
||||
"@typescript-eslint/parser": "6.7.3",
|
||||
|
@ -5155,6 +5156,12 @@
|
|||
"@types/istanbul-lib-report": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/js-cookie": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.4.tgz",
|
||||
"integrity": "sha512-vMMnFF+H5KYqdd/myCzq6wLDlPpteJK+jGFgBus3Da7lw+YsDmx2C8feGTzY2M3Fo823yON+HC2CL240j4OV+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/js-yaml": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.6.tgz",
|
||||
|
@ -5249,9 +5256,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.25",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz",
|
||||
"integrity": "sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==",
|
||||
"version": "17.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz",
|
||||
"integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/yargs-parser": "*"
|
||||
|
@ -21885,6 +21892,12 @@
|
|||
"@types/istanbul-lib-report": "*"
|
||||
}
|
||||
},
|
||||
"@types/js-cookie": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.4.tgz",
|
||||
"integrity": "sha512-vMMnFF+H5KYqdd/myCzq6wLDlPpteJK+jGFgBus3Da7lw+YsDmx2C8feGTzY2M3Fo823yON+HC2CL240j4OV+w==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/js-yaml": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.6.tgz",
|
||||
|
@ -21979,9 +21992,9 @@
|
|||
}
|
||||
},
|
||||
"@types/yargs": {
|
||||
"version": "17.0.25",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz",
|
||||
"integrity": "sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==",
|
||||
"version": "17.0.26",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz",
|
||||
"integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/yargs-parser": "*"
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
"@tiptap/extension-text": "2.0.3",
|
||||
"@tiptap/extension-underline": "2.0.3",
|
||||
"@tiptap/extension-youtube": "2.0.3",
|
||||
"@types/js-cookie": "3.0.4",
|
||||
"@types/node": "20.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.3",
|
||||
"@typescript-eslint/parser": "6.7.3",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// FIXME: breaks on vercel, research
|
||||
// import 'solid-devtools'
|
||||
|
||||
import { MODALS, showModal } from '../stores/ui'
|
||||
import { hideModal, MODALS, showModal } from '../stores/ui'
|
||||
import { Component, createEffect, createMemo } from 'solid-js'
|
||||
import { ROUTES, useRouter } from '../stores/router'
|
||||
import { Dynamic } from 'solid-js/web'
|
||||
|
@ -89,6 +89,10 @@ export const App = (props: PageProps) => {
|
|||
const { page, searchParams } = useRouter<RootSearchParams>()
|
||||
|
||||
createEffect(() => {
|
||||
if (!searchParams().modal) {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
const modal = MODALS[searchParams().modal]
|
||||
if (modal) {
|
||||
showModal(modal)
|
||||
|
|
|
@ -97,7 +97,9 @@ export const FullArticle = (props: Props) => {
|
|||
createEffect(() => {
|
||||
if (searchParams()?.scrollTo === 'comments' && commentsRef.current) {
|
||||
scrollToComments()
|
||||
changeSearchParam('scrollTo', null)
|
||||
changeSearchParam({
|
||||
scrollTo: null
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { createEffect, JSX, Show } from 'solid-js'
|
||||
import { useSession } from '../../context/session'
|
||||
import { hideModal, showModal } from '../../stores/ui'
|
||||
import { useRouter } from '../../stores/router'
|
||||
import { RootSearchParams } from '../../pages/types'
|
||||
import { AuthModalSearchParams } from '../Nav/AuthModal/types'
|
||||
|
||||
type Props = {
|
||||
children: JSX.Element
|
||||
|
@ -9,6 +12,7 @@ type Props = {
|
|||
|
||||
export const AuthGuard = (props: Props) => {
|
||||
const { isAuthenticated, isSessionLoaded } = useSession()
|
||||
const { changeSearchParam } = useRouter<RootSearchParams & AuthModalSearchParams>()
|
||||
|
||||
createEffect(() => {
|
||||
if (props.disabled) {
|
||||
|
@ -18,7 +22,13 @@ export const AuthGuard = (props: Props) => {
|
|||
if (isAuthenticated()) {
|
||||
hideModal()
|
||||
} else {
|
||||
showModal('auth', 'authguard')
|
||||
changeSearchParam(
|
||||
{
|
||||
source: 'authguard',
|
||||
modal: 'auth'
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -93,7 +93,9 @@ export const AuthorCard = (props: Props) => {
|
|||
const initChat = () => {
|
||||
requireAuthentication(() => {
|
||||
openPage(router, `inbox`)
|
||||
changeSearchParam('initChat', `${props.author.id}`)
|
||||
changeSearchParam({
|
||||
initChat: props.author.id.toString()
|
||||
})
|
||||
}, 'discussions')
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@ export default () => {
|
|||
class="button"
|
||||
onClick={() => {
|
||||
showModal('auth')
|
||||
changeSearchParam('mode', 'register')
|
||||
changeSearchParam({
|
||||
mode: 'register'
|
||||
})
|
||||
}}
|
||||
>
|
||||
{t('Join the community')}
|
||||
|
|
|
@ -84,7 +84,9 @@ export const ArticleCard = (props: ArticleCardProps) => {
|
|||
const scrollToComments = (event) => {
|
||||
event.preventDefault()
|
||||
openPage(router, 'article', { slug: props.article.slug })
|
||||
changeSearchParam('scrollTo', 'comments')
|
||||
changeSearchParam({
|
||||
scrollTo: 'comments'
|
||||
})
|
||||
}
|
||||
|
||||
const [isActionPopupActive, setIsActionPopupActive] = createSignal(false)
|
||||
|
|
|
@ -115,7 +115,9 @@ export const ForgotPasswordForm = () => {
|
|||
href="#"
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
changeSearchParam('mode', 'register')
|
||||
changeSearchParam({
|
||||
mode: 'register'
|
||||
})
|
||||
}}
|
||||
>
|
||||
{t('register')}
|
||||
|
@ -132,7 +134,14 @@ export const ForgotPasswordForm = () => {
|
|||
</button>
|
||||
</div>
|
||||
<div class={styles.authControl}>
|
||||
<span class={styles.authLink} onClick={() => changeSearchParam('mode', 'login')}>
|
||||
<span
|
||||
class={styles.authLink}
|
||||
onClick={() =>
|
||||
changeSearchParam({
|
||||
mode: 'login'
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('I know the password')}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -195,11 +195,12 @@ export const LoginForm = () => {
|
|||
</div>
|
||||
<div class={styles.authActions}>
|
||||
<span
|
||||
class={'link'}
|
||||
onClick={(ev) => {
|
||||
ev.preventDefault()
|
||||
changeSearchParam('mode', 'forgot-password')
|
||||
}}
|
||||
class="link"
|
||||
onClick={() =>
|
||||
changeSearchParam({
|
||||
mode: 'forgot-password'
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('Forgot password?')}
|
||||
</span>
|
||||
|
@ -210,7 +211,14 @@ export const LoginForm = () => {
|
|||
<SocialProviders />
|
||||
|
||||
<div class={styles.authControl}>
|
||||
<span class={styles.authLink} onClick={() => changeSearchParam('mode', 'register')}>
|
||||
<span
|
||||
class={styles.authLink}
|
||||
onClick={() =>
|
||||
changeSearchParam({
|
||||
mode: 'register'
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('I have no account yet')}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -198,7 +198,9 @@ export const RegisterForm = () => {
|
|||
href="#"
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
changeSearchParam('mode', 'login')
|
||||
changeSearchParam({
|
||||
mode: 'login'
|
||||
})
|
||||
}}
|
||||
>
|
||||
{t('enter')}
|
||||
|
@ -246,7 +248,14 @@ export const RegisterForm = () => {
|
|||
<SocialProviders />
|
||||
|
||||
<div class={styles.authControl}>
|
||||
<span class={styles.authLink} onClick={() => changeSearchParam('mode', 'login')}>
|
||||
<span
|
||||
class={styles.authLink}
|
||||
onClick={() =>
|
||||
changeSearchParam({
|
||||
mode: 'login'
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('I have an account')}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -251,7 +251,7 @@
|
|||
|
||||
.mainNavigationItemActive {
|
||||
background: var(--link-hover-background);
|
||||
color: var(--link-hover-color);
|
||||
color: var(--link-hover-color) !important;
|
||||
}
|
||||
|
||||
.headerWithTitle.headerScrolledBottom {
|
||||
|
|
|
@ -40,15 +40,9 @@ export const ProfilePopup = (props: ProfilePopupProps) => {
|
|||
<a href={getPagePath(router, 'profileSettings')}>{t('Settings')}</a>
|
||||
</li>
|
||||
<li class={styles.topBorderItem}>
|
||||
<a
|
||||
href="#"
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
signOut()
|
||||
}}
|
||||
>
|
||||
<span class="link" onClick={() => signOut()}>
|
||||
{t('Logout')}
|
||||
</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</Popup>
|
||||
|
|
|
@ -38,7 +38,9 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
|
|||
|
||||
onMount(() => {
|
||||
if (!searchParams().by) {
|
||||
changeSearchParam('by', 'shouts')
|
||||
changeSearchParam({
|
||||
by: 'shouts'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -47,7 +49,8 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
|
|||
})
|
||||
|
||||
const byLetter = createMemo<{ [letter: string]: Author[] }>(() => {
|
||||
return sortedAuthors().reduce((acc, author) => {
|
||||
return sortedAuthors().reduce(
|
||||
(acc, author) => {
|
||||
let letter = author.name.trim().split(' ').pop().at(0).toUpperCase()
|
||||
|
||||
if (/[^ËА-яё]/.test(letter) && lang() === 'ru') letter = '@'
|
||||
|
@ -56,7 +59,9 @@ export const AllAuthorsView = (props: AllAuthorsViewProps) => {
|
|||
|
||||
acc[letter].push(author)
|
||||
return acc
|
||||
}, {} as { [letter: string]: Author[] })
|
||||
},
|
||||
{} as { [letter: string]: Author[] }
|
||||
)
|
||||
})
|
||||
|
||||
const sortedKeys = createMemo<string[]>(() => {
|
||||
|
|
|
@ -38,7 +38,9 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
|
|||
|
||||
onMount(() => {
|
||||
if (!searchParams().by) {
|
||||
changeSearchParam('by', 'shouts')
|
||||
changeSearchParam({
|
||||
by: 'shouts'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -47,13 +49,16 @@ export const AllTopicsView = (props: AllTopicsViewProps) => {
|
|||
})
|
||||
|
||||
const byLetter = createMemo<{ [letter: string]: Topic[] }>(() => {
|
||||
return sortedTopics().reduce((acc, topic) => {
|
||||
return sortedTopics().reduce(
|
||||
(acc, topic) => {
|
||||
let letter = topic.title[0].toUpperCase()
|
||||
if (/[^ËА-яё]/.test(letter) && lang() === 'ru') letter = '#'
|
||||
if (!acc[letter]) acc[letter] = []
|
||||
acc[letter].push(topic)
|
||||
return acc
|
||||
}, {} as { [letter: string]: Topic[] })
|
||||
},
|
||||
{} as { [letter: string]: Topic[] }
|
||||
)
|
||||
})
|
||||
|
||||
const sortedKeys = createMemo<string[]>(() => {
|
||||
|
|
|
@ -3,13 +3,13 @@ import { Icon } from '../_shared/Icon'
|
|||
import { ArticleCard } from '../Feed/ArticleCard'
|
||||
import { AuthorCard } from '../Author/AuthorCard'
|
||||
import { Sidebar } from '../Feed/Sidebar'
|
||||
import { loadShouts, loadMyFeed, useArticlesStore, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { useArticlesStore, resetSortedArticles } from '../../stores/zine/articles'
|
||||
import { useAuthorsStore } from '../../stores/zine/authors'
|
||||
import { useTopicsStore } from '../../stores/zine/topics'
|
||||
import { useTopAuthorsStore } from '../../stores/zine/topAuthors'
|
||||
import { clsx } from 'clsx'
|
||||
import { useReactions } from '../../context/reactions'
|
||||
import type { Author, LoadShoutsOptions, Reaction } from '../../graphql/types.gen'
|
||||
import type { Author, LoadShoutsOptions, Reaction, Shout } from '../../graphql/types.gen'
|
||||
import { getPagePath } from '@nanostores/router'
|
||||
import { router, useRouter } from '../../stores/router'
|
||||
import { useLocalize } from '../../context/localize'
|
||||
|
@ -18,8 +18,6 @@ import stylesTopic from '../Feed/CardTopic.module.scss'
|
|||
import stylesBeside from '../../components/Feed/Beside.module.scss'
|
||||
import { CommentDate } from '../Article/CommentDate'
|
||||
import { Loading } from '../_shared/Loading'
|
||||
import { AuthGuard } from '../AuthGuard'
|
||||
import { useSession } from '../../context/session'
|
||||
|
||||
export const FEED_PAGE_SIZE = 20
|
||||
|
||||
|
@ -39,17 +37,13 @@ const getOrderBy = (by: FeedSearchParams['by']) => {
|
|||
return ''
|
||||
}
|
||||
|
||||
const routesWithAuthGuard = new Set([
|
||||
'feedMy',
|
||||
'feedNotifications',
|
||||
'feedBookmarks',
|
||||
'feedCollaborations',
|
||||
'feedDiscussions'
|
||||
])
|
||||
export const FeedView = () => {
|
||||
type Props = {
|
||||
loadShouts: (options: LoadShoutsOptions) => Promise<{ hasMore: boolean; newShouts: Shout[] }>
|
||||
}
|
||||
|
||||
export const FeedView = (props: Props) => {
|
||||
const { t } = useLocalize()
|
||||
const { page, searchParams } = useRouter<FeedSearchParams>()
|
||||
const { isAuthenticated } = useSession()
|
||||
const [isLoading, setIsLoading] = createSignal(false)
|
||||
|
||||
// state
|
||||
|
@ -91,15 +85,7 @@ export const FeedView = () => {
|
|||
options.order_by = orderBy
|
||||
}
|
||||
|
||||
if (isAuthenticated()) {
|
||||
return loadMyFeed(options)
|
||||
}
|
||||
|
||||
// default feed
|
||||
return loadShouts({
|
||||
...options,
|
||||
filters: { visibility: 'community' }
|
||||
})
|
||||
return props.loadShouts(options)
|
||||
}
|
||||
|
||||
const loadMore = async () => {
|
||||
|
@ -124,8 +110,6 @@ export const FeedView = () => {
|
|||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AuthGuard disabled={!routesWithAuthGuard.has(page().route)}>
|
||||
<div class="wide-container feed">
|
||||
<div class="row">
|
||||
<div class={clsx('col-md-5 col-xl-4', styles.feedNavigation)}>
|
||||
|
@ -136,8 +120,7 @@ export const FeedView = () => {
|
|||
<ul class={clsx(styles.feedFilter, 'view-switcher')}>
|
||||
<li
|
||||
class={clsx({
|
||||
'view-switcher__item--selected':
|
||||
searchParams().by === 'publish_date' || !searchParams().by
|
||||
'view-switcher__item--selected': searchParams().by === 'publish_date' || !searchParams().by
|
||||
})}
|
||||
>
|
||||
<a href={getPagePath(router, page().route)}>{t('Recent')}</a>
|
||||
|
@ -275,7 +258,5 @@ export const FeedView = () => {
|
|||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</AuthGuard>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -64,7 +64,9 @@ export const InboxView = () => {
|
|||
|
||||
const handleOpenChat = async (chat: Chat) => {
|
||||
setCurrentDialog(chat)
|
||||
changeSearchParam('chat', `${chat.id}`)
|
||||
changeSearchParam({
|
||||
chat: chat.id
|
||||
})
|
||||
try {
|
||||
await getMessages(chat.id)
|
||||
} catch (error) {
|
||||
|
@ -121,8 +123,10 @@ export const InboxView = () => {
|
|||
try {
|
||||
const newChat = await createChat([Number(searchParams().initChat)], '')
|
||||
await loadChats()
|
||||
changeSearchParam('initChat', null)
|
||||
changeSearchParam('chat', newChat.chat.id)
|
||||
changeSearchParam({
|
||||
initChat: null,
|
||||
chat: newChat.chat.id
|
||||
})
|
||||
const chatToOpen = chats().find((chat) => chat.id === newChat.chat.id)
|
||||
await handleOpenChat(chatToOpen)
|
||||
} catch (error) {
|
||||
|
|
|
@ -88,7 +88,14 @@ export const TopicView = (props: TopicProps) => {
|
|||
'view-switcher__item--selected': searchParams().by === 'recent' || !searchParams().by
|
||||
}}
|
||||
>
|
||||
<button type="button" onClick={() => changeSearchParam('by', 'recent')}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
changeSearchParam({
|
||||
by: 'recent'
|
||||
})
|
||||
}
|
||||
>
|
||||
{t('Recent')}
|
||||
</button>
|
||||
</li>
|
||||
|
|
|
@ -33,7 +33,7 @@ export const LocalizeProvider = (props: { children: JSX.Element }) => {
|
|||
changeLanguage(lng)
|
||||
setLang(lng)
|
||||
Cookie.set('lng', lng)
|
||||
changeSearchParam('lng', null)
|
||||
changeSearchParam({ lng: null }, true)
|
||||
})
|
||||
|
||||
const value: LocalizeContextType = { t, lang, setLang }
|
||||
|
|
|
@ -74,8 +74,8 @@ export const SessionProvider = (props: { children: JSX.Element }) => {
|
|||
|
||||
const signIn = async ({ email, password }: { email: string; password: string }) => {
|
||||
const authResult = await apiClient.authLogin({ email, password })
|
||||
mutate(authResult)
|
||||
setToken(authResult.token)
|
||||
mutate(authResult)
|
||||
console.debug('signed in')
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,41 @@
|
|||
import { PageLayout } from '../components/_shared/PageLayout'
|
||||
import { FeedView } from '../components/Views/Feed'
|
||||
import { onCleanup } from 'solid-js'
|
||||
import { resetSortedArticles } from '../stores/zine/articles'
|
||||
import { Match, onCleanup, Switch } from 'solid-js'
|
||||
import { loadMyFeed, loadShouts, resetSortedArticles } from '../stores/zine/articles'
|
||||
import { ReactionsProvider } from '../context/reactions'
|
||||
import { useRouter } from '../stores/router'
|
||||
import { AuthGuard } from '../components/AuthGuard'
|
||||
import { LoadShoutsOptions } from '../graphql/types.gen'
|
||||
|
||||
export const FeedPage = () => {
|
||||
onCleanup(() => resetSortedArticles())
|
||||
|
||||
const { page } = useRouter()
|
||||
|
||||
const handleFeedLoadShouts = (options: LoadShoutsOptions) => {
|
||||
return loadShouts({
|
||||
...options,
|
||||
filters: { visibility: 'community' }
|
||||
})
|
||||
}
|
||||
|
||||
const handleMyFeedLoadShouts = (options: LoadShoutsOptions) => {
|
||||
return loadMyFeed(options)
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
<ReactionsProvider>
|
||||
<FeedView />
|
||||
<Switch fallback={<FeedView loadShouts={handleFeedLoadShouts} />}>
|
||||
<Match when={page().route === 'feed'}>
|
||||
<FeedView loadShouts={handleFeedLoadShouts} />
|
||||
</Match>
|
||||
<Match when={page().route === 'feedMy'}>
|
||||
<AuthGuard>
|
||||
<FeedView loadShouts={handleMyFeedLoadShouts} />
|
||||
</AuthGuard>
|
||||
</Match>
|
||||
</Switch>
|
||||
</ReactionsProvider>
|
||||
</PageLayout>
|
||||
)
|
||||
|
|
|
@ -137,17 +137,16 @@ export const useRouter = <TSearchParams extends Record<string, string> = Record<
|
|||
const page = useStore(routerStore)
|
||||
const searchParams = useStore(searchParamsStore) as unknown as Accessor<TSearchParams>
|
||||
|
||||
const changeSearchParam = <TKey extends keyof TSearchParams>(
|
||||
key: TKey,
|
||||
value: TSearchParams[TKey],
|
||||
replace = false
|
||||
) => {
|
||||
const changeSearchParam = (newValues: Partial<TSearchParams>, replace = false) => {
|
||||
const newSearchParams = { ...searchParamsStore.get() }
|
||||
if (value === null) {
|
||||
|
||||
Object.keys(newValues).forEach((key) => {
|
||||
if (newValues[key] === null) {
|
||||
delete newSearchParams[key.toString()]
|
||||
} else {
|
||||
newSearchParams[key.toString()] = value
|
||||
newSearchParams[key.toString()] = newValues[key]
|
||||
}
|
||||
})
|
||||
|
||||
searchParamsStore.open(newSearchParams, replace)
|
||||
}
|
||||
|
|
|
@ -58,7 +58,9 @@ const { searchParams, changeSearchParam } = useRouter<
|
|||
|
||||
export const showModal = (modalType: ModalType, modalSource?: AuthModalSource) => {
|
||||
if (modalSource) {
|
||||
changeSearchParam('source', modalSource)
|
||||
changeSearchParam({
|
||||
source: modalSource
|
||||
})
|
||||
}
|
||||
|
||||
setModal(modalType)
|
||||
|
@ -66,15 +68,19 @@ export const showModal = (modalType: ModalType, modalSource?: AuthModalSource) =
|
|||
|
||||
// TODO: find a better solution
|
||||
export const hideModal = () => {
|
||||
if (searchParams().modal === 'auth') {
|
||||
if (searchParams().mode === 'confirm-email') {
|
||||
changeSearchParam('token', null, true)
|
||||
}
|
||||
changeSearchParam('mode', null, true)
|
||||
const newSearchParams: Partial<AuthModalSearchParams & ConfirmEmailSearchParams & RootSearchParams> = {
|
||||
modal: null,
|
||||
source: null
|
||||
}
|
||||
|
||||
changeSearchParam('modal', null, true)
|
||||
changeSearchParam('source', null)
|
||||
if (searchParams().modal === 'auth') {
|
||||
if (searchParams().mode === 'confirm-email') {
|
||||
newSearchParams.token = null
|
||||
}
|
||||
newSearchParams.mode = null
|
||||
}
|
||||
|
||||
changeSearchParam(newSearchParams, true)
|
||||
|
||||
setModal(null)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user