From 5c52d8f3b97a9127d56cf8d39208c3410a15caa7 Mon Sep 17 00:00:00 2001
From: Jiwon Chae <63784453+jiwon0226@users.noreply.github.com>
Date: Thu, 15 May 2025 08:09:47 +0900
Subject: [PATCH 1/5] =?UTF-8?q?KW-377/feat:=20useAuthStore=20=EC=83=9D?=
=?UTF-8?q?=EC=84=B1=20(=EC=A3=BC=EC=8A=A4=ED=83=A0=EB=93=9C)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app.config.js | 4 ++--
package-lock.json | 32 +++++++++++++++++++++++++++++++-
package.json | 3 ++-
stores/authStore.js | 42 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 77 insertions(+), 4 deletions(-)
create mode 100644 stores/authStore.js
diff --git a/app.config.js b/app.config.js
index ff3e665..f9371b2 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.180:8081', // 도커 사용시 - 본인 pc IPv4 주소로 수정하세용
},
},
};
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/stores/authStore.js b/stores/authStore.js
new file mode 100644
index 0000000..6641ae9
--- /dev/null
+++ b/stores/authStore.js
@@ -0,0 +1,42 @@
+import { create } from 'zustand';
+import { persist, createJSONStorage } from 'zustand/middleware';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+
+export const useAuthStore = create(
+ persist(
+ (set) => ({
+ //토큰 상태 관리
+ accessToken: null,
+ setAccessToken: (token) =>
+ set({
+ accessToken: token,
+ isLoggedIn: !!token,
+ }),
+ clearAccessToken: () =>
+ set({
+ accessToken: null,
+ isLoggedIn: false,
+ }),
+
+ // 로그인 상태 관리
+ isLoggedIn: false,
+ setIsLoggedIn: (value) => set({ isLoggedIn: value }),
+
+ // 로딩 상태 관리
+ loading: false,
+ setLoading: (value) => set({ loading: value }),
+
+ // 로그아웃시 상태 설정
+ logout: () =>
+ set({
+ isLoggedIn: false,
+ accessToken: null,
+ }),
+ }),
+ {
+ name: 'auth-storage',
+ storage: createJSONStorage(() => AsyncStorage),
+ whitelist: ['accessToken', 'isLoggedIn'],
+ },
+ ),
+);
From ef020cb2de24fd87560ac293e9fc39ae9d8e5d4d Mon Sep 17 00:00:00 2001
From: Jiwon Chae <63784453+jiwon0226@users.noreply.github.com>
Date: Thu, 15 May 2025 08:40:32 +0900
Subject: [PATCH 2/5] =?UTF-8?q?KW-377/fix:=20AxiosInstance.js=20=EC=88=98?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
AppNavigator.js | 1 +
apis/AxiosInstance.js | 33 +++++++++------------------------
stores/authStore.js | 10 +++++-----
3 files changed, 15 insertions(+), 29 deletions(-)
diff --git a/AppNavigator.js b/AppNavigator.js
index f67bdcc..d0ad078 100644
--- a/AppNavigator.js
+++ b/AppNavigator.js
@@ -9,6 +9,7 @@ import { setLogoutCallback } from './handler/logoutHandler';
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';
diff --git a/apis/AxiosInstance.js b/apis/AxiosInstance.js
index 8bb45eb..4bd9a05 100644
--- a/apis/AxiosInstance.js
+++ b/apis/AxiosInstance.js
@@ -2,6 +2,7 @@ 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 +13,8 @@ const instance = axios.create({
// accessToken 가져오는 함수
const getAccessToken = async () => {
- return await AsyncStorage.getItem('accessToken');
+ const { accessToken } = useAuthStore.getState();
+ return accessToken;
};
// 요청 인터셉터: 모든 요청에 accessToken 자동 첨부
@@ -23,9 +25,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 +33,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 +40,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 +54,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 +82,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/stores/authStore.js b/stores/authStore.js
index 6641ae9..bcc8994 100644
--- a/stores/authStore.js
+++ b/stores/authStore.js
@@ -27,11 +27,11 @@ export const useAuthStore = create(
setLoading: (value) => set({ loading: value }),
// 로그아웃시 상태 설정
- logout: () =>
- set({
- isLoggedIn: false,
- accessToken: null,
- }),
+ // logout: () =>
+ // set({
+ // isLoggedIn: false,
+ // accessToken: null,
+ // }),
}),
{
name: 'auth-storage',
From 3e0588a710cace59ddc45afdfbd1ee79c8887f9c Mon Sep 17 00:00:00 2001
From: Jiwon Chae <63784453+jiwon0226@users.noreply.github.com>
Date: Thu, 15 May 2025 13:39:25 +0900
Subject: [PATCH 3/5] =?UTF-8?q?KW-377/feat:=20=EB=B9=84=EB=B0=80=EB=B2=88?=
=?UTF-8?q?=ED=98=B8=20=ED=99=95=EC=9D=B8=20=EB=AA=A8=EB=8B=AC,=20?=
=?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=EB=B3=80=EA=B2=BD=20?=
=?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?=
=?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80,=20=EB=A7=88=EC=9D=B4=ED=8E=98?=
=?UTF-8?q?=EC=9D=B4=EC=A7=80,=20authStore,=20AppNavigator=EC=97=90=20=20?=
=?UTF-8?q?=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
AppNavigator.js | 38 ++++++++++++++--------------------
app.config.js | 2 +-
modals/PasswordConfirmModal.js | 4 +---
pages/ChangePasswordPage.js | 3 ---
pages/LoginPage.js | 14 ++++++-------
pages/MyPage.js | 26 +++++++----------------
stores/authStore.js | 12 +++++------
7 files changed, 36 insertions(+), 63 deletions(-)
diff --git a/AppNavigator.js b/AppNavigator.js
index d0ad078..20c285b 100644
--- a/AppNavigator.js
+++ b/AppNavigator.js
@@ -2,10 +2,7 @@ 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';
@@ -25,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(() => {
@@ -41,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);
@@ -64,11 +65,6 @@ export default function AppNavigator() {
checkToken();
}, []);
- // 앱 시작시 logoutHandler.js에 콜백 함수 등록
- useEffect(() => {
- setLogoutCallback(() => setIsLoggedIn(false));
- }, []);
-
const navTheme = {
...DefaultTheme,
colors: {
@@ -101,9 +97,7 @@ export default function AppNavigator() {
component={MainPage}
options={{ headerShown: false, title: '홈' }}
/>
-
- {(props) => }
-
+
-
- {(props) => }
-
+
{
@@ -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/pages/ChangePasswordPage.js b/pages/ChangePasswordPage.js
index f87b793..7a69160 100644
--- a/pages/ChangePasswordPage.js
+++ b/pages/ChangePasswordPage.js
@@ -8,7 +8,6 @@ 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';
const ChangePasswordPage = () => {
const [originalPassword, setOriginalPassword] = useState(''); // 기존 비밀번호
@@ -49,8 +48,6 @@ const ChangePasswordPage = () => {
const handleConfirmChange = async () => {
setShowConfirmAlert(false);
try {
- // 토큰 불러오기
- const token = await AsyncStorage.getItem('accessToken');
await updatePassword({ originalPassword, newPassword });
setTimeout(() => {
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 (
<>
-
+ set({
+ accessToken: token,
+ }),
clearAccessToken: () =>
set({
accessToken: null,
@@ -25,13 +30,6 @@ export const useAuthStore = create(
// 로딩 상태 관리
loading: false,
setLoading: (value) => set({ loading: value }),
-
- // 로그아웃시 상태 설정
- // logout: () =>
- // set({
- // isLoggedIn: false,
- // accessToken: null,
- // }),
}),
{
name: 'auth-storage',
From a65a50febda68606a6fb9b069157a290a2501576 Mon Sep 17 00:00:00 2001
From: Jiwon Chae <63784453+jiwon0226@users.noreply.github.com>
Date: Thu, 15 May 2025 13:42:47 +0900
Subject: [PATCH 4/5] =?UTF-8?q?KW-377/fix:=20logoutHandler.js=20=EC=82=AD?=
=?UTF-8?q?=EC=A0=9C=20=EB=B0=8F=20=ED=95=84=EC=9A=94=EC=97=86=EB=8A=94=20?=
=?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apis/AxiosInstance.js | 2 --
handler/logoutHandler.js | 11 -----------
2 files changed, 13 deletions(-)
delete mode 100644 handler/logoutHandler.js
diff --git a/apis/AxiosInstance.js b/apis/AxiosInstance.js
index 4bd9a05..b12850a 100644
--- a/apis/AxiosInstance.js
+++ b/apis/AxiosInstance.js
@@ -1,7 +1,5 @@
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;
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();
-}
From 47bec5dbb32e6d92ae0e9afd1c01c5081c7a4a1f Mon Sep 17 00:00:00 2001
From: Jiwon Chae <63784453+jiwon0226@users.noreply.github.com>
Date: Thu, 15 May 2025 14:41:31 +0900
Subject: [PATCH 5/5] =?UTF-8?q?KW-377/feat:=20=EB=A1=9C=EB=94=A9=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=B6=88=ED=95=84=EC=9A=94?=
=?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apis/AccessRequestApi.js | 1 -
app.config.js | 2 +-
components/accessRequest/GuardianVerificationForm.js | 5 +++++
components/accessRequest/PatientVerficationForm.js | 8 ++++++++
pages/AccessRequestPage.js | 6 +++++-
pages/AccessRequestRolePage.js | 5 +++++
pages/ChangePasswordPage.js | 5 +++++
pages/MyAccessListPage.js | 6 +++++-
pages/SignUpPage.js | 5 ++---
9 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/apis/AccessRequestApi.js b/apis/AccessRequestApi.js
index 101fee8..f0c07b9 100644
--- a/apis/AccessRequestApi.js
+++ b/apis/AccessRequestApi.js
@@ -3,7 +3,6 @@ import axios from './AxiosInstance';
// 병원 목록 조회
export const getHospitalList = async () => {
const response = await axios.get('/hospitals');
-
return response.data.data;
};
diff --git a/app.config.js b/app.config.js
index 9b9e9d9..23490b4 100644
--- a/app.config.js
+++ b/app.config.js
@@ -26,7 +26,7 @@ export default {
},
extra: {
//BASE_URL: 'http://keywe.site', // EKS 사용시
- BASE_URL: 'http://192.168.0.111:8081', // 도커 사용시 - 본인 pc IPv4 주소로 수정하세용
+ 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/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 7a69160..3f9217c 100644
--- a/pages/ChangePasswordPage.js
+++ b/pages/ChangePasswordPage.js
@@ -8,8 +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 { useAuthStore } from '../stores/authStore';
const ChangePasswordPage = () => {
+ const { setLoading } = useAuthStore();
const [originalPassword, setOriginalPassword] = useState(''); // 기존 비밀번호
const [newPassword, setNewPassword] = useState(''); // 새 비밀번호
const [confirmNewPassword, setConfirmNewPassword] = useState(''); // 새 비밀번호 확인
@@ -47,6 +49,7 @@ const ChangePasswordPage = () => {
// 비밀번호 변경 확인 버튼 클릭 핸들러
const handleConfirmChange = async () => {
setShowConfirmAlert(false);
+ setLoading(true);
try {
await updatePassword({ originalPassword, newPassword });
@@ -65,6 +68,8 @@ const ChangePasswordPage = () => {
setErrorAlertMessage(message);
setShowErrorAlert(true);
+ } finally {
+ setLoading(false);
}
};
diff --git a/pages/MyAccessListPage.js b/pages/MyAccessListPage.js
index a40a7d6..2cbb139 100644
--- a/pages/MyAccessListPage.js
+++ b/pages/MyAccessListPage.js
@@ -5,8 +5,10 @@ import { MyAccessList } from '../mocks/MyAccessListSample'; //예시 데이터
import { styles } from './styles/MyAccessListPage.styles';
import { getAccessList } from '../apis/MyAccessListApi';
import MyAccessDetailModal from '../modals/MyAccessDetailModal';
+import { useAuthStore } from '../stores/authStore';
const MyAccessListPage = () => {
+ 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/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 (
<>
-