diff --git a/packages/frontend/src/constants/errorMessage.ts b/packages/frontend/src/constants/errorMessage.ts new file mode 100644 index 000000000..3b5b2ffe6 --- /dev/null +++ b/packages/frontend/src/constants/errorMessage.ts @@ -0,0 +1,3 @@ +export const AUTH_ERROR_MESSAGE = { + DEFAULT: '很抱歉通知您,您尚未登陸帳號,請返回註冊頁再次嘗試註冊,謝謝您!', +} diff --git a/packages/frontend/src/constants/paths.ts b/packages/frontend/src/constants/paths.ts index c5ece8fa3..a7b7fa303 100644 --- a/packages/frontend/src/constants/paths.ts +++ b/packages/frontend/src/constants/paths.ts @@ -9,6 +9,6 @@ export const PATHS = { VIEW_POST: '/posts/:id', WRITE_POST: '/write-post', PROFILE: '/profile', - HISTORTY: '/profile/history', + HISTORY: '/profile/history', REPUTATION: '/profile/reputation', } diff --git a/packages/frontend/src/features/auth/components/AuthErrorDialog/AuthErrorDialog.tsx b/packages/frontend/src/features/auth/components/AuthErrorDialog/AuthErrorDialog.tsx index e345e7d27..9f3a1f20f 100644 --- a/packages/frontend/src/features/auth/components/AuthErrorDialog/AuthErrorDialog.tsx +++ b/packages/frontend/src/features/auth/components/AuthErrorDialog/AuthErrorDialog.tsx @@ -6,12 +6,14 @@ interface ErrorModalProps { isOpen: boolean message?: string buttonText?: string + onClose: () => void } export default function AuthErrorDialog({ isOpen, message = '', buttonText = '返回註冊頁重新嘗試', + onClose, }: ErrorModalProps) { const navigate = useNavigate() @@ -26,14 +28,14 @@ export default function AuthErrorDialog({ -
+

親愛的用戶:

{message}

{compact && imageUrl && ( diff --git a/packages/frontend/src/features/post/components/Post/PostActionMenu.tsx b/packages/frontend/src/features/post/components/Post/PostActionMenu.tsx index 3447bf46a..97126c1e5 100644 --- a/packages/frontend/src/features/post/components/Post/PostActionMenu.tsx +++ b/packages/frontend/src/features/post/components/Post/PostActionMenu.tsx @@ -1,4 +1,6 @@ import { ReactComponent as BanIcon } from '@/assets/svg/ban.svg' +import { AUTH_ERROR_MESSAGE } from '@/constants/errorMessage' +import { useAuthCheck } from '@/features/auth/hooks/useAuthCheck/useAuthCheck' import { useReputationScore } from '@/features/reporting' import { useDialog } from '@/features/shared' import { openForbidActionDialog } from '@/features/shared/stores/dialog' @@ -30,10 +32,18 @@ export function PostActionMenu({ postId }: PostActionMenuProps) { } = useDialog() const { isValidReputationScore } = useReputationScore() + const checkAuth = useAuthCheck(AUTH_ERROR_MESSAGE.DEFAULT) + const handleReportPost = isValidReputationScore ? onReportDialogOpen : openForbidActionDialog + const onReport = () => { + checkAuth(() => { + handleReportPost() + }) + } + return ( } name="檢舉貼文" - onClick={handleReportPost} + onClick={onReport} disabled={false} /> @@ -57,7 +67,7 @@ export function PostActionMenu({ postId }: PostActionMenuProps) { } name="檢舉貼文" - onClick={handleReportPost} + onClick={onReport} disabled={false} /> diff --git a/packages/frontend/src/features/post/components/PostList/PostList.tsx b/packages/frontend/src/features/post/components/PostList/PostList.tsx index 2b547bb82..bd0cfe6b5 100644 --- a/packages/frontend/src/features/post/components/PostList/PostList.tsx +++ b/packages/frontend/src/features/post/components/PostList/PostList.tsx @@ -1,4 +1,5 @@ import { QueryKeys } from '@/constants/queryKeys' + import { ActionStatus, postActionsSelector, @@ -126,6 +127,15 @@ export default function PostList() { const { createVote } = useVotes() + const handleComment = (postId?: string) => { + if (!postId) return + if (!isValidReputationScore) { + openForbidActionDialog() + return + } + gotoCommentsByPostId(postId) + } + const handleVote = async ( id: string, voteType: VoteAction, @@ -219,14 +229,7 @@ export default function PostList() { votedNonce={post.votedNonce} votedEpoch={post.votedEpoch} status={post.status} - onComment={() => { - if (!post.postId) return - if (!isValidReputationScore) { - openForbidActionDialog() - return - } - gotoCommentsByPostId(post.postId) - }} + onComment={() => handleComment(post.id)} onVote={(voteType) => handleVote(post.postId!, voteType, post) } diff --git a/packages/frontend/src/features/reporting/components/AdjudicateNotification/AdjudicateNotification.tsx b/packages/frontend/src/features/reporting/components/AdjudicateNotification/AdjudicateNotification.tsx index 2e592f8a4..c8dfd343a 100644 --- a/packages/frontend/src/features/reporting/components/AdjudicateNotification/AdjudicateNotification.tsx +++ b/packages/frontend/src/features/reporting/components/AdjudicateNotification/AdjudicateNotification.tsx @@ -6,6 +6,7 @@ import { usePendingReports } from '../../hooks/usePendingReports/usePendingRepor import { isMyAdjudicateNullifier } from '../../utils/helpers' import Adjudicate from '../Adjudicate/Adjudicate' import AdjudicateButton from './AdjudicateButton' +import { useAuthStatus } from '@/features/auth' function useActiveAdjudication() { const { userState } = useUserState() @@ -74,6 +75,7 @@ function useActiveAdjudication() { } export default function AdjudicationNotification() { + const { isLoggedIn } = useAuthStatus() const { data: activeAdjudication, refetch } = useActiveAdjudication() const [open, toggle] = useToggle(false) @@ -83,7 +85,7 @@ export default function AdjudicationNotification() { toggle(false) } - if (!activeAdjudication) { + if (!activeAdjudication || !isLoggedIn) { return null } diff --git a/packages/frontend/src/routes/app/layout.tsx b/packages/frontend/src/routes/app/layout.tsx index a100a7744..51129e7a1 100644 --- a/packages/frontend/src/routes/app/layout.tsx +++ b/packages/frontend/src/routes/app/layout.tsx @@ -42,11 +42,11 @@ function NotificationContainer({ children }: { children: React.ReactNode }) { export default function AppLayout() { const matchPath = useMatch('/') - const location = useLocation() - const navigate = useNavigate() + // const { isAuthError, hideAuthError } = useAuthStore() + useBackgroundReputationClaim() const headerTextOnDesktop = getDesktopHeaderTextByPath(location.pathname) @@ -238,6 +238,12 @@ export default function AppLayout() { + {/* {isAuthError && ( + + )} */} diff --git a/packages/frontend/src/routes/app/posts/[id]/page.tsx b/packages/frontend/src/routes/app/posts/[id]/page.tsx index 289a18368..c63667abb 100644 --- a/packages/frontend/src/routes/app/posts/[id]/page.tsx +++ b/packages/frontend/src/routes/app/posts/[id]/page.tsx @@ -1,5 +1,4 @@ import { QueryKeys } from '@/constants/queryKeys' -import { AuthErrorDialog, useAuthStatus } from '@/features/auth' import { PostService, useUserState } from '@/features/core' import { CommentList, @@ -28,8 +27,6 @@ const PostDetailsPage: React.FC = () => { const { userState } = useUserState() - const { isLoggedIn } = useAuthStatus() - const { createVote } = useVotes() const { data, refetch } = useQuery({ @@ -69,23 +66,16 @@ const PostDetailsPage: React.FC = () => { } }, [data, userState]) - const [isOpenComment, setIsOpenCommnet] = useState(false) - - const [errorMessage, setErrorMessage] = useState() + const [isOpenComment, setIsOpenComment] = useState(false) const { isValidReputationScore } = useReputationScore() + const onWriteComment = () => { - if (!isLoggedIn) { - setErrorMessage( - '很抱歉通知您,您尚未登陸帳號,請返回註冊頁再次嘗試註冊,謝謝您!', - ) - return - } if (!isValidReputationScore) { openForbidActionDialog() return } - setIsOpenCommnet((prev) => !prev) + setIsOpenComment((prev) => !prev) } const handleVote = async (voteType: VoteAction): Promise => { @@ -154,14 +144,9 @@ const PostDetailsPage: React.FC = () => { setIsOpenCommnet(false)} + onClose={() => setIsOpenComment(false)} /> - ) } diff --git a/packages/frontend/src/routes/app/profile/history/page.tsx b/packages/frontend/src/routes/app/profile/history/page.tsx index d6104dc86..07f0a0a88 100644 --- a/packages/frontend/src/routes/app/profile/history/page.tsx +++ b/packages/frontend/src/routes/app/profile/history/page.tsx @@ -1,5 +1,27 @@ +import { LoginButton, useAuthStatus } from '@/features/auth' import { AccountHistory } from '@/features/profile' +import { RiLoginBoxLine } from 'react-icons/ri' +import { useNavigate } from 'react-router-dom' export default function History() { + const { isLoggedIn } = useAuthStatus() + const navigate = useNavigate() + + const handleClick = () => { + navigate('/welcome') + } + + if (!isLoggedIn) + return ( + + ) return } diff --git a/packages/frontend/src/routes/app/profile/page.tsx b/packages/frontend/src/routes/app/profile/page.tsx index 8852a1634..591d8a0bf 100644 --- a/packages/frontend/src/routes/app/profile/page.tsx +++ b/packages/frontend/src/routes/app/profile/page.tsx @@ -4,14 +4,22 @@ import { RiHourglassFill, RiLogoutBoxRLine, RiShieldStarLine, + RiLoginBoxLine, } from 'react-icons/ri' -import { CyanButton, LoginButton, LogoutModal } from '@/features/auth' +import { + CyanButton, + LoginButton, + LogoutModal, + useAuthStatus, +} from '@/features/auth' function HistoryButton() { const navigate = useNavigate() + const handleLogout = () => { navigate('/profile/history') } + return ( { + navigate('/welcome') + } + return (
- - - + {isLoggedIn ? ( + <> + + + + + ) : ( + + )}
) diff --git a/packages/frontend/src/routes/app/profile/reputation/page.tsx b/packages/frontend/src/routes/app/profile/reputation/page.tsx index 6141260e4..01addb921 100644 --- a/packages/frontend/src/routes/app/profile/reputation/page.tsx +++ b/packages/frontend/src/routes/app/profile/reputation/page.tsx @@ -1,5 +1,8 @@ +import { LoginButton, useAuthStatus } from '@/features/auth' import ReputationHistory from '@/features/profile/components/ReputationHistory/ReputationHistory' import { useReputationScore } from '@/features/reporting' +import { RiLoginBoxLine } from 'react-icons/ri' +import { useNavigate } from 'react-router-dom' const CONTENT = '為維護匿名平台的抗審查及自治特性,Reputation 代表著您在此平台上的信用分數,每位用戶在註冊時的分數都為0,當分數為負數時,平台將限制您的行為使您無法發文、留言、投票,若希望提高分數,請參閱平台政策。此分數受您的在平台上的行為所影響,若您受到他人檢舉,並且檢舉被判斷為有效時,您將會被扣分;若您檢舉他人成功、或是幫助平台裁定檢舉,您將會被加分。平台方保有最終解釋權' @@ -48,11 +51,32 @@ function checkIsMyScoreNegative(score: number) { } export default function Reputation() { + const { isLoggedIn } = useAuthStatus() + const navigate = useNavigate() + + const handleClick = () => { + navigate('/welcome') + } + return (
- - - + {isLoggedIn ? ( + <> + + + + + ) : ( + + )}
) } diff --git a/packages/frontend/src/routes/full-screen/write-post/page.tsx b/packages/frontend/src/routes/full-screen/write-post/page.tsx index ce265d47c..9fe5a6cac 100644 --- a/packages/frontend/src/routes/full-screen/write-post/page.tsx +++ b/packages/frontend/src/routes/full-screen/write-post/page.tsx @@ -1,5 +1,7 @@ +import { AUTH_ERROR_MESSAGE } from '@/constants/errorMessage' import { PATHS } from '@/constants/paths' -import { AuthErrorDialog, useAuthStatus } from '@/features/auth' +import { useAuthStatus } from '@/features/auth' +import { useAuthStore } from '@/features/auth/stores/authStore' import { PostFailureDialog, PostForm, @@ -13,6 +15,7 @@ import { useNavigate } from 'react-router-dom' export default function WritePostPage() { const { isLoggedIn } = useAuthStatus() + const setErrorMessage = useAuthStore((state) => state.setErrorMessage) const navigate = useNavigate() @@ -23,6 +26,7 @@ export default function WritePostPage() { const [isSubmitting, setIsSubmitting] = useState(false) const onSubmit = async (values: PostFormValues) => { + if (!isLoggedIn) return const previousPostsData = queryClient.getQueryData(['posts']) try { @@ -47,14 +51,11 @@ export default function WritePostPage() { } }, [isPending, navigate]) - if (!isLoggedIn) { - return ( - - ) - } + useEffect(() => { + if (!isLoggedIn) { + setErrorMessage(AUTH_ERROR_MESSAGE.DEFAULT) + } + }, [isLoggedIn, setErrorMessage]) return (
diff --git a/packages/frontend/src/routes/onboarding/login/internal/page.tsx b/packages/frontend/src/routes/onboarding/login/internal/page.tsx index 8d74f5fd3..6d26fff53 100644 --- a/packages/frontend/src/routes/onboarding/login/internal/page.tsx +++ b/packages/frontend/src/routes/onboarding/login/internal/page.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { GrFormClose } from 'react-icons/gr' -import { useParams } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router-dom' import { AuthErrorDialog, AuthNoteDialog, @@ -20,6 +20,11 @@ enum NoteStatus { export default function LoginInternalPage() { const { selectedSignupMethod } = useParams() + const navigate = useNavigate() + + const handleClose = () => { + navigate('/welcome') + } const { isPending: isWalletLoginPending, @@ -97,7 +102,11 @@ export default function LoginInternalPage() { noteStatus={noteStatus} onClose={() => setNoteStatus(NoteStatus.Close)} /> - +
) } diff --git a/packages/frontend/src/routes/onboarding/signup/internal/page.tsx b/packages/frontend/src/routes/onboarding/signup/internal/page.tsx index ddd7ab783..ebfa89f43 100644 --- a/packages/frontend/src/routes/onboarding/signup/internal/page.tsx +++ b/packages/frontend/src/routes/onboarding/signup/internal/page.tsx @@ -15,6 +15,7 @@ import { } from '@/features/auth' import { LocalStorageHelper } from '@/utils/helpers/LocalStorageHelper' import { getVariantAutoScrollY } from '@/utils/helpers/motionVariants' +import { useNavigate } from 'react-router-dom' enum NoteStatus { Close = 'close', @@ -24,6 +25,11 @@ enum NoteStatus { export default function SignupInternalPage() { const [noteStatus, setNoteStatus] = useState(NoteStatus.Close) + const navigate = useNavigate() + + const handleClose = () => { + navigate('/welcome') + } const { isPending: isWalletSignupPending, @@ -114,7 +120,11 @@ export default function SignupInternalPage() { noteStatus={noteStatus} onClose={() => setNoteStatus(NoteStatus.Close)} /> - + ) } diff --git a/packages/frontend/src/routes/router.tsx b/packages/frontend/src/routes/router.tsx index 49535db75..46c9cbc6f 100644 --- a/packages/frontend/src/routes/router.tsx +++ b/packages/frontend/src/routes/router.tsx @@ -1,23 +1,23 @@ +import { PATHS } from '@/constants/paths' +import AuthProvider from '@/features/auth/provider/AuthProvider' +import { ErrorBoundary, ResetStorage } from '@/features/shared' import { RouterProvider, createBrowserRouter, redirect } from 'react-router-dom' -import OnboardingLayout from './onboarding/layout' -import LoginPage from './onboarding/login/page' -import LoginInternalPage from './onboarding/login/internal/page' -import SignupPage from './onboarding/signup/page' -import SignupInternalPage from './onboarding/signup/internal/page' -import WelcomePage from './welcome/page' -import TwitterCallbackPage from './twitter/callback/page' import AppLayout from './app/layout' -import PostListPage from './app/posts/page' import PostPage from './app/posts/[id]/page' +import PostListPage from './app/posts/page' +import HistoryPage from './app/profile/history/page' import ProfileLayout from './app/profile/layout' import ProfilePage from './app/profile/page' -import HistoryPage from './app/profile/history/page' import ReputationPage from './app/profile/reputation/page' import FullScreenLayout from './full-screen/layout' import WritePostPage from './full-screen/write-post/page' -import { ProtectedRoute } from '@/features/auth' -import { ErrorBoundary, ResetStorage } from '@/features/shared' -import { PATHS } from '@/constants/paths' +import OnboardingLayout from './onboarding/layout' +import LoginInternalPage from './onboarding/login/internal/page' +import LoginPage from './onboarding/login/page' +import SignupInternalPage from './onboarding/signup/internal/page' +import SignupPage from './onboarding/signup/page' +import TwitterCallbackPage from './twitter/callback/page' +import WelcomePage from './welcome/page' const router = createBrowserRouter([ { @@ -52,9 +52,9 @@ const router = createBrowserRouter([ }, { element: ( - + - + ), errorElement: , children: [ @@ -78,7 +78,7 @@ const router = createBrowserRouter([ element: , }, { - path: PATHS.HISTORTY, + path: PATHS.HISTORY, element: , }, ], @@ -91,9 +91,9 @@ const router = createBrowserRouter([ { path: PATHS.WRITE_POST, element: ( - - - + + , + ), }, ],