diff --git a/fe/src/app/components/ClientStorageHandler.tsx b/fe/src/app/components/ClientStorageHandler.tsx index 3ea14e7..e0489e2 100644 --- a/fe/src/app/components/ClientStorageHandler.tsx +++ b/fe/src/app/components/ClientStorageHandler.tsx @@ -1,12 +1,12 @@ "use client"; -import { useEffect } from "react"; +import { useEffect, useCallback } from "react"; import useLastUpdateStore from "../stores/useLastUpdateStore"; -const ClientStorageHandler = () => { +function ClientStorageHandler() { const { lastUpdated } = useLastUpdateStore(); - const clearLocalStorageIfExpired = () => { + const clearLocalStorageIfExpired = useCallback(() => { if (lastUpdated) { const elapsedTime = Date.now() - lastUpdated; if (elapsedTime > 24 * 60 * 60 * 1000) { @@ -15,20 +15,17 @@ const ClientStorageHandler = () => { localStorage.removeItem("lastUpdated"); } } - }; + }, [lastUpdated]); useEffect(() => { - const interval = setInterval( - () => { - clearLocalStorageIfExpired(); - }, - 24 * 60 * 60 * 1000 - ); + const interval = setInterval(() => { + clearLocalStorageIfExpired(); + }, 60 * 1000); return () => clearInterval(interval); - }, [lastUpdated]); + }, [clearLocalStorageIfExpired]); return null; -}; +} export default ClientStorageHandler; diff --git a/fe/src/app/event-maps/[id]/components/LoginModal.tsx b/fe/src/app/event-maps/[id]/components/LoginModal.tsx index 5751b2a..f2ce329 100644 --- a/fe/src/app/event-maps/[id]/components/LoginModal.tsx +++ b/fe/src/app/event-maps/[id]/components/LoginModal.tsx @@ -1,10 +1,10 @@ "use client"; import React, { useEffect, useState } from "react"; +import Image from "next/image"; import { useSwipeable } from "react-swipeable"; import { useRouter } from "next/navigation"; import { useLoginModalStore } from "../stores/useLoginModalStore"; -import Image from "next/image"; interface NonMember { nonMemberId: number; diff --git a/fe/src/app/event-maps/[id]/components/PingInformation.tsx b/fe/src/app/event-maps/[id]/components/PingInformation.tsx index 35e4401..dd89210 100644 --- a/fe/src/app/event-maps/[id]/components/PingInformation.tsx +++ b/fe/src/app/event-maps/[id]/components/PingInformation.tsx @@ -1,10 +1,10 @@ import React from "react"; import Image from "next/image"; +import useLastUpdateStore from "@/app/stores/useLastUpdateStore"; import { useMapStore } from "../stores/useMapStore"; import { useMarkerStore } from "../load-mappin/stores/useMarkerStore"; import { useLoginModalStore } from "../stores/useLoginModalStore"; import useTriggerStore from "../stores/useTriggerStore"; -import useLastUpdateStore from "@/app/stores/useLastUpdateStore"; export default function PingInformaion() { const { customMarkers } = useMarkerStore(); @@ -13,6 +13,46 @@ export default function PingInformaion() { const { openLoginModal } = useLoginModalStore(); const { setLastUpdated } = useLastUpdateStore(); const nonMemberId = localStorage.getItem("nonMemberId"); + + const selectedPing = customMarkers.find( + (ping) => ping.placeName === selectedMarkerName + ); + + const reissueAccessToken = async (refreshToken: string | null) => { + if (!refreshToken) { + console.error("Refresh Token이 없습니다."); + return null; + } + + try { + const response = await fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/auth/reissue`, + { + method: "POST", + headers: { + Authorization: `Bearer ${refreshToken}`, + "Content-Type": "application/json", + }, + } + ); + + if (response.ok) { + const data = await response.json(); + const newAccessToken = data.accessToken; + + // 새로 발급받은 Access Token 저장 + localStorage.setItem("authToken", newAccessToken); + console.log("Access Token 재발급 성공:", newAccessToken); + return newAccessToken; + } + console.error("Access Token 재발급 실패:", response.status); + return null; + } catch (error) { + console.error("토큰 재발급 중 오류 발생:", error); + return null; + } + }; + const sendPingApi = async () => { try { const token = localStorage.getItem("authToken"); @@ -36,59 +76,21 @@ export default function PingInformaion() { if (errorResponse.subCode === 4) { const newAccessToken = await reissueAccessToken(token); if (newAccessToken) { - await sendPingApi(); - } else { - openLoginModal(); + return await sendPingApi(); } - } else { openLoginModal(); + return null; } } + openLoginModal(); throw new Error(`HTTP error! status: ${response.status}`); } toggleTrigger(); - console.log("API Response:"); - const currentTime = Date.now(); - setLastUpdated(currentTime); + setLastUpdated(Date.now()); + return true; } catch (error) { console.error("API Error:", error); - } - }; - - const reissueAccessToken = async (refreshToken: string | null) => { - if (!refreshToken) { - console.error("Refresh Token이 없습니다."); - return null; - } - - try { - const response = await fetch( - `${process.env.NEXT_PUBLIC_API_BASE_URL}/auth/reissue`, - { - method: "POST", - headers: { - Authorization: `Bearer ${refreshToken}`, - "Content-Type": "application/json", - }, - } - ); - - if (response.ok) { - const data = await response.json(); - const newAccessToken = data.accessToken; - - // 새로 발급받은 Access Token 저장 - localStorage.setItem("authToken", newAccessToken); - - console.log("Access Token 재발급 성공:", newAccessToken); - return newAccessToken; - } else { - console.error("Access Token 재발급 실패:", response.status); - return null; - } - } catch (error) { - console.error("토큰 재발급 중 오류 발생:", error); return null; } }; @@ -98,9 +100,6 @@ export default function PingInformaion() { console.log("Button clicked: Open login modal"); }; - const selectedPing = customMarkers.find( - (ping) => ping.placeName === selectedMarkerName - ); console.log(Number(nonMemberId)); console.log(selectedPing?.nonMembers); const isAlreadyPing = selectedPing?.nonMembers.some((member) => { diff --git a/fe/src/app/event-maps/[id]/login/pin-check/components/LoginPinCheck.tsx b/fe/src/app/event-maps/[id]/login/pin-check/components/LoginPinCheck.tsx index 9d44439..71dea02 100644 --- a/fe/src/app/event-maps/[id]/login/pin-check/components/LoginPinCheck.tsx +++ b/fe/src/app/event-maps/[id]/login/pin-check/components/LoginPinCheck.tsx @@ -4,7 +4,6 @@ import React, { useRef, useState, useEffect, useCallback } from "react"; import Image from "next/image"; import { useSearchParams, useParams } from "next/navigation"; import { v4 as uuidv4 } from "uuid"; // UUID를 생성하기 위해 추가 -import { useLoginModalStore } from "../../../stores/useLoginModalStore"; export interface PasswordInputProps { iconUrl: string | null; @@ -63,7 +62,7 @@ export default function PasswordInput({ iconUrl }: PasswordInputProps) { setHasError(true); alert("로그인 API 호출에 실패했습니다. 다시 시도해주세요."); } - }, [nonMemberId, password, searchParams]); + }, [nonMemberId, password, id]); useEffect(() => { if (password.every((digit) => digit !== "")) {