diff --git a/AppNavigator.js b/AppNavigator.js
index f67bdcc..20c285b 100644
--- a/AppNavigator.js
+++ b/AppNavigator.js
@@ -2,13 +2,11 @@ import { NavigationContainer, DefaultTheme } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useState, useEffect } from 'react';
import Ionicons from '@expo/vector-icons/Ionicons';
-import { StatusBar, View } from 'react-native';
-import AsyncStorage from '@react-native-async-storage/async-storage';
-
-import { setLogoutCallback } from './handler/logoutHandler';
+import { StatusBar } from 'react-native';
import HomeButtonController from './components/buttons/HomeButtonController';
import LoadingOverlay from './components/loadings/LoadingOverlay';
import { getMyInfo } from './apis/MyPageApi';
+import { useAuthStore } from './stores/authStore';
// 로그인 전 페이지
import WelcomePage from './pages/WelcomePage';
@@ -24,15 +22,21 @@ import AccessListPage from './pages/AccessListPage';
import MyAccessListPage from './pages/MyAccessListPage';
import AccessRequestPage from './pages/AccessRequestPage';
import AccessRequestRolePage from './pages/AccessRequestRolePage';
-
import { colors } from './constants/colors';
const Stack = createStackNavigator();
export default function AppNavigator() {
- const [isLoggedIn, setIsLoggedIn] = useState(true); // 로그인 상태
+ const {
+ isLoggedIn,
+ setIsLoggedIn,
+ accessToken,
+ setLoading,
+ loading,
+ setAccessToken,
+ clearAccessToken,
+ } = useAuthStore();
const [navState, setNavState] = useState(null);
- const [loading, setLoading] = useState(false); // 토큰 확인 중 상태
// 앱 시작 시 토큰 유효성 확인
useEffect(() => {
@@ -40,16 +44,14 @@ export default function AppNavigator() {
setLoading(true);
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
- const token = await AsyncStorage.getItem('accessToken');
- if (token) {
+ if (accessToken) {
// 회원 정보 조회로 토큰 유효성 검증
try {
await getMyInfo();
- setIsLoggedIn(true); // 토큰 유효
+ setAccessToken(accessToken); // 토큰 유효
} catch (err) {
//에러 발생 시
- setIsLoggedIn(false);
- await AsyncStorage.removeItem('accessToken');
+ clearAccessToken();
}
} else {
setIsLoggedIn(false);
@@ -63,11 +65,6 @@ export default function AppNavigator() {
checkToken();
}, []);
- // 앱 시작시 logoutHandler.js에 콜백 함수 등록
- useEffect(() => {
- setLogoutCallback(() => setIsLoggedIn(false));
- }, []);
-
const navTheme = {
...DefaultTheme,
colors: {
@@ -100,9 +97,7 @@ export default function AppNavigator() {
component={MainPage}
options={{ headerShown: false, title: '홈' }}
/>
-
- {(props) => }
-
+
-
- {(props) => }
-
+
{
const response = await axios.get('/hospitals');
-
return response.data.data;
};
diff --git a/apis/AxiosInstance.js b/apis/AxiosInstance.js
index 8bb45eb..b12850a 100644
--- a/apis/AxiosInstance.js
+++ b/apis/AxiosInstance.js
@@ -1,7 +1,6 @@
import axios from 'axios';
import Constants from 'expo-constants';
-import AsyncStorage from '@react-native-async-storage/async-storage';
-import { runLogoutCallback } from '../handler/logoutHandler';
+import { useAuthStore } from '../stores/authStore';
const BASE_URL = Constants.expoConfig.extra.BASE_URL;
@@ -12,7 +11,8 @@ const instance = axios.create({
// accessToken 가져오는 함수
const getAccessToken = async () => {
- return await AsyncStorage.getItem('accessToken');
+ const { accessToken } = useAuthStore.getState();
+ return accessToken;
};
// 요청 인터셉터: 모든 요청에 accessToken 자동 첨부
@@ -23,9 +23,6 @@ instance.interceptors.request.use(
config.headers = config.headers || {}; // headers가 없으면 빈 객체로 초기화
config.headers.Authorization = `Bearer ${token}`; // Authorization 헤더에 Bearer 토큰 추가
}
- // 요청 정보 로그
- // console.log('[axios request] url:', config.url);
- // console.log('[axios request] headers:', config.headers);
return config;
},
(error) => Promise.reject(error),
@@ -34,9 +31,6 @@ instance.interceptors.request.use(
// 응답 인터셉터: 401(accessToken 만료) → 토큰 재발급 후 재요청
instance.interceptors.response.use(
(response) => {
- // 응답 로그
- // console.log('[axios response] url:', response.config.url);
- // console.log('[axios response] status:', response.status);
return response;
},
async (error) => {
@@ -44,6 +38,7 @@ instance.interceptors.response.use(
// 401 에러이면서 아직 재시도 하지 않은 요청만 처리
if (error.response && error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
+ const { setAccessToken, clearAccessToken } = useAuthStore.getState();
try {
// 토큰 재발급 요청
const refreshResponse = await axios.post(
@@ -57,21 +52,16 @@ instance.interceptors.response.use(
},
},
);
- //재발급 응답 헤더 로그
- //console.log('refreshResponse.headers:', refreshResponse.headers);
//authorization, Authorization 대소문자 상관없시 추출하도록함
//새 accessToken을 헤더에서 추출
- let newAccessToken = refreshResponse.headers['authorization'];
- //새 accessTokem 로그
- //console.log('newAccessToken:', newAccessToken);
- if (!newAccessToken) {
- newAccessToken = refreshResponse.headers['Authorization'];
- }
+ let newAccessToken =
+ refreshResponse.headers['authorization'] || refreshResponse.headers['Authorization'];
+
// newAccessToken이 있으면, 'Bearer ' 접두사 제거 후 공백 제거 후 AsyncStorage에 저장
if (newAccessToken) {
const tokenValue = newAccessToken.replace('Bearer ', '').trim();
- await AsyncStorage.setItem('accessToken', tokenValue);
+ setAccessToken(tokenValue);
// 기존 헤더는 spread로 보존, Authorization만 교체
originalRequest.headers = {
@@ -90,20 +80,13 @@ instance.interceptors.response.use(
// 서버가 토큰 바로 반영 안 할 때를 대비해 약간 딜레이
await new Promise((resolve) => setTimeout(resolve, 200));
-
- // 재요청 전 로그
- //console.log('재요청 config:', originalRequest);
-
//새 accessToken으로 원래 요청을 재시도
return instance(originalRequest);
}
//새 accessToken을 받지 못한 경우 에러 반환
return Promise.reject(new Error('새로운 accessToken을 받지 못했습니다.'));
} catch (refreshError) {
- //토큰 재발급 실패 시
- await AsyncStorage.removeItem('accessToken');
- // 로그아웃 콜백 실행
- runLogoutCallback();
+ clearAccessToken();
return Promise.reject(refreshError); //에러 반환
}
}
diff --git a/app.config.js b/app.config.js
index ff3e665..23490b4 100644
--- a/app.config.js
+++ b/app.config.js
@@ -25,8 +25,8 @@ export default {
favicon: './assets/images/logoIcon.png',
},
extra: {
- BASE_URL: 'http://keywe.site', // EKS 사용시
- //BASE_URL: 'http://192.168.0.181:8081', // 도커 사용시 - 본인 pc IPv4 주소로 수정하세용
+ //BASE_URL: 'http://keywe.site', // EKS 사용시
+ BASE_URL: 'http://192.168.0.225:8081', // 도커 사용시 - 본인 pc IPv4 주소로 수정하세용
},
},
};
diff --git a/components/accessRequest/GuardianVerificationForm.js b/components/accessRequest/GuardianVerificationForm.js
index 28c658c..1bf805e 100644
--- a/components/accessRequest/GuardianVerificationForm.js
+++ b/components/accessRequest/GuardianVerificationForm.js
@@ -4,8 +4,10 @@ import { useState } from 'react';
import NormalInput from '../textinputs/NormalInput';
import NormalAlert from '../alerts/NormalAlert';
import { verifyPatientCode } from '../../apis/AccessRequestApi';
+import { useAuthStore } from '../../stores/authStore';
const GuardianVerificationForm = ({ onVerifiedHandler }) => {
+ const { setLoading } = useAuthStore();
const [patientCode, setPatientCode] = useState(''); // 환자 번호 관리
const [isVerified, setIsVerified] = useState(false);
const [alertMessage, setAlertMessage] = useState('');
@@ -15,6 +17,7 @@ const GuardianVerificationForm = ({ onVerifiedHandler }) => {
// 환자 번호 검증 버튼 클릭 핸들러
const handleVerifyPatient = async () => {
+ setLoading(true);
try {
await verifyPatientCode(patientCode);
@@ -29,6 +32,8 @@ const GuardianVerificationForm = ({ onVerifiedHandler }) => {
setAlertMessage(`일치하는 환자 정보가\n존재하지 않습니다.\n확인 후 다시 입력해 주세요.`);
setShowVerifiedAlert(true);
setPatientCode('');
+ } finally {
+ setLoading(false);
}
};
diff --git a/components/accessRequest/PatientVerficationForm.js b/components/accessRequest/PatientVerficationForm.js
index 207f08a..9eb3537 100644
--- a/components/accessRequest/PatientVerficationForm.js
+++ b/components/accessRequest/PatientVerficationForm.js
@@ -5,8 +5,10 @@ import { useState, useEffect } from 'react';
import NormalInput from '../textinputs/NormalInput';
import NormalAlert from '../alerts/NormalAlert';
import { getMyInfo } from '../../apis/MyPageApi';
+import { useAuthStore } from '../../stores/authStore';
const PatientVerficationForm = ({ onVerifiedHandler }) => {
+ const { setLoading } = useAuthStore();
const [userInfo, setUserInfo] = useState({ name: '', birth: '', contact: '' }); // 회원 정보 관리
const [isVerified, setIsVerified] = useState(false);
const [alertMessage, setAlertMessage] = useState('');
@@ -17,6 +19,7 @@ const PatientVerficationForm = ({ onVerifiedHandler }) => {
// 사용자 정보 불러오기
useEffect(() => {
const loadInfo = async () => {
+ setLoading(true);
try {
const data = await getMyInfo();
setUserInfo({
@@ -26,6 +29,8 @@ const PatientVerficationForm = ({ onVerifiedHandler }) => {
});
} catch (error) {
console.log('내 정보 조회 실패:', error.response?.data || error.message);
+ } finally {
+ setLoading(false);
}
};
@@ -33,6 +38,7 @@ const PatientVerficationForm = ({ onVerifiedHandler }) => {
}, []);
const handleVerifyPatient = async () => {
+ setLoading(true);
// TODO: 환자 번호 검증 API 연결
// 임시 검증 로직
try {
@@ -53,6 +59,8 @@ const PatientVerficationForm = ({ onVerifiedHandler }) => {
} catch (error) {
setIsVerified(false);
setShowVerifiedAlert(true);
+ } finally {
+ setLoading(false);
}
};
diff --git a/handler/logoutHandler.js b/handler/logoutHandler.js
deleted file mode 100644
index 471cd66..0000000
--- a/handler/logoutHandler.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// 콜백 함수 저장하는 변수
-let logoutCallback = null;
-
-export function setLogoutCallback(cb) {
- logoutCallback = cb;
-}
-
-// 설정된 콜백 함수를 실행하는 함수
-export function runLogoutCallback() {
- if (logoutCallback) logoutCallback();
-}
diff --git a/modals/PasswordConfirmModal.js b/modals/PasswordConfirmModal.js
index d25784c..aaf3d9f 100644
--- a/modals/PasswordConfirmModal.js
+++ b/modals/PasswordConfirmModal.js
@@ -5,7 +5,6 @@ import NormalInput from '../components/textinputs/NormalInput';
import NormalButton from '../components/buttons/NormalButton';
import WaveHeader from '../components/headers/WaveHeader';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
-import AsyncStorage from '@react-native-async-storage/async-storage';
import { verifyPassword } from '../apis/PasswordApi';
const PasswordConfirmModal = ({ visible = true, onCloseHandler }) => {
@@ -34,8 +33,6 @@ const PasswordConfirmModal = ({ visible = true, onCloseHandler }) => {
}
try {
- // 토큰 불러오기
- const token = await AsyncStorage.getItem('accessToken');
await verifyPassword(password);
// 모달창 닫기
@@ -45,6 +42,7 @@ const PasswordConfirmModal = ({ visible = true, onCloseHandler }) => {
setErrorText('비밀번호가 일치하지 않습니다. 다시 입력해주세요.');
}
};
+ // 모달 오류시 임시 코드
// const handleConfirm = async () => {
// if (!isValidPassword(password)) {
// setErrorText('8자 이상, 영문/숫자/특수문자를 포함해야 합니다.');
diff --git a/package-lock.json b/package-lock.json
index 3ee9b1c..d1d6f90 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,7 +25,8 @@
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "^4.12.0",
"react-native-screens": "~4.4.0",
- "react-native-vector-icons": "^10.2.0"
+ "react-native-vector-icons": "^10.2.0",
+ "zustand": "^5.0.4"
},
"devDependencies": {
"@babel/core": "^7.20.0",
@@ -13213,6 +13214,35 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zustand": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.4.tgz",
+ "integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=18.0.0",
+ "immer": ">=9.0.6",
+ "react": ">=18.0.0",
+ "use-sync-external-store": ">=1.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "use-sync-external-store": {
+ "optional": true
+ }
+ }
}
}
}
diff --git a/package.json b/package.json
index 634721a..8102387 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,8 @@
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "^4.12.0",
"react-native-screens": "~4.4.0",
- "react-native-vector-icons": "^10.2.0"
+ "react-native-vector-icons": "^10.2.0",
+ "zustand": "^5.0.4"
},
"devDependencies": {
"@babel/core": "^7.20.0",
diff --git a/pages/AccessRequestPage.js b/pages/AccessRequestPage.js
index d584740..0eb83fc 100644
--- a/pages/AccessRequestPage.js
+++ b/pages/AccessRequestPage.js
@@ -4,14 +4,17 @@ import { styles } from './styles/AccessRequestPage.styles';
import NormalInput from '../components/textinputs/NormalInput';
import NormalList from '../components/lists/NormalList';
import { getHospitalList } from '../apis/AccessRequestApi';
+import { useAuthStore } from '../stores/authStore';
const AccessRequestPage = () => {
+ const { setLoading } = useAuthStore();
const [searchText, setSearchText] = useState('');
const [hospitalName, setHospitalName] = useState([]);
// 병원 목록 불러오기
useEffect(() => {
const getHospitalsName = async () => {
+ setLoading(true);
try {
const data = await getHospitalList();
console.log(data);
@@ -19,9 +22,10 @@ const AccessRequestPage = () => {
setHospitalName(data);
} catch (error) {
console.error('병원 목록 불러오기 실패:', error);
+ } finally {
+ setLoading(false);
}
};
-
getHospitalsName();
}, []);
diff --git a/pages/AccessRequestRolePage.js b/pages/AccessRequestRolePage.js
index 4c81295..5772caa 100644
--- a/pages/AccessRequestRolePage.js
+++ b/pages/AccessRequestRolePage.js
@@ -10,8 +10,10 @@ import PatientVerficationForm from '../components/accessRequest/PatientVerficati
import GuardianVerificationForm from '../components/accessRequest/GuardianVerificationForm';
import { useNavigation } from '@react-navigation/native';
import { getAvailableDates } from '../apis/AccessRequestApi';
+import { useAuthStore } from '../stores/authStore';
const AccessRequestRolePage = ({ route }) => {
+ const { setLoading } = useAuthStore();
const { hospitalId, hospitalName } = route.params;
const [role, setRole] = useState('patient');
@@ -23,11 +25,14 @@ const AccessRequestRolePage = ({ route }) => {
// 방문 가능 날짜 불러오기
useEffect(() => {
const fetchAvailableDates = async () => {
+ setLoading(true);
try {
const dates = await getAvailableDates(hospitalId);
setAvailableDates(dates);
} catch (error) {
console.error('방문 가능 날짜 불러오기 실패:', error);
+ } finally {
+ setLoading(false);
}
};
diff --git a/pages/ChangePasswordPage.js b/pages/ChangePasswordPage.js
index f87b793..3f9217c 100644
--- a/pages/ChangePasswordPage.js
+++ b/pages/ChangePasswordPage.js
@@ -8,9 +8,10 @@ import { useNavigation } from '@react-navigation/native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import NormalAlert from '../components/alerts/NormalAlert';
import { updatePassword } from '../apis/PasswordApi';
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import { useAuthStore } from '../stores/authStore';
const ChangePasswordPage = () => {
+ const { setLoading } = useAuthStore();
const [originalPassword, setOriginalPassword] = useState(''); // 기존 비밀번호
const [newPassword, setNewPassword] = useState(''); // 새 비밀번호
const [confirmNewPassword, setConfirmNewPassword] = useState(''); // 새 비밀번호 확인
@@ -48,9 +49,8 @@ const ChangePasswordPage = () => {
// 비밀번호 변경 확인 버튼 클릭 핸들러
const handleConfirmChange = async () => {
setShowConfirmAlert(false);
+ setLoading(true);
try {
- // 토큰 불러오기
- const token = await AsyncStorage.getItem('accessToken');
await updatePassword({ originalPassword, newPassword });
setTimeout(() => {
@@ -68,6 +68,8 @@ const ChangePasswordPage = () => {
setErrorAlertMessage(message);
setShowErrorAlert(true);
+ } finally {
+ setLoading(false);
}
};
diff --git a/pages/LoginPage.js b/pages/LoginPage.js
index bdc2672..a5b852a 100644
--- a/pages/LoginPage.js
+++ b/pages/LoginPage.js
@@ -8,11 +8,11 @@ import GrayUnderlineButton from '../components/buttons/GrayButton';
import { useNavigation } from '@react-navigation/native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import NormalAlert from '../components/alerts/NormalAlert';
-import AsyncStorage from '@react-native-async-storage/async-storage';
import { loginUser } from '../apis/LoginApi';
-import LoadingOverlay from '../components/loadings/LoadingOverlay';
+import { useAuthStore } from '../stores/authStore';
-const LoginPage = ({ setIsLoggedIn }) => {
+const LoginPage = () => {
+ const { setIsLoggedIn, setLoading, setOnlyAccessToken } = useAuthStore();
//상태 변수
const [form, setForm] = useState({
email: '', // 이메일
@@ -20,7 +20,7 @@ const LoginPage = ({ setIsLoggedIn }) => {
});
// Alert 관리 상태변수
- const [showAlert, setShowAlert] = useState(null);
+ const [showAlert, setShowAlert] = useState(false);
const [showErrorAlert, setShowErrorAlert] = useState(false);
//이메일 형식 검증 함수
@@ -34,7 +34,6 @@ const LoginPage = ({ setIsLoggedIn }) => {
const [error, setError] = useState({}); // 에러 메시지
const [isPwValid, setIsPwValid] = useState(false); //비밀번호 유효성
- const [loading, setLoading] = useState(false); // 토큰 확인 중 상태
const handleInputChange = (field, value) => {
// field : 바꿀 필드의 이름 (ex. name), value : 입력된 새로운 값
@@ -70,9 +69,9 @@ const LoginPage = ({ setIsLoggedIn }) => {
try {
//로그인 API 연결
const data = await loginUser(form);
+ //토큰 있어야만 저장하도록함
if (data && data.data.accessToken) {
- //토큰 있어야만 저장하도록함
- await AsyncStorage.setItem('accessToken', data.data.accessToken);
+ setOnlyAccessToken(data.data.accessToken);
setShowAlert(true);
} else {
setShowErrorAlert(true);
@@ -100,7 +99,6 @@ const LoginPage = ({ setIsLoggedIn }) => {
return (
<>
-
{
+ const { setLoading } = useAuthStore();
const [myAccessList, setMyAccessList] = useState([]);
// Alert 관리 상태변수
@@ -16,15 +18,17 @@ const MyAccessListPage = () => {
// 출입증 목록 불러오기
useEffect(() => {
const getMyAccessList = async () => {
+ setLoading(true);
try {
const data = await getAccessList();
console.log(data.data.data);
setMyAccessList(data.data.data);
} catch (error) {
console.error('출입증 목록 불러오기 실패: ', error);
+ } finally {
+ setLoading(false);
}
};
-
getMyAccessList();
}, []);
diff --git a/pages/MyPage.js b/pages/MyPage.js
index 9c94625..0978053 100644
--- a/pages/MyPage.js
+++ b/pages/MyPage.js
@@ -8,9 +8,10 @@ import GrayButton from '../components/buttons/GrayButton';
import { useNavigation } from '@react-navigation/native';
import NormalAlert from '../components/alerts/NormalAlert';
import { deleteUser, getMyInfo, logoutUser } from '../apis/MyPageApi';
-import AsyncStorage from '@react-native-async-storage/async-storage';
+import { useAuthStore } from '../stores/authStore';
-export default function MyPage({ setIsLoggedIn }) {
+export default function MyPage() {
+ const { accessToken, clearAccessToken } = useAuthStore();
const [isVerified, setIsVerified] = useState(false); // 비밀번호 인증 여부
const [isModalVisible, setIsModalVisible] = useState(true);
@@ -28,8 +29,6 @@ export default function MyPage({ setIsLoggedIn }) {
email: '',
});
- const [accessToken, setAccessToken] = useState(null); // 사용자 토큰
-
const navigation = useNavigation();
// 인증 완료 시, 모달 창 닫음
@@ -39,14 +38,9 @@ export default function MyPage({ setIsLoggedIn }) {
// 회원 정보 불러오기
try {
- // 토큰 불러오기
- const token = await AsyncStorage.getItem('accessToken');
- if (!token) {
+ if (!accessToken) {
throw new Error('토큰이 존재하지 않습니다.');
}
-
- setAccessToken(token);
-
const data = await getMyInfo();
setUserInfo({
name: data.name,
@@ -79,10 +73,8 @@ export default function MyPage({ setIsLoggedIn }) {
// 로그아웃 처리
try {
await logoutUser();
- // 토큰 삭제
- await AsyncStorage.removeItem('accessToken');
- // 시작 페이지로 이동되도록 로그인 상태 설정
- setIsLoggedIn(false);
+ // 토큰 삭제, 시작 페이지로 이동되도록 로그인 상태 설정
+ clearAccessToken();
} catch (error) {
console.log('내 정보 조회 실패:', error);
}
@@ -108,10 +100,8 @@ export default function MyPage({ setIsLoggedIn }) {
// 회원 탈퇴 처리
try {
await deleteUser();
- // 토큰 삭제
- await AsyncStorage.removeItem('accessToken');
- // 시작 페이지로 이동되도록 로그인 상태 설정
- setIsLoggedIn(false);
+ // 토큰 삭제, 시작 페이지로 이동되도록 로그인 상태 설정
+ clearAccessToken();
} catch (error) {
console.log('회원 탈퇴 실패:', error);
}
diff --git a/pages/SignUpPage.js b/pages/SignUpPage.js
index dba8965..e23f139 100644
--- a/pages/SignUpPage.js
+++ b/pages/SignUpPage.js
@@ -9,7 +9,7 @@ import { useNavigation, useRoute } from '@react-navigation/native';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
import NormalAlert from '../components/alerts/NormalAlert';
import { createMemberInfo } from '../apis/SignUpApi';
-import LoadingOverlay from '../components/loadings/LoadingOverlay';
+import { useAuthStore } from '../stores/authStore';
// 주민등록번호에서 생년월일 추출 (YYMMDD + 성별코드로 19/20세기 구분)
const getBirthDateFromRRN = (rrn) => {
@@ -35,6 +35,7 @@ const getBirthDateFromRRN = (rrn) => {
};
const SignUpPage = () => {
+ const { setLoading } = useAuthStore();
const navigation = useNavigation();
const route = useRoute();
@@ -66,7 +67,6 @@ const SignUpPage = () => {
const [error, setError] = useState({}); // 에러 메시지
const [isPwValid, setIsPwValid] = useState(false); //비밀번호 유효성
const [isPwMatch, setIsPwMatch] = useState(false); //비밀번호 일치성
- const [loading, setLoading] = useState(false); // 토큰 확인 중 상태
//공통 핸들러 - 입력값 변경을 처리
const handleInputChange = (field, value) => {
@@ -143,7 +143,6 @@ const SignUpPage = () => {
return (
<>
-
({
+ //토큰 상태 관리
+ accessToken: null,
+ setAccessToken: (token) =>
+ set({
+ accessToken: token,
+ isLoggedIn: !!token,
+ }),
+ //토큰 값만 설정할 때 사용
+ setOnlyAccessToken: (token) =>
+ set({
+ accessToken: token,
+ }),
+ clearAccessToken: () =>
+ set({
+ accessToken: null,
+ isLoggedIn: false,
+ }),
+
+ // 로그인 상태 관리
+ isLoggedIn: false,
+ setIsLoggedIn: (value) => set({ isLoggedIn: value }),
+
+ // 로딩 상태 관리
+ loading: false,
+ setLoading: (value) => set({ loading: value }),
+ }),
+ {
+ name: 'auth-storage',
+ storage: createJSONStorage(() => AsyncStorage),
+ whitelist: ['accessToken', 'isLoggedIn'],
+ },
+ ),
+);