diff --git a/src/App.tsx b/src/App.tsx index a6a34c3..6833aa0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -72,7 +72,7 @@ function App() { }> } /> - } /> + } /> } /> diff --git a/src/components/building/BuildingLoginCard.tsx b/src/components/building/BuildingLoginCard.tsx index 2847799..fcf7155 100644 --- a/src/components/building/BuildingLoginCard.tsx +++ b/src/components/building/BuildingLoginCard.tsx @@ -28,6 +28,7 @@ const BuildingLoginCard: React.FC = ({ onSwitch: _, isExiting, direction, if (token) { localStorage.setItem("accessToken", token); onLogin(); + sessionStorage.clear(); navigate("/building/select"); } else { setError("로그인 실패: 엑세스 토큰이 없음"); diff --git a/src/components/buttons/LogoutButton.tsx b/src/components/buttons/LogoutButton.tsx index 4b80188..d10a015 100644 --- a/src/components/buttons/LogoutButton.tsx +++ b/src/components/buttons/LogoutButton.tsx @@ -14,9 +14,11 @@ const LogoutButton: React.FC = () => { try { await adminLogout(); localStorage.clear(); + sessionStorage.clear(); navigate("/login"); } catch (err: any) { localStorage.clear(); + sessionStorage.clear(); const message = err?.message ?? "로그아웃 실패"; alert(message); console.warn("관리자 로그아웃 실패:", err); diff --git a/src/components/zone/ZoneLoginCard.tsx b/src/components/zone/ZoneLoginCard.tsx index f439364..607b3c4 100644 --- a/src/components/zone/ZoneLoginCard.tsx +++ b/src/components/zone/ZoneLoginCard.tsx @@ -28,6 +28,7 @@ const ZoneLoginCard: React.FC = ({ onSwitch: _, isExiting, direction, onL if (token) { localStorage.setItem("accessToken", token); onLogin(); + sessionStorage.clear(); navigate("/zone/select"); } else { setError("로그인 실패: 엑세스 토큰이 없음"); diff --git a/src/components/zone/ZoneSelectMainZoneCard.tsx b/src/components/zone/ZoneSelectMainZoneCard.tsx index 53a5c43..5829abf 100644 --- a/src/components/zone/ZoneSelectMainZoneCard.tsx +++ b/src/components/zone/ZoneSelectMainZoneCard.tsx @@ -76,7 +76,7 @@ const ZoneSelectMainZoneCard: React.FC = ({ buildingId, buildingName, onB localStorage.setItem("deviceAreaCode", areaCode); localStorage.setItem("zoneName", areaName); localStorage.setItem("buildingName", buildingName); - navigate("/qr"); + navigate("/qr", { replace: false }); }; return ( diff --git a/src/contexts/axiosWithAuthorization.tsx b/src/contexts/axiosWithAuthorization.tsx index 9edefb6..dfa33cd 100644 --- a/src/contexts/axiosWithAuthorization.tsx +++ b/src/contexts/axiosWithAuthorization.tsx @@ -72,7 +72,8 @@ axiosWithAuthorization.interceptors.response.use( } catch (refreshError) { console.error("엑세스 토큰 재발급 실패:", refreshError); localStorage.clear(); - window.location.href = "/admin/login"; + sessionStorage.clear(); + window.location.href = "/login"; return Promise.reject(refreshError); } } diff --git a/src/pages/QRCodeScanner.tsx b/src/pages/QRCodeScanner.tsx index 56e39c9..b117c1a 100644 --- a/src/pages/QRCodeScanner.tsx +++ b/src/pages/QRCodeScanner.tsx @@ -149,7 +149,8 @@ const QRCodeScanner = () => { console.error("카메라 정리 중 오류", err); } finally { scannerRef.current = null; - navigate(-1); + sessionStorage.setItem("zoneSelectStep", 'zone'); + navigate(-1); } } else { navigate(-1); diff --git a/src/pages/ZoneSelectPage.tsx b/src/pages/ZoneSelectPage.tsx index cdff79a..b6c9594 100644 --- a/src/pages/ZoneSelectPage.tsx +++ b/src/pages/ZoneSelectPage.tsx @@ -1,5 +1,6 @@ import './css/ZoneSelectPage.css'; import { useEffect, useState } from 'react'; +import { useNavigate, useLocation } from 'react-router-dom'; import ZoneSelectGreenCard from '../components/zone/ZoneSelectGreenCard'; import ZoneSelectWhiteCard from '../components/zone/ZoneSelectWhiteCard'; @@ -9,25 +10,85 @@ import ZoneSelectMainZoneCard from '../components/zone/ZoneSelectMainZoneCard'; import zonewrapperBackground from '../assets/images/zone-background.png'; const ZoneSelectPage: React.FC = () => { - const [buildingId, setBuildingId] = useState(null); - const [buildingName, setBuildingName] = useState(null); + const navigate = useNavigate(); + const location = useLocation(); + const [buildingId, setBuildingId] = useState(sessionStorage.getItem("buildingId")); + const [buildingName, setBuildingName] = useState(sessionStorage.getItem("buildingName")); const [currentStep, setCurrentStep] = useState<'white' | 'building' | 'zone'>('white'); + const [isInternalChange, setIsInternalChange] = useState(false); useEffect(() => { - const timer = setTimeout(() => { - setCurrentStep('building'); - }, 800); - - return () => clearTimeout(timer); + const savedStep = sessionStorage.getItem("zoneSelectStep") as 'white' | 'building' | 'zone' | null; + if (savedStep) { + setCurrentStep(savedStep); + } else { + const timer = setTimeout(() => { + setCurrentStep('building'); + sessionStorage.setItem("zoneSelectStep", 'building'); + }, 800); + return () => clearTimeout(timer); + } }, []); const handleNext = (selectedBuildingId: string, selectedBuildingName: string) => { setBuildingId(selectedBuildingId); setBuildingName(selectedBuildingName); localStorage.setItem("buildingName", selectedBuildingName); - setCurrentStep('zone'); + + sessionStorage.setItem("buildingId", selectedBuildingId); + sessionStorage.setItem("buildingName", selectedBuildingName); + sessionStorage.setItem("zoneSelectStep", 'zone'); + + setIsInternalChange(true); + setCurrentStep('zone'); + }; + + const handleBack = () => { + sessionStorage.setItem("zoneSelectStep", 'building'); + setIsInternalChange(true); + setCurrentStep('building'); }; + useEffect(() => { + const handlePopState = () => { + const savedStep = sessionStorage.getItem("zoneSelectStep") as 'white' | 'building' | 'zone' | null; + if (savedStep) { + setCurrentStep(savedStep); + } else { + setCurrentStep('building'); + } + }; + + window.addEventListener('popstate', handlePopState); + return () => window.removeEventListener('popstate', handlePopState); + }, []); + + useEffect(() => { + if (!isInternalChange) return; + + if (currentStep === 'building' && location.pathname !== '/zone/select/building') { + navigate('/zone/select/building', { replace: false }); + } else if (currentStep === 'zone' && location.pathname !== '/zone/select/zone') { + navigate('/zone/select/zone', { replace: false }); + } + + setIsInternalChange(false); // reset flag + }, [currentStep, navigate, location.pathname, isInternalChange]); + + useEffect(() => { + if (location.pathname === '/zone/select') { + navigate('/zone/select/building', { replace: true }); + } + }, [location.pathname, navigate]); + + useEffect(() => { + if (location.pathname === '/zone/select/building') { + sessionStorage.setItem('zoneSelectStep', 'building'); + } else if (location.pathname === '/zone/select/zone') { + sessionStorage.setItem('zoneSelectStep', 'zone'); + } + }, [location.pathname]); + return (
{
{currentStep === 'white' && } - {currentStep === 'building' && ( - - )} + {currentStep === 'building' && } {currentStep === 'zone' && buildingId && buildingName && ( setCurrentStep('building')} + onBack={handleBack} /> )}