From 7e20975cb1cd1846ffde389135ba8e8b25b74ee9 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Mon, 30 Oct 2023 17:37:31 +0600 Subject: [PATCH] show like button to guests --- src/components/node/NodeLikeButton/index.tsx | 38 ++++++++++ .../node/NodeLikeButton/styles.module.scss | 72 +++++++++++++++++++ src/components/node/NodeTitle/index.tsx | 59 +++++++-------- .../node/NodeTitle/styles.module.scss | 71 ------------------ src/constants/modal/index.ts | 2 + src/containers/node/NodeCommentForm/index.tsx | 6 +- src/layouts/NodeLayout/index.tsx | 13 +++- 7 files changed, 149 insertions(+), 112 deletions(-) create mode 100644 src/components/node/NodeLikeButton/index.tsx create mode 100644 src/components/node/NodeLikeButton/styles.module.scss diff --git a/src/components/node/NodeLikeButton/index.tsx b/src/components/node/NodeLikeButton/index.tsx new file mode 100644 index 00000000..e9772201 --- /dev/null +++ b/src/components/node/NodeLikeButton/index.tsx @@ -0,0 +1,38 @@ +import React, { FC } from 'react'; + +import classNames from 'classnames'; + +import { Icon } from '~/components/input/Icon'; + +import styles from './styles.module.scss'; + +interface NodeLikeButtonProps { + active: boolean; + count?: number; + className?: string; + + onClick: () => void; +} + +const NodeLikeButton: FC = ({ + className, + active, + count, + onClick, +}) => ( +
+ {active ? ( + + ) : ( + + )} + + {!!count && count > 0 &&
{count}
} +
+); + +export { NodeLikeButton }; diff --git a/src/components/node/NodeLikeButton/styles.module.scss b/src/components/node/NodeLikeButton/styles.module.scss new file mode 100644 index 00000000..b4ff99d2 --- /dev/null +++ b/src/components/node/NodeLikeButton/styles.module.scss @@ -0,0 +1,72 @@ +@import 'src/styles/variables'; + +@keyframes pulse { + 0% { + transform: scale(1); + } + + 45% { + transform: scale(1); + } + + 60% { + transform: scale(1.4); + } + + 75% { + transform: scale(1); + } + + 90% { + transform: scale(1.4); + } + + 100% { + transform: scale(1); + } +} + +.like { + transition: fill, stroke 0.25s; + will-change: transform; + position: relative; + flex: 0 0 32px; + fill: currentColor; + + &.is_liked { + opacity: 1; + + svg { + fill: $color_like; + } + + .like_count { + color: $color_like; + } + } + + &:hover { + fill: $color_like; + animation: pulse 0.75s infinite; + + .count { + opacity: 0; + } + } +} + +.count { + position: absolute; + font: $font_12_bold; + left: 16px; + bottom: 0; + opacity: 1; + transition: opacity 0.25s, color 0.25s; + background: $content_bg_dark; + padding: 0 3px; + border-radius: 10px; + z-index: 3; + color: $gray_50; + pointer-events: none; + touch-action: none; +} diff --git a/src/components/node/NodeTitle/index.tsx b/src/components/node/NodeTitle/index.tsx index 99ae85ae..a910cd6e 100644 --- a/src/components/node/NodeTitle/index.tsx +++ b/src/components/node/NodeTitle/index.tsx @@ -1,14 +1,14 @@ -import React, { memo, VFC } from 'react'; +import { memo, VFC } from 'react'; import classNames from 'classnames'; -import { Authorized } from '~/components/containers/Authorized'; -import { Icon } from '~/components/input/Icon'; import { SeparatedMenu } from '~/components/menu/SeparatedMenu'; import { NodeEditMenu } from '~/components/node/NodeEditMenu'; import { Placeholder } from '~/components/placeholders/Placeholder'; import { getPrettyDate } from '~/utils/dom'; +import { NodeLikeButton } from '../NodeLikeButton'; + import styles from './styles.module.scss'; interface IProps { @@ -77,39 +77,28 @@ const NodeTitle: VFC = memo( )} - - - {canEdit && ( - - )} + + {canEdit && ( + + )} - {canLike && ( -
- {isLiked ? ( - - ) : ( - - )} - - {!!likeCount && likeCount > 0 && ( -
{likeCount}
- )} -
- )} -
-
+ {canLike && ( + + )} + ); diff --git a/src/components/node/NodeTitle/styles.module.scss b/src/components/node/NodeTitle/styles.module.scss index dd30b4bd..95c8e616 100644 --- a/src/components/node/NodeTitle/styles.module.scss +++ b/src/components/node/NodeTitle/styles.module.scss @@ -59,77 +59,6 @@ min-width: 0; } -@keyframes pulse { - 0% { - transform: scale(1); - } - - 45% { - transform: scale(1); - } - - 60% { - transform: scale(1.4); - } - - 75% { - transform: scale(1); - } - - 90% { - transform: scale(1.4); - } - - 100% { - transform: scale(1); - } -} - -.like { - transition: fill, stroke 0.25s; - will-change: transform; - position: relative; - flex: 0 0 32px; - fill: currentColor; - - &.is_liked { - opacity: 1; - - svg { - fill: $color_like; - } - - .like_count { - color: $color_like; - } - } - - &:hover { - fill: $color_like; - animation: pulse 0.75s infinite; - - .like_count { - opacity: 0; - } - } -} - -.like_count { - position: absolute; - font: $font_12_bold; - left: 16px; - bottom: 0; - opacity: 1; - transition: opacity 0.25s, color 0.25s; - background: $content_bg_dark; - padding: 0 3px; - border-radius: 10px; - z-index: 3; - color: $gray_50; - pointer-events: none; - touch-action: none; -} - .buttons { margin-top: 12px; margin-right: $gap; diff --git a/src/constants/modal/index.ts b/src/constants/modal/index.ts index 344fb577..c1700f8e 100644 --- a/src/constants/modal/index.ts +++ b/src/constants/modal/index.ts @@ -11,6 +11,7 @@ import { TestDialog } from '~/containers/dialogs/TestDialog'; export enum Dialog { Login = 'Login', + Register = 'Register', LoginSocialRegister = 'LoginSocialRegister', Loading = 'Loading', RestoreRequest = 'RestoreRequest', @@ -24,6 +25,7 @@ export enum Dialog { export const DIALOG_CONTENT = { [Dialog.Login]: LoginDialog, + [Dialog.Register]: LoginDialog, // TODO: make inviting dialog [Dialog.LoginSocialRegister]: LoginSocialRegisterDialog, [Dialog.Loading]: LoadingDialog, [Dialog.Test]: TestDialog, diff --git a/src/containers/node/NodeCommentForm/index.tsx b/src/containers/node/NodeCommentForm/index.tsx index 60d15d66..cebf4d5a 100644 --- a/src/containers/node/NodeCommentForm/index.tsx +++ b/src/containers/node/NodeCommentForm/index.tsx @@ -20,19 +20,19 @@ export interface Props { const NodeCommentForm: FC = observer(({ saveComment }) => { const { user, isUser } = useAuth(); - const showLoginDialog = useShowModal(Dialog.Login); + const showRegisterDialog = useShowModal(Dialog.Register); const uploader = useUploader(UploadSubject.Comment, UploadTarget.Comments); const onCommentSave = useCallback( async (comment: IComment) => { if (!isUser) { - showLoginDialog({}); + showRegisterDialog({}); return; } return saveComment(comment); }, - [isUser, showLoginDialog, saveComment], + [isUser, showRegisterDialog, saveComment], ); return ( diff --git a/src/layouts/NodeLayout/index.tsx b/src/layouts/NodeLayout/index.tsx index 427b6954..56abd89c 100644 --- a/src/layouts/NodeLayout/index.tsx +++ b/src/layouts/NodeLayout/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback } from 'react'; import { observer } from 'mobx-react-lite'; @@ -7,9 +7,12 @@ import { ScrollHelperBottom } from '~/components/common/ScrollHelperBottom'; import { Card } from '~/components/containers/Card'; import { Footer } from '~/components/main/Footer'; import { NodeTitle } from '~/components/node/NodeTitle'; +import { Dialog } from '~/constants/modal'; import { Container } from '~/containers/main/Container'; import { SubmitBarRouter } from '~/containers/main/SubmitBarRouter'; import { NodeBottomBlock } from '~/containers/node/NodeBottomBlock'; +import { useAuth } from '~/hooks/auth/useAuth'; +import { useShowModal } from '~/hooks/modal/useShowModal'; import { useNodeActions } from '~/hooks/node/useNodeActions'; import { useNodeBlocks } from '~/hooks/node/useNodeBlocks'; import { useNodeCoverImage } from '~/hooks/node/useNodeCoverImage'; @@ -19,6 +22,8 @@ import { useNodeContext } from '~/utils/context/NodeContextProvider'; import styles from './styles.module.scss'; const NodeLayout = observer(() => { + const { isUser } = useAuth(); + const showRegisterDialog = useShowModal(Dialog.Register); const { node, isLoading, update } = useNodeContext(); const { head, block } = useNodeBlocks(node, isLoading); const [canEdit, canLike, canStar] = useNodePermissions(node); @@ -26,6 +31,8 @@ const NodeLayout = observer(() => { useNodeCoverImage(node); + const onUnauthorizedLike = useCallback(() => showRegisterDialog({}), []); + return (
{head} @@ -46,9 +53,9 @@ const NodeLayout = observer(() => { isLoading={isLoading} createdAt={node.created_at || ''} canEdit={canEdit} - canLike={canLike} + canLike={canLike || !isUser} canStar={canStar} - onLike={onLike} + onLike={isUser ? onLike : onUnauthorizedLike} onStar={onStar} onLock={onLock} onEdit={onEdit}