From 3a7d138eef0b4be7ea98c7d2e3495882a48f5763 Mon Sep 17 00:00:00 2001 From: Igor Lobanov Date: Wed, 20 Dec 2023 09:07:57 +0100 Subject: [PATCH] feed period select (#340) * feed period select * fix, unused code removed * Fix styles * Fix styles * Fix styles --------- Co-authored-by: Igor Lobanov Co-authored-by: ilya-bkv --- public/locales/en/translation.json | 3 + public/locales/ru/translation.json | 3 + src/components/Article/FullArticle.tsx | 6 +- src/components/AuthGuard/AuthGuard.tsx | 4 +- .../Author/AuthorBadge/AuthorBadge.tsx | 4 +- .../Author/AuthorCard/AuthorCard.tsx | 4 +- src/components/Discours/Hero.tsx | 4 +- .../Feed/ArticleCard/ArticleCard.tsx | 4 +- .../Nav/AuthModal/ForgotPasswordForm.tsx | 6 +- src/components/Nav/AuthModal/LoginForm.tsx | 6 +- src/components/Nav/AuthModal/RegisterForm.tsx | 6 +- .../NotificationView/NotificationView.tsx | 4 +- src/components/Views/AllAuthors.tsx | 4 +- src/components/Views/AllTopics.tsx | 4 +- src/components/Views/Expo/Expo.tsx | 2 +- src/components/Views/Feed/Feed.module.scss | 25 +++- src/components/Views/Feed/Feed.tsx | 125 ++++++++++++++---- src/components/Views/Home.tsx | 12 -- src/components/Views/Inbox.tsx | 6 +- src/components/Views/Topic.tsx | 10 +- .../_shared/DropDown/DropDown.module.scss | 7 + src/components/_shared/DropDown/DropDown.tsx | 69 ++++++++++ src/components/_shared/DropDown/index.ts | 1 + src/components/_shared/Popup/Popup.tsx | 4 +- src/context/localize.tsx | 4 +- src/pages/feed.page.tsx | 5 +- src/stores/router.ts | 4 +- src/stores/ui.ts | 6 +- src/styles/app.scss | 10 +- 29 files changed, 260 insertions(+), 92 deletions(-) create mode 100644 src/components/_shared/DropDown/DropDown.module.scss create mode 100644 src/components/_shared/DropDown/DropDown.tsx create mode 100644 src/components/_shared/DropDown/index.ts diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 6b7a4173..35c0913e 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -357,9 +357,12 @@ "This comment has not yet been rated": "This comment has not yet been rated", "This email is already taken. If it's you": "This email is already taken. If it's you", "This functionality is currently not available, we would like to work on this issue. Use the download link.": "This functionality is currently not available, we would like to work on this issue. Use the download link.", + "This month": "This month", "This post has not been rated yet": "This post has not been rated yet", "This way we ll realize that you re a real person and ll take your vote into account. And you ll see how others voted": "This way we ll realize that you re a real person and ll take your vote into account. And you ll see how others voted", "This way you ll be able to subscribe to authors, interesting topics and customize your feed": "This way you ll be able to subscribe to authors, interesting topics and customize your feed", + "This week": "This week", + "This year": "This year", "To leave a comment please": "To leave a comment please", "To write a comment, you must": "To write a comment, you must", "Top authors": "Authors rating", diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json index 5f9fd460..b496a982 100644 --- a/public/locales/ru/translation.json +++ b/public/locales/ru/translation.json @@ -377,9 +377,12 @@ "This comment has not yet been rated": "Этот комментарий еще пока никто не оценил", "This email is already taken. If it's you": "Такой email уже зарегистрирован. Если это вы", "This functionality is currently not available, we would like to work on this issue. Use the download link.": "В данный момент этот функционал не доступен, бы работаем над этой проблемой. Воспользуйтесь загрузкой по ссылке.", + "This month": "За месяц", "This post has not been rated yet": "Эту публикацию еще пока никто не оценил", "This way we ll realize that you re a real person and ll take your vote into account. And you ll see how others voted": "Так мы поймем, что вы реальный человек, и учтем ваш голос. А вы увидите, как проголосовали другие", "This way you ll be able to subscribe to authors, interesting topics and customize your feed": "Так вы сможете подписаться на авторов, интересные темы и настроить свою ленту", + "This week": "За неделю", + "This year": "За год", "To leave a comment please": "Чтобы оставить комментарий, необходимо", "To write a comment, you must": "Чтобы написать комментарий, необходимо", "Top authors": "Рейтинг авторов", diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 51ea46f4..2fc420ce 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -135,7 +135,7 @@ export const FullArticle = (props: Props) => { scrollTo(commentsRef.current) } - const { searchParams, changeSearchParam } = useRouter() + const { searchParams, changeSearchParams } = useRouter() createEffect(() => { if (props.scrollToComments) { @@ -146,7 +146,7 @@ export const FullArticle = (props: Props) => { createEffect(() => { if (searchParams()?.scrollTo === 'comments' && commentsRef.current) { scrollToComments() - changeSearchParam({ + changeSearchParams({ scrollTo: null, }) } @@ -158,7 +158,7 @@ export const FullArticle = (props: Props) => { `[id='comment_${searchParams().commentId}']`, ) - changeSearchParam({ commentId: null }) + changeSearchParams({ commentId: null }) if (commentElement) { scrollTo(commentElement) diff --git a/src/components/AuthGuard/AuthGuard.tsx b/src/components/AuthGuard/AuthGuard.tsx index c7b0c442..d4e2e133 100644 --- a/src/components/AuthGuard/AuthGuard.tsx +++ b/src/components/AuthGuard/AuthGuard.tsx @@ -13,7 +13,7 @@ type Props = { export const AuthGuard = (props: Props) => { const { isAuthenticated, isSessionLoaded } = useSession() - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() createEffect(() => { if (props.disabled) { @@ -23,7 +23,7 @@ export const AuthGuard = (props: Props) => { if (isAuthenticated()) { hideModal() } else { - changeSearchParam( + changeSearchParams( { source: 'authguard', modal: 'auth', diff --git a/src/components/Author/AuthorBadge/AuthorBadge.tsx b/src/components/Author/AuthorBadge/AuthorBadge.tsx index 9ab3f66b..b744df32 100644 --- a/src/components/Author/AuthorBadge/AuthorBadge.tsx +++ b/src/components/Author/AuthorBadge/AuthorBadge.tsx @@ -29,7 +29,7 @@ export const AuthorBadge = (props: Props) => { subscriptions, actions: { loadSubscriptions, requireAuthentication }, } = useSession() - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const { t, formatDate } = useLocalize() const subscribed = createMemo(() => subscriptions().authors.some((author) => author.slug === props.author.slug), @@ -54,7 +54,7 @@ export const AuthorBadge = (props: Props) => { const initChat = () => { requireAuthentication(() => { openPage(router, `inbox`) - changeSearchParam({ + changeSearchParams({ initChat: props.author.id.toString(), }) }, 'discussions') diff --git a/src/components/Author/AuthorCard/AuthorCard.tsx b/src/components/Author/AuthorCard/AuthorCard.tsx index 65f4353a..a1269d82 100644 --- a/src/components/Author/AuthorCard/AuthorCard.tsx +++ b/src/components/Author/AuthorCard/AuthorCard.tsx @@ -72,11 +72,11 @@ export const AuthorCard = (props: Props) => { }) // TODO: reimplement AuthorCard - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const initChat = () => { requireAuthentication(() => { openPage(router, `inbox`) - changeSearchParam({ + changeSearchParams({ initChat: props.author.id.toString(), }) }, 'discussions') diff --git a/src/components/Discours/Hero.tsx b/src/components/Discours/Hero.tsx index 27be6cc3..105300cc 100644 --- a/src/components/Discours/Hero.tsx +++ b/src/components/Discours/Hero.tsx @@ -7,7 +7,7 @@ import styles from './Hero.module.scss' export default () => { const { t } = useLocalize() - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() return (
@@ -28,7 +28,7 @@ export default () => { class="button" onClick={() => { showModal('auth') - changeSearchParam({ + changeSearchParams({ mode: 'register', }) }} diff --git a/src/components/Feed/ArticleCard/ArticleCard.tsx b/src/components/Feed/ArticleCard/ArticleCard.tsx index 00654f34..f656c8a7 100644 --- a/src/components/Feed/ArticleCard/ArticleCard.tsx +++ b/src/components/Feed/ArticleCard/ArticleCard.tsx @@ -98,11 +98,11 @@ export const ArticleCard = (props: ArticleCardProps) => { const canEdit = () => props.article.authors?.some((a) => a.slug === user()?.slug) - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const scrollToComments = (event) => { event.preventDefault() openPage(router, 'article', { slug: props.article.slug }) - changeSearchParam({ + changeSearchParams({ scrollTo: 'comments', }) } diff --git a/src/components/Nav/AuthModal/ForgotPasswordForm.tsx b/src/components/Nav/AuthModal/ForgotPasswordForm.tsx index 31c59da7..eb27ab16 100644 --- a/src/components/Nav/AuthModal/ForgotPasswordForm.tsx +++ b/src/components/Nav/AuthModal/ForgotPasswordForm.tsx @@ -20,7 +20,7 @@ type FormFields = { type ValidationErrors = Partial> export const ForgotPasswordForm = () => { - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const { t, lang } = useLocalize() const handleEmailInput = (newEmail: string) => { setValidationErrors(({ email: _notNeeded, ...rest }) => rest) @@ -119,7 +119,7 @@ export const ForgotPasswordForm = () => { href="#" onClick={(event) => { event.preventDefault() - changeSearchParam({ + changeSearchParams({ mode: 'register', }) }} @@ -141,7 +141,7 @@ export const ForgotPasswordForm = () => { - changeSearchParam({ + changeSearchParams({ mode: 'login', }) } diff --git a/src/components/Nav/AuthModal/LoginForm.tsx b/src/components/Nav/AuthModal/LoginForm.tsx index 25f45594..0a7e11fc 100644 --- a/src/components/Nav/AuthModal/LoginForm.tsx +++ b/src/components/Nav/AuthModal/LoginForm.tsx @@ -47,7 +47,7 @@ export const LoginForm = () => { actions: { signIn }, } = useSession() - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const [password, setPassword] = createSignal('') @@ -201,7 +201,7 @@ export const LoginForm = () => { - changeSearchParam({ + changeSearchParams({ mode: 'forgot-password', }) } @@ -218,7 +218,7 @@ export const LoginForm = () => { - changeSearchParam({ + changeSearchParams({ mode: 'register', }) } diff --git a/src/components/Nav/AuthModal/RegisterForm.tsx b/src/components/Nav/AuthModal/RegisterForm.tsx index d2f9c9f2..7f642d3e 100644 --- a/src/components/Nav/AuthModal/RegisterForm.tsx +++ b/src/components/Nav/AuthModal/RegisterForm.tsx @@ -32,7 +32,7 @@ const handleEmailInput = (newEmail: string) => { } export const RegisterForm = () => { - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const { t } = useLocalize() const { emailChecks } = useEmailChecks() @@ -202,7 +202,7 @@ export const RegisterForm = () => { href="#" onClick={(event) => { event.preventDefault() - changeSearchParam({ + changeSearchParams({ mode: 'login', }) }} @@ -255,7 +255,7 @@ export const RegisterForm = () => { - changeSearchParam({ + changeSearchParams({ mode: 'login', }) } diff --git a/src/components/NotificationsPanel/NotificationView/NotificationView.tsx b/src/components/NotificationsPanel/NotificationView/NotificationView.tsx index 5751884b..c611f4f3 100644 --- a/src/components/NotificationsPanel/NotificationView/NotificationView.tsx +++ b/src/components/NotificationsPanel/NotificationView/NotificationView.tsx @@ -42,7 +42,7 @@ export const NotificationView = (props: Props) => { actions: { markNotificationAsRead, hideNotificationsPanel }, } = useNotifications() - const { changeSearchParam } = useRouter() + const { changeSearchParams } = useRouter() const { t, formatDate, formatTime } = useLocalize() @@ -139,7 +139,7 @@ export const NotificationView = (props: Props) => { openPage(router, 'article', { slug: data().shout.slug }) if (data().reactionIds) { - changeSearchParam({ commentId: data().reactionIds[0].toString() }) + changeSearchParams({ commentId: data().reactionIds[0].toString() }) } } diff --git a/src/components/Views/AllAuthors.tsx b/src/components/Views/AllAuthors.tsx index b3d40f15..f3d059a3 100644 --- a/src/components/Views/AllAuthors.tsx +++ b/src/components/Views/AllAuthors.tsx @@ -31,7 +31,7 @@ const ALPHABET = [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫ export const AllAuthorsView = (props: Props) => { const { t, lang } = useLocalize() const [limit, setLimit] = createSignal(PAGE_SIZE) - const { searchParams, changeSearchParam } = useRouter() + const { searchParams, changeSearchParams } = useRouter() const { sortedAuthors } = useAuthorsStore({ authors: props.authors, sortBy: searchParams().by || 'shouts', @@ -41,7 +41,7 @@ export const AllAuthorsView = (props: Props) => { createEffect(() => { if (!searchParams().by) { - changeSearchParam({ + changeSearchParams({ by: 'shouts', }) } diff --git a/src/components/Views/AllTopics.tsx b/src/components/Views/AllTopics.tsx index 6fad3908..6c7e6b30 100644 --- a/src/components/Views/AllTopics.tsx +++ b/src/components/Views/AllTopics.tsx @@ -31,7 +31,7 @@ const ALPHABET = [...'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫ export const AllTopicsView = (props: Props) => { const { t, lang } = useLocalize() - const { searchParams, changeSearchParam } = useRouter() + const { searchParams, changeSearchParams } = useRouter() const [limit, setLimit] = createSignal(PAGE_SIZE) const { sortedTopics } = useTopicsStore({ @@ -43,7 +43,7 @@ export const AllTopicsView = (props: Props) => { createEffect(() => { if (!searchParams().by) { - changeSearchParam({ + changeSearchParams({ by: 'shouts', }) } diff --git a/src/components/Views/Expo/Expo.tsx b/src/components/Views/Expo/Expo.tsx index 76a06530..52d61cd9 100644 --- a/src/components/Views/Expo/Expo.tsx +++ b/src/components/Views/Expo/Expo.tsx @@ -46,7 +46,7 @@ export const Expo = (props: Props) => { }) const getLoadShoutsFilters = (additionalFilters: LoadShoutsFilters = {}): LoadShoutsFilters => { - const filters = { ...additionalFilters } + const filters = { visibility: 'public', ...additionalFilters } if (props.layout) { filters.layout = props.layout diff --git a/src/components/Views/Feed/Feed.module.scss b/src/components/Views/Feed/Feed.module.scss index 87fc5f6e..5c97c2ca 100644 --- a/src/components/Views/Feed/Feed.module.scss +++ b/src/components/Views/Feed/Feed.module.scss @@ -1,7 +1,4 @@ .feedFilter { - margin-bottom: 4.8rem; - margin-top: 0.2em; - @include media-breakpoint-down(md) { margin-right: 4rem !important; } @@ -192,3 +189,25 @@ font-weight: 500; } + +.filtersContainer { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 4rem; + + .feedFilter { + margin-top: 0; + margin-bottom: 0; + + & > li { + margin-bottom: 0; + } + } +} + +.periodSwitcher { + font-size: 14px; + font-weight: 700; + line-height: 18px; +} diff --git a/src/components/Views/Feed/Feed.tsx b/src/components/Views/Feed/Feed.tsx index 3ac8822e..6629bdf6 100644 --- a/src/components/Views/Feed/Feed.tsx +++ b/src/components/Views/Feed/Feed.tsx @@ -3,7 +3,7 @@ import type { Author, LoadShoutsOptions, Reaction, Shout } from '../../../graphq import { getPagePath } from '@nanostores/router' import { Meta } from '@solidjs/meta' import { clsx } from 'clsx' -import { createEffect, createSignal, For, on, onMount, Show } from 'solid-js' +import { createEffect, createMemo, createSignal, For, on, onMount, Show } from 'solid-js' import { useLocalize } from '../../../context/localize' import { useReactions } from '../../../context/reactions' @@ -13,6 +13,8 @@ import { useTopAuthorsStore } from '../../../stores/zine/topAuthors' import { useTopicsStore } from '../../../stores/zine/topics' import { apiClient } from '../../../utils/apiClient' import { getImageUrl } from '../../../utils/getImageUrl' +import { getServerDate } from '../../../utils/getServerDate' +import { DropDown } from '../../_shared/DropDown' import { Icon } from '../../_shared/Icon' import { Loading } from '../../_shared/Loading' import { CommentDate } from '../../Article/CommentDate' @@ -28,8 +30,16 @@ import stylesTopic from '../../Feed/CardTopic.module.scss' export const FEED_PAGE_SIZE = 20 const UNRATED_ARTICLES_COUNT = 5 +type FeedPeriod = 'week' | 'month' | 'year' + +type PeriodItem = { + value: FeedPeriod + title: string +} + type FeedSearchParams = { by: 'publish_date' | 'rating' | 'last_comment' + period: FeedPeriod } const getOrderBy = (by: FeedSearchParams['by']) => { @@ -53,7 +63,16 @@ type Props = { export const Feed = (props: Props) => { const { t } = useLocalize() - const { page, searchParams } = useRouter() + + const monthPeriod: PeriodItem = { value: 'month', title: t('This month') } + + const periods: PeriodItem[] = [ + { value: 'week', title: t('This week') }, + monthPeriod, + { value: 'year', title: t('This year') }, + ] + + const { page, searchParams, changeSearchParams } = useRouter() const [isLoading, setIsLoading] = createSignal(false) const [isRightColumnLoaded, setIsRightColumnLoaded] = createSignal(false) @@ -64,6 +83,16 @@ export const Feed = (props: Props) => { const [topComments, setTopComments] = createSignal([]) const [unratedArticles, setUnratedArticles] = createSignal([]) + const currentPeriod = createMemo(() => { + const period = periods.find((p) => p.value === searchParams().period) + + if (!period) { + return monthPeriod + } + + return period + }) + const { actions: { loadReactionsBy }, } = useReactions() @@ -86,7 +115,7 @@ export const Feed = (props: Props) => { createEffect( on( - () => page().route + searchParams().by, + () => page().route + searchParams().by + searchParams().period, () => { resetSortedArticles() loadMore() @@ -94,6 +123,21 @@ export const Feed = (props: Props) => { { defer: true }, ), ) + + const getFromDate = (period: FeedPeriod): Date => { + const now = new Date() + switch (period) { + case 'week': { + return new Date(now.setDate(now.getDate() - 7)) + } + case 'month': { + return new Date(now.setMonth(now.getMonth() - 1)) + } + case 'year': { + return new Date(now.setFullYear(now.getFullYear() - 1)) + } + } + } const loadFeedShouts = () => { const options: LoadShoutsOptions = { limit: FEED_PAGE_SIZE, @@ -106,6 +150,12 @@ export const Feed = (props: Props) => { options.order_by = orderBy } + if (searchParams().by && searchParams().by !== 'publish_date') { + const period = searchParams().period || 'month' + const fromDate = getFromDate(period) + options.filters = { fromDate: getServerDate(fromDate) } + } + return props.loadShouts(options) } @@ -148,32 +198,49 @@ export const Feed = (props: Props) => {
- +
+
    +
  • + {t('Recent')} +
  • + {/*
  • */} + {/* {t('Most read')}*/} + {/*
  • */} +
  • + changeSearchParams({ by: 'rating' })}> + {t('Top rated')} + +
  • +
  • + changeSearchParams({ by: 'last_comment' })}> + {t('Most commented')} + +
  • +
+ +
+ changeSearchParams({ period: period.value })} + /> +
+
+
}> 0}> diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index 952bf1da..a7b69137 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -115,9 +115,7 @@ export const HomeView = (props: Props) => { wrapper={'top-article'} nodate={true} /> - - { wrapper={'author'} nodate={true} /> - - - - { header={

{t('Top commented')}

} nodate={true} /> - {randomLayout()} - - { isTopicCompact={true} nodate={true} /> - - - diff --git a/src/components/Views/Inbox.tsx b/src/components/Views/Inbox.tsx index 755c39a4..348b7207 100644 --- a/src/components/Views/Inbox.tsx +++ b/src/components/Views/Inbox.tsx @@ -52,7 +52,7 @@ export const InboxView = () => { const [isClear, setClear] = createSignal(false) const { session } = useSession() const currentUserId = createMemo(() => session()?.user.id) - const { changeSearchParam, searchParams } = useRouter() + const { changeSearchParams, searchParams } = useRouter() // Поиск по диалогам const getQuery = (query) => { if (query().length >= 2) { @@ -67,7 +67,7 @@ export const InboxView = () => { const handleOpenChat = async (chat: Chat) => { setCurrentDialog(chat) - changeSearchParam({ + changeSearchParams({ chat: chat.id, }) try { @@ -126,7 +126,7 @@ export const InboxView = () => { try { const newChat = await createChat([Number(searchParams().initChat)], '') await loadChats() - changeSearchParam({ + changeSearchParams({ initChat: null, chat: newChat.chat.id, }) diff --git a/src/components/Views/Topic.tsx b/src/components/Views/Topic.tsx index 27717294..b830a1a6 100644 --- a/src/components/Views/Topic.tsx +++ b/src/components/Views/Topic.tsx @@ -41,7 +41,7 @@ const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3 export const TopicView = (props: Props) => { const { t } = useLocalize() - const { searchParams, changeSearchParam } = useRouter() + const { searchParams, changeSearchParams } = useRouter() const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) @@ -125,7 +125,7 @@ export const TopicView = (props: Props) => { */} {/**/} {/*
  • */} - {/* */} {/*
  • */} {/*
  • */} - {/* */} {/*
  • */} diff --git a/src/components/_shared/DropDown/DropDown.module.scss b/src/components/_shared/DropDown/DropDown.module.scss new file mode 100644 index 00000000..c438b02b --- /dev/null +++ b/src/components/_shared/DropDown/DropDown.module.scss @@ -0,0 +1,7 @@ +.chevron { + vertical-align: top; + + &.rotate { + transform: rotate(180deg); + } +} diff --git a/src/components/_shared/DropDown/DropDown.tsx b/src/components/_shared/DropDown/DropDown.tsx new file mode 100644 index 00000000..e1ba7aa4 --- /dev/null +++ b/src/components/_shared/DropDown/DropDown.tsx @@ -0,0 +1,69 @@ +import type { PopupProps } from '../Popup' + +import { clsx } from 'clsx' +import { createSignal, For, Show } from 'solid-js' + +import { Popup } from '../Popup' + +import styles from './DropDown.module.scss' + +export type Option = { + value: string | number + title: string +} + +type Props = { + class?: string + popupProps?: PopupProps + options: TOption[] + currentOption: TOption + triggerCssClass?: string + onChange: (option: TOption) => void +} + +const Chevron = (props: { class?: string }) => { + return ( + + + + ) +} + +export const DropDown = (props: Props) => { + const [isPopupVisible, setIsPopupVisible] = createSignal(false) + + return ( + + + {props.currentOption.title}{' '} + +
    + } + variant="tiny" + onVisibilityChange={(isVisible) => setIsPopupVisible(isVisible)} + {...props.popupProps} + > + p.value !== props.currentOption.value)}> + {(option) => ( + + )} + + + + ) +} diff --git a/src/components/_shared/DropDown/index.ts b/src/components/_shared/DropDown/index.ts new file mode 100644 index 00000000..8a266f72 --- /dev/null +++ b/src/components/_shared/DropDown/index.ts @@ -0,0 +1 @@ +export { DropDown } from './DropDown' diff --git a/src/components/_shared/Popup/Popup.tsx b/src/components/_shared/Popup/Popup.tsx index 78d5cdde..f9cb0902 100644 --- a/src/components/_shared/Popup/Popup.tsx +++ b/src/components/_shared/Popup/Popup.tsx @@ -32,7 +32,9 @@ export const Popup = (props: PopupProps) => { useOutsideClickHandler({ containerRef, predicate: () => isVisible(), - handler: () => setIsVisible(false), + handler: () => { + setIsVisible(false) + }, }) const toggle = () => setIsVisible((oldVisible) => !oldVisible) diff --git a/src/context/localize.tsx b/src/context/localize.tsx index 394526e8..8dcc6cd5 100644 --- a/src/context/localize.tsx +++ b/src/context/localize.tsx @@ -32,7 +32,7 @@ export function useLocalize() { export const LocalizeProvider = (props: { children: JSX.Element }) => { const [lang, setLang] = createSignal(i18next.language === 'en' ? 'en' : 'ru') - const { searchParams, changeSearchParam } = useRouter<{ + const { searchParams, changeSearchParams } = useRouter<{ lng: string }>() @@ -46,7 +46,7 @@ export const LocalizeProvider = (props: { children: JSX.Element }) => { changeLanguage(lng) setLang(lng) Cookie.set('lng', lng) - changeSearchParam({ lng: null }, true) + changeSearchParams({ lng: null }, true) }) const formatTime = (date: Date, options: Intl.DateTimeFormatOptions = {}) => { diff --git a/src/pages/feed.page.tsx b/src/pages/feed.page.tsx index 3daf019d..9b1a099f 100644 --- a/src/pages/feed.page.tsx +++ b/src/pages/feed.page.tsx @@ -12,7 +12,10 @@ import { loadMyFeed, loadShouts, resetSortedArticles } from '../stores/zine/arti const handleFeedLoadShouts = (options: LoadShoutsOptions) => { return loadShouts({ ...options, - filters: { visibility: 'community' }, + filters: { + visibility: 'community', + ...options.filters, + }, }) } diff --git a/src/stores/router.ts b/src/stores/router.ts index 4803ed82..a9409c68 100644 --- a/src/stores/router.ts +++ b/src/stores/router.ts @@ -138,7 +138,7 @@ export const useRouter = = Record< const page = useStore(routerStore) const searchParams = useStore(searchParamsStore) as unknown as Accessor - const changeSearchParam = (newValues: Partial, replace = false) => { + const changeSearchParams = (newValues: Partial, replace = false) => { const newSearchParams = { ...searchParamsStore.get() } Object.keys(newValues).forEach((key) => { @@ -155,6 +155,6 @@ export const useRouter = = Record< return { page, searchParams, - changeSearchParam, + changeSearchParams, } } diff --git a/src/stores/ui.ts b/src/stores/ui.ts index aa555272..b5630fc0 100644 --- a/src/stores/ui.ts +++ b/src/stores/ui.ts @@ -42,13 +42,13 @@ export const MODALS: Record = { const [modal, setModal] = createSignal(null) -const { searchParams, changeSearchParam } = useRouter< +const { searchParams, changeSearchParams } = useRouter< AuthModalSearchParams & ConfirmEmailSearchParams & RootSearchParams >() export const showModal = (modalType: ModalType, modalSource?: AuthModalSource) => { if (modalSource) { - changeSearchParam({ + changeSearchParams({ source: modalSource, }) } @@ -70,7 +70,7 @@ export const hideModal = () => { newSearchParams.mode = null } - changeSearchParam(newSearchParams, true) + changeSearchParams(newSearchParams, true) setModal(null) } diff --git a/src/styles/app.scss b/src/styles/app.scss index 376ab52d..ef3ea022 100644 --- a/src/styles/app.scss +++ b/src/styles/app.scss @@ -204,7 +204,7 @@ a:hover, a:visited, a:link, .link { - border-bottom: 1px solid rgb(0 0 0 / 30%); + border-bottom: 2px solid rgb(0 0 0 / 30%); text-decoration: none; cursor: pointer; } @@ -624,6 +624,10 @@ figure { margin-bottom: 0.6em; white-space: nowrap; + .link { + border-bottom: none; + } + &:last-child { margin-right: 0; } @@ -645,9 +649,10 @@ figure { } a, + .link, .linkReplacement, button { - border-bottom: 2px solid transparent; + border-bottom: 1px solid transparent; color: var(--link-color); cursor: pointer; font-weight: inherit; @@ -662,6 +667,7 @@ figure { font-weight: bold; a, + .link, .linkReplacement, button { border-bottom: 2px solid #000;