11// src/pages/PostDetail.jsx
22import React , { useEffect , useState , useMemo , useRef , useCallback } from "react" ;
3- import { useParams , useNavigate } from "react-router-dom" ;
3+ import { useParams , useNavigate , useLocation } from "react-router-dom" ;
44import "./PostDetail.css" ;
55import config from "../../config" ;
66import { promptLogin } from "../../utils/auth" ;
@@ -29,6 +29,14 @@ const deriveCommentCount = (resp, data) => {
2929export default function PostDetail ( ) {
3030 const { id } = useParams ( ) ; // /community/post/:id
3131 const navigate = useNavigate ( ) ;
32+ const location = useLocation ( ) ;
33+
34+ const [ authState , setAuthState ] = useState ( ( ) => ( {
35+ token : localStorage . getItem ( "token" ) ,
36+ userId : localStorage . getItem ( "userId" ) ,
37+ username : localStorage . getItem ( "username" ) ,
38+ role : localStorage . getItem ( "role" ) ,
39+ } ) ) ;
3240
3341 const [ post , setPost ] = useState ( null ) ;
3442 const [ comments , setComments ] = useState ( [ ] ) ;
@@ -56,13 +64,15 @@ export default function PostDetail() {
5664 const [ replyContent , setReplyContent ] = useState ( "" ) ;
5765
5866 // 토큰 및 인증 헤더 (백틱 사용 수정 반영)
59- const tokenRaw = useMemo ( ( ) => localStorage . getItem ( "token" ) , [ ] ) ;
60- const authHeader = tokenRaw
61- ? tokenRaw . startsWith ( "Bearer " ) ? tokenRaw : `Bearer ${ tokenRaw } `
62- : null ;
63- const currentUserId = useMemo ( ( ) => localStorage . getItem ( "userId" ) || "" , [ ] ) ;
64- const currentUsername = useMemo ( ( ) => localStorage . getItem ( "username" ) || "" , [ ] ) ;
65- const currentRole = useMemo ( ( ) => ( localStorage . getItem ( "role" ) || "" ) . toUpperCase ( ) , [ ] ) ;
67+ const authHeader = useMemo ( ( ) => {
68+ const token = authState . token ;
69+ if ( ! token ) return null ;
70+ return token . startsWith ( "Bearer " ) ? token : `Bearer ${ token } ` ;
71+ } , [ authState . token ] ) ;
72+
73+ const currentUserId = useMemo ( ( ) => authState . userId || "" , [ authState . userId ] ) ;
74+ const currentUsername = useMemo ( ( ) => authState . username || "" , [ authState . username ] ) ;
75+ const currentRole = useMemo ( ( ) => ( authState . role || "" ) . toUpperCase ( ) , [ authState . role ] ) ;
6676 const hasManageRole = useMemo ( ( ) => [ "ADMIN" , "MANAGER" , "ROLE_ADMIN" , "ROLE_MANAGER" ] . includes ( currentRole ) , [ currentRole ] ) ;
6777 const matchesCurrentUser = useCallback ( ( writerName , writerId ) => {
6878 if ( writerId && currentUserId ) return String ( writerId ) === String ( currentUserId ) ;
@@ -74,6 +84,41 @@ export default function PostDetail() {
7484 return matchesCurrentUser ( writerName , writerId ) ;
7585 } , [ hasManageRole , matchesCurrentUser ] ) ;
7686
87+ useEffect ( ( ) => {
88+ const syncAuth = ( ) => {
89+ setAuthState ( ( prev ) => {
90+ const next = {
91+ token : localStorage . getItem ( "token" ) ,
92+ userId : localStorage . getItem ( "userId" ) ,
93+ username : localStorage . getItem ( "username" ) ,
94+ role : localStorage . getItem ( "role" ) ,
95+ } ;
96+ if (
97+ prev . token === next . token &&
98+ prev . userId === next . userId &&
99+ prev . username === next . username &&
100+ prev . role === next . role
101+ ) {
102+ return prev ;
103+ }
104+ return next ;
105+ } ) ;
106+ } ;
107+
108+ window . addEventListener ( "storage" , syncAuth ) ;
109+ window . addEventListener ( "dv:auth-updated" , syncAuth ) ;
110+
111+ return ( ) => {
112+ window . removeEventListener ( "storage" , syncAuth ) ;
113+ window . removeEventListener ( "dv:auth-updated" , syncAuth ) ;
114+ } ;
115+ } , [ ] ) ;
116+
117+ const redirectPath = useMemo ( ( ) => `${ location . pathname } ${ location . search || "" } ` , [ location . pathname , location . search ] ) ;
118+ const requestLogin = useCallback ( ( ) => {
119+ promptLogin ( undefined , { redirectTo : redirectPath } ) ;
120+ } , [ redirectPath ] ) ;
121+
77122 // 좋아요 수 및 내 상태 재조회
78123 const refreshLikeStatus = async ( ) => {
79124 try {
@@ -209,7 +254,7 @@ export default function PostDetail() {
209254 // 좋아요 토글
210255 const handleToggleLike = async ( ) => {
211256 if ( ! authHeader ) {
212- promptLogin ( ) ;
257+ requestLogin ( ) ;
213258 return ;
214259 }
215260 if ( liking ) return ;
@@ -263,7 +308,7 @@ export default function PostDetail() {
263308 const handleCreateComment = async ( ) => {
264309 if ( ! newComment . trim ( ) ) return ;
265310 if ( ! authHeader ) {
266- promptLogin ( ) ;
311+ requestLogin ( ) ;
267312 return ;
268313 }
269314
@@ -300,7 +345,7 @@ export default function PostDetail() {
300345 const handleCreateReply = async ( parentId ) => {
301346 if ( ! replyContent . trim ( ) ) return ;
302347 if ( ! authHeader ) {
303- promptLogin ( ) ;
348+ requestLogin ( ) ;
304349 return ;
305350 }
306351
@@ -335,7 +380,7 @@ export default function PostDetail() {
335380
336381 const handleDeletePost = async ( ) => {
337382 if ( ! authHeader ) {
338- promptLogin ( ) ;
383+ requestLogin ( ) ;
339384 return ;
340385 }
341386 if ( deletingPost ) return ;
@@ -364,7 +409,7 @@ export default function PostDetail() {
364409
365410 const handleDeleteComment = async ( commentId ) => {
366411 if ( ! authHeader ) {
367- promptLogin ( ) ;
412+ requestLogin ( ) ;
368413 return ;
369414 }
370415 if ( ! commentId || deletingCommentId === commentId ) return ;
0 commit comments