diff --git a/src/api/auth.ts b/src/api/auth.ts index 653a443f..58720fdf 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -16,29 +16,26 @@ export const postLogin = async (loginData: loginDataTypes, sessionId: string) => path: '/', sameSite: 'strict' }) - await memberStore.updateMemberInfoWithToken() return response.data } export const patchPassword = async (password: string) => { const response = await axiosInstance.patch('/api/members/password', password) - return response.data } export const deleteLogout = async () => { - const memberStore = useMemberStore() const refreshToken = Cookies.get('refreshToken') + const accessToken = Cookies.get('accessToken') const response = await axiosInstance.delete('/api/auths/logout', { headers: { - Authorization: `Bearer ${import.meta.env.VITE_ACCESS_TOKEN}`, + Authorization: `Bearer ${accessToken}`, refreshToken: refreshToken } }) Cookies.remove('accessToken', { path: '/' }) Cookies.remove('refreshToken', { path: '/' }) - await memberStore.updateMemberInfoWithToken() return response } diff --git a/src/api/user.ts b/src/api/user.ts index 0315d6e2..4b6d2eaf 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -1,7 +1,13 @@ import type { Status } from '@/types/common' +import type { userInfo } from '@/types/user' import type { RequestApprovePostTypes } from '@/types/manager' import { axiosInstance, formDataAxiosInstance } from '@/utils/axios' +export const patchEditInfo = async (formdata: userInfo, image: File) => { + const response = await formDataAxiosInstance.post('/api/tasks', formdata, image) + return response.data +} + export const postTaskRequest = async (formdata: FormData) => { const response = await formDataAxiosInstance.post('/api/tasks', formdata) return response.data diff --git a/src/components/EditInformation.vue b/src/components/EditInformation.vue index 549368a1..17e774de 100644 --- a/src/components/EditInformation.vue +++ b/src/components/EditInformation.vue @@ -10,15 +10,22 @@

프로필 사진

프로필 이미지 -
- -

변경

+ + +
@@ -26,23 +33,23 @@ + v-model="info.memberName" />

아이디

-

{{ memberId }}

+

{{ info.nickname }}

이메일

-

{{ memberEmail }}

+

{{ info.email }}

부서

-

{{ memberDepartment }}

+

{{ info.departmentName }}

직무

-

{{ memberJob }}

+

{{ info.departmentRole }}

알림 수신 여부

@@ -85,13 +92,17 @@ import ModalView from './ModalView.vue' import FormButtonContainer from './common/FormButtonContainer.vue' import FormCheckbox from './common/FormCheckbox.vue' const router = useRouter() +import { useMemberStore } from '@/stores/member' +import { storeToRefs } from 'pinia' +import { patchEditInfo } from '@/api/user' +import + +const memberStore = useMemberStore() +const { info } = storeToRefs(memberStore) + +const selectedFile = ref(null) +const previewUrl = ref(null) -const memberName = ref('백지연') -const memberId = ref('Chole.yeon') -const memberEmail = ref('taskflow123@gachon.ac.kr') -const memberDepartment = ref('인프라팀') -const memberJob = ref('인프라 아키텍처') -const imageUrl = ref('') const isModalVisible = ref(false) const memberForm = ref({ @@ -100,15 +111,34 @@ const memberForm = ref({ isEmailChecked: false }) +const formData = new FormData() + +const requestData: any = { + name: info.value.memberName, + agitNotification: memberForm.value.isAgitChecked, + emailNotification: memberForm.value.isEmailChecked, + kakaoWorkNotification: memberForm.value.isKakaoWorkChecked +} const handleCancel = () => { router.back() } -const handleSubmit = () => { - isModalVisible.value = true -} - const handlePwChange = () => { router.push('/pw-check') } + +const handleFileUpload = (event: Event) => { + const target = event.target as HTMLInputElement + if (target.files && target.files[0]) { + selectedFile.value = target.files[0] + + previewUrl.value = URL.createObjectURL(selectedFile.value) + } +} + +const handleSubmit = () => { + isModalVisible.value = true + console.log(requestData) + patchEditInfo(requestData, selectedFile.value) +} diff --git a/src/components/TopBar.vue b/src/components/TopBar.vue deleted file mode 100644 index 5f74dcba..00000000 --- a/src/components/TopBar.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - diff --git a/src/components/top-bar/ProfileModal.vue b/src/components/top-bar/ProfileModal.vue index f5e1088b..eda33884 100644 --- a/src/components/top-bar/ProfileModal.vue +++ b/src/components/top-bar/ProfileModal.vue @@ -63,7 +63,7 @@ import { computed } from 'vue' const isModalVisible = ref(false) const memberStore = useMemberStore() -const { info } = storeToRefs(memberStore) +const { isLogined, info } = storeToRefs(memberStore) const imgUrl = computed(() => info.value.imageUrl) const name = computed(() => info.value.memberName) @@ -88,6 +88,7 @@ const handleEdit = () => { } const openLogoutModal = () => { isModalVisible.value = true + isLogined.value = false } const closeLogoutModal = () => { isModalVisible.value = false diff --git a/src/components/top-bar/TopBar.vue b/src/components/top-bar/TopBar.vue index 9d1b47e6..f761b739 100644 --- a/src/components/top-bar/TopBar.vue +++ b/src/components/top-bar/TopBar.vue @@ -65,9 +65,10 @@ const { isLogined, info } = storeToRefs(memberStore) const route = useRoute() const router = useRouter() onMounted(async () => { - await fetchNotificationCount() - - await memberStore.updateMemberInfoWithToken() + if (isLogined.value) { + await fetchNotificationCount() + await memberStore.updateMemberInfoWithToken() + } const originUrl = route.path.split('/')[1] if (info.value.memberRole === 'ROLE_USER') { @@ -90,11 +91,13 @@ const isNotifiVisible = ref(false) const isProfileVisible = ref(false) const fetchNotificationCount = async () => { - try { - const data = await getNotifiCount() - countNotifi.value = data.count - } catch (error) { - console.error('알림 개수 불러오기 실패:', error) + if (isLogined.value) { + try { + const data = await getNotifiCount() + countNotifi.value = data.count + } catch (error) { + console.error('알림 개수 불러오기 실패:', error) + } } } @@ -109,10 +112,16 @@ const onCloseSide = () => { isSideOpen.value = false } +watch(isLogined, newValue => { + if (newValue) { + location.reload() // 페이지 새로고침 + } +}) + watch( () => info.value, async newInfo => { - if (newInfo.memberName) { + if (newInfo.memberName && isLogined) { await fetchNotificationCount() } }, diff --git a/src/stores/member.ts b/src/stores/member.ts index a3b1ef72..f4e45b13 100644 --- a/src/stores/member.ts +++ b/src/stores/member.ts @@ -10,7 +10,10 @@ export const useMemberStore = defineStore('memberInfo', () => { nickname: '', imageUrl: '', memberRole: '', - memberStatus: '' + memberStatus: '', + email: '', + departmentName: '', + departmentRole: '' }) const refreshToken = ref(Cookies.get('refreshToken') || '') @@ -27,9 +30,12 @@ export const useMemberStore = defineStore('memberInfo', () => { info.value = { memberName: responseData.name || '', nickname: responseData.nicknanme || '', + email: responseData.email || '', imageUrl: responseData.profileImageUrl || '', memberRole: responseData.role || '', - memberStatus: '' + memberStatus: responseData.memberStatus || '', + departmentName: responseData.departmentName || '', + departmentRole: responseData.departmentRole || '' } console.log('Updated member info:', info.value) } @@ -40,7 +46,10 @@ export const useMemberStore = defineStore('memberInfo', () => { nickname: '', imageUrl: '', memberRole: '', - memberStatus: '' + memberStatus: '', + email: '', + departmentName: '', + departmentRole: '' } isLogined.value = false Cookies.remove('accessToken') diff --git a/src/types/auth.ts b/src/types/auth.ts index 87007613..3e91977d 100644 --- a/src/types/auth.ts +++ b/src/types/auth.ts @@ -1,9 +1,12 @@ export interface User { memberName: string nickname: string + email: string imageUrl: string memberRole: string memberStatus: string + departmentName: string + departmentRole: string } export interface loginDataTypes { diff --git a/src/types/user.ts b/src/types/user.ts index 14a699f4..01241965 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -1,6 +1,13 @@ import type { LabelDataTypes, Status } from './common' import type { ManagerTypes } from './manager' +export interface userInfo { + name: string + agitNotification: boolean + emailNotification: boolean + kakaoWorkNotification: boolean +} + export interface MyRequestListData { taskId: number taskCode: string diff --git a/src/utils/axios.ts b/src/utils/axios.ts index 2531c53c..9c12f4c6 100644 --- a/src/utils/axios.ts +++ b/src/utils/axios.ts @@ -3,6 +3,32 @@ import Cookies from 'js-cookie' const baseURL = import.meta.env.VITE_API_BASE_URL +const getNewAccessToken = async () => { + console.log('토큰 재발급 시도') + try { + const refreshToken = Cookies.get('refreshToken') + console.log(refreshToken) + const response = await axios.post( + baseURL + '/api/auths/reissuance', + {}, + { + headers: { refreshToken: refreshToken } + } + ) + Cookies.set('accessToken', response.data.accessToken) + Cookies.set('refreshToken', response.data.newRefreshToken) + console.log('토큰 발행 성공') + + console.log(response.data) + + return response.data.accessToken + } catch (e) { + console.error('토큰 발행 실패', e) + Cookies.remove('accessToken') + Cookies.remove('refreshToken') + window.location.reload() + } +} const setInterceptors = (instance: AxiosInstance) => { instance.interceptors.request.use( (config: InternalAxiosRequestConfig) => { @@ -19,17 +45,34 @@ const setInterceptors = (instance: AxiosInstance) => { instance.interceptors.response.use( response => response, - error => { + async error => { if (axios.isCancel(error)) { console.log('요청이 취소되었습니다:', error.message) } else if (error.response) { + console.log('상태확인 에러메세지:', error.response) switch (error.response.status) { case 401: console.error('인증 오류: 다시 로그인하세요.') break - case 403: + case 403: { console.error('권한 오류: 접근 권한이 없습니다.') + + const originalRequest = error.config + if (!originalRequest._retry) { + originalRequest._retry = true + + try { + console.log('토큰이 만료됨') + const newAccessToken = await getNewAccessToken() + + originalRequest.headers.Authorization = `Bearer ${newAccessToken}` + return instance(originalRequest) + } catch (err) { + console.error('토큰 갱신 실패:', err) + } + } break + } case 404: console.error('요청한 자원을 찾을 수 없습니다.') break diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index 1dd39baf..0654f0b8 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -1,11 +1,9 @@