Skip to content

Commit 7b59131

Browse files
authored
Merge pull request #114 from TaskFlow-CLAP/CLAP-307
CLAP-307 비밀번호 재설정 관련 API 설정
2 parents dbd7201 + 70e9b63 commit 7b59131

File tree

8 files changed

+113
-66
lines changed

8 files changed

+113
-66
lines changed

src/api/auth.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@ import Cookies from 'js-cookie'
33
import type { loginDataTypes } from '@/types/auth'
44
import { useMemberStore } from '@/stores/member'
55

6+
export const postPasswordEmailSend = async (name: string, email: string) => {
7+
const request = {
8+
name: name,
9+
email: email
10+
}
11+
const response = await axiosInstance.post('/api/new-password', request)
12+
return response.data
13+
}
14+
15+
export const postPasswordCheck = async (password: string) => {
16+
const response = await axiosInstance.post('/api/members/password', { password: password })
17+
return response.data
18+
}
19+
620
export const postLogin = async (loginData: loginDataTypes) => {
721
const response = await axiosInstance.post('/api/auths/login', loginData)
822
Cookies.set('accessToken', response.data.accessToken, {
@@ -17,7 +31,8 @@ export const postLogin = async (loginData: loginDataTypes) => {
1731
}
1832

1933
export const patchPassword = async (password: string) => {
20-
const response = await axiosInstance.patch('/api/members/password', password)
34+
const request = { password: password }
35+
const response = await axiosInstance.patch('/api/members/password', request)
2136
return response.data
2237
}
2338

src/components/EditInformation.vue

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
<template #header> 정보가 수정되었습니다 </template>
88
</ModalView>
99

10+
<ModalView
11+
:isOpen="isWarnningModalVisible"
12+
:type="'warningType'"
13+
@click="changePw"
14+
@close="warningModalToggle">
15+
<template #header> 정보가 저장되지 않았습니다 </template>
16+
<template #body> 수정 사항을 삭제하고 이동하시겠습니까? </template>
17+
</ModalView>
18+
1019
<div class="profile">
1120
<p class="text-body text-xs font-bold">프로필 사진</p>
1221
<img
@@ -33,7 +42,7 @@
3342
<input
3443
class="input-box h-11 mt-2 text-black"
3544
placeholder="이름을 입력해주세요"
36-
v-model="info.name" />
45+
v-model="name" />
3746
</div>
3847
<div class="flex flex-col">
3948
<p class="text-body text-xs font-bold">아이디</p>
@@ -55,17 +64,17 @@
5564
<p class="text-body text-xs font-bold">알림 수신 여부</p>
5665
<div class="flex flex-col mt-2 gap-2">
5766
<FormCheckbox
58-
v-model="info.notificationSettingInfo.agit"
67+
v-model="agitCheck"
5968
:checkButtonName="'아지트'"
60-
:isChecked="info.notificationSettingInfo.agit" />
69+
:isChecked="agitCheck" />
6170
<FormCheckbox
62-
v-model="info.notificationSettingInfo.kakaoWork"
71+
v-model="kakaoWorkCheck"
6372
:checkButtonName="'카카오워크'"
64-
:isChecked="info.notificationSettingInfo.kakaoWork" />
73+
:isChecked="kakaoWorkCheck" />
6574
<FormCheckbox
66-
v-model="info.notificationSettingInfo.email"
75+
v-model="emailCheck"
6776
:checkButtonName="'이메일'"
68-
:isChecked="info.notificationSettingInfo.email" />
77+
:isChecked="emailCheck" />
6978
</div>
7079
</div>
7180
<div>
@@ -86,7 +95,7 @@
8695
</template>
8796

8897
<script lang="ts" setup>
89-
import { ref } from 'vue'
98+
import { ref, watchEffect } from 'vue'
9099
import { useRouter } from 'vue-router'
91100
import ModalView from './ModalView.vue'
92101
import FormButtonContainer from './common/FormButtonContainer.vue'
@@ -99,37 +108,68 @@ import { patchEditInfo } from '@/api/common'
99108
const memberStore = useMemberStore()
100109
const { info } = storeToRefs(memberStore)
101110
111+
const name = ref(info.value.name)
112+
const agitCheck = ref(info.value.notificationSettingInfo.agit)
113+
const emailCheck = ref(info.value.notificationSettingInfo.email)
114+
const kakaoWorkCheck = ref(info.value.notificationSettingInfo.kakaoWork)
115+
102116
const selectedFile = ref<File | null>(null)
103117
const previewUrl = ref<string | null>(null)
104118
105119
const isModalVisible = ref(false)
120+
const isWarnningModalVisible = ref(false)
121+
122+
watchEffect(() => {
123+
if (info.value) {
124+
name.value = info.value.name
125+
agitCheck.value = info.value.notificationSettingInfo.agit
126+
emailCheck.value = info.value.notificationSettingInfo.email
127+
kakaoWorkCheck.value = info.value.notificationSettingInfo.kakaoWork
128+
}
129+
})
106130
107131
const handleCancel = () => {
108132
router.back()
109133
}
110134
111135
const handlePwChange = () => {
136+
if (
137+
selectedFile.value ||
138+
info.value.name != name.value ||
139+
info.value.notificationSettingInfo.agit != agitCheck.value ||
140+
info.value.notificationSettingInfo.kakaoWork != kakaoWorkCheck.value ||
141+
info.value.notificationSettingInfo.email != emailCheck.value
142+
) {
143+
warningModalToggle()
144+
} else {
145+
changePw()
146+
}
147+
}
148+
149+
const changePw = () => {
112150
router.push('/pw-check')
113151
}
114152
153+
const warningModalToggle = () => {
154+
isWarnningModalVisible.value = !isWarnningModalVisible.value
155+
}
156+
115157
const handleFileUpload = (event: Event) => {
116158
const target = event.target as HTMLInputElement
117159
if (target.files && target.files[0]) {
118160
selectedFile.value = target.files[0]
119-
120161
previewUrl.value = URL.createObjectURL(selectedFile.value)
121162
}
122163
}
123164
124165
const handleSubmit = async () => {
125166
const formData = new FormData()
126167
const memberInfo = {
127-
name: info.value.name,
128-
agitNotification: info.value.notificationSettingInfo.agit,
129-
emailNotification: info.value.notificationSettingInfo.email,
130-
kakaoWorkNotification: info.value.notificationSettingInfo.kakaoWork
168+
name: name.value,
169+
agitNotification: agitCheck.value,
170+
emailNotification: emailCheck.value,
171+
kakaoWorkNotification: kakaoWorkCheck.value
131172
}
132-
133173
const jsonMemberInfo = JSON.stringify(memberInfo)
134174
const newBlob = new Blob([jsonMemberInfo], { type: 'application/json' })
135175

src/router/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createRouter, createWebHistory } from 'vue-router'
2+
import Cookies from 'js-cookie'
23

34
const router = createRouter({
45
history: createWebHistory(import.meta.env.BASE_URL),
@@ -135,10 +136,13 @@ const router = createRouter({
135136

136137
router.beforeEach((to, from, next) => {
137138
if (to.path === '/pw-change') {
138-
if (from.path === '/pw-check' || from.path === '/pw-change-email') {
139+
if (
140+
from.path === '/pw-check' ||
141+
from.path === '/pw-change-email' ||
142+
(from.path === '/login' && Cookies.get('accessToken'))
143+
) {
139144
next()
140145
} else {
141-
alert('비밀번호를 먼저 확인해주세요.')
142146
next('/login')
143147
return
144148
}

src/stores/member.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ export const useMemberStore = defineStore('memberInfo', () => {
2323
}
2424

2525
const info = ref<User>(INITIAL_INFO)
26-
const refreshToken = ref(Cookies.get('refreshToken') || '')
27-
const isLogined = ref(!!refreshToken.value)
26+
const isLogined = ref(!!Cookies.get('refreshToken'))
2827
const router = useRouter()
2928

3029
async function updateMemberInfoWithToken() {
@@ -35,7 +34,7 @@ export const useMemberStore = defineStore('memberInfo', () => {
3534
try {
3635
const { data }: { data: User } = await axiosInstance.get('/api/members/info')
3736
info.value = data
38-
isLogined.value = true
37+
isLogined.value = Cookies.get('refreshToken') ? true : false
3938
return data.role
4039
} catch {
4140
router.push('/login')

src/views/LoginView.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import { useRouter } from 'vue-router'
4848
import { postLogin } from '@/api/auth'
4949
import { useMemberStore } from '@/stores/member'
5050
import TitleContainer from '@/components/common/TitleContainer.vue'
51+
import Cookies from 'js-cookie'
5152
5253
const router = useRouter()
5354
@@ -64,7 +65,9 @@ const handleLogin = async () => {
6465
const res = await postLogin(loginData)
6566
const role = await memberStore.updateMemberInfoWithToken()
6667
67-
if (res && role) {
68+
if (!Cookies.get('refreshToken')) {
69+
router.push('/pw-change')
70+
} else if (res && role && Cookies.get('refreshToken')) {
6871
switch (role) {
6972
case 'ROLE_ADMIN':
7073
router.push('/member-management')
@@ -80,7 +83,6 @@ const handleLogin = async () => {
8083
}
8184
}
8285
} catch (error) {
83-
// 로그인 실패 시 에러 처리
8486
console.error('로그인 실패:', error)
8587
}
8688
}

src/views/PwChange.vue

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
</ModalView>
1010
<div class="py-16">
1111
<TitleContainer
12+
v-if="!isFirst"
13+
:title="'비밀번호\n재설정'"
14+
content="새로운 비밀번호를 입력해주세요" />
15+
<TitleContainer
16+
v-if="isFirst"
1217
:title="'비밀번호\n재설정'"
1318
content="초기 비밀번호를 변경해주세요" />
1419
</div>
@@ -47,9 +52,15 @@
4752
import { ref } from 'vue'
4853
import { useRouter } from 'vue-router'
4954
import ModalView from '../components/ModalView.vue'
50-
import { patchPassword } from '@/api/auth'
55+
import { deleteLogout, patchPassword } from '@/api/auth'
5156
import TitleContainer from '@/components/common/TitleContainer.vue'
57+
import Cookies from 'js-cookie'
58+
import { useMemberStore } from '@/stores/member'
59+
import { storeToRefs } from 'pinia'
60+
const memberStore = useMemberStore()
61+
const { isLogined } = storeToRefs(memberStore)
5262
63+
const isFirst = Cookies.get('accessToken') ? (Cookies.get('refreshToken') ? false : true) : false
5364
const newPw = ref('')
5465
const checkPw = ref('')
5566
const isModalOpen = ref(false)
@@ -61,16 +72,15 @@ const toggleModal = () => {
6172
6273
const handleChange = () => {
6374
if (newPw.value === checkPw.value) {
64-
const response = patchPassword(newPw.value)
65-
console.log(response)
66-
console.log('비밀번호 변경 성공!')
75+
patchPassword(newPw.value)
6776
toggleModal()
6877
} else {
69-
alert('비밀번호가 일치하지 않습니다.')
7078
}
7179
}
7280
7381
const pwChange = () => {
82+
isLogined.value = false
83+
deleteLogout()
7484
router.push('/login')
7585
}
7686
</script>

src/views/PwChangeEmail.vue

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,33 @@
33
<ModalView
44
:isOpen="isModalOpen"
55
type="successType"
6-
@close="toggleModal">
6+
@close="closeModal">
77
<template #header> 인증 번호가 전송되었습니다 </template>
88
<template #body> 이메일을 확인해주세요 </template>
99
</ModalView>
1010
<div class="py-16">
1111
<TitleContainer
1212
:title="'비밀번호\n재설정'"
13-
content="가입된 아이디와 이메일을 입력해주세요" />
13+
content="가입된 이메일과 이름을 입력해주세요" />
1414
</div>
1515
<form
1616
@submit.prevent="handleCheck"
1717
class="mb-2">
1818
<div class="mb-6">
19-
<input
20-
type="text"
21-
id="id"
22-
v-model="id"
23-
placeholder="아이디를 입력해주세요"
24-
required
25-
class="input-box" />
26-
</div>
27-
<div class="relative mb-6">
28-
<div class="absolute flex items-center right-4 h-full">
29-
<button
30-
type="button"
31-
@click="handleRequestEmail"
32-
class="bg-white text-xs py-2 px-4 border-[1px] border-primary1 rounded text-primary1">
33-
{{ requestEmail ? '재요청' : '인증 요청' }}
34-
</button>
35-
</div>
3619
<input
3720
type="email"
3821
id="email"
3922
v-model="email"
40-
placeholder="이메일을 입력해주세요"
23+
placeholder="이메일 입력해주세요"
4124
required
4225
class="input-box" />
4326
</div>
44-
<div class="mb-8">
27+
<div class="relative mb-8">
4528
<input
4629
type="text"
47-
:disabled="!requestEmail"
48-
id="checkCode"
49-
v-model="checkCode"
50-
placeholder="인증코드를 입력해주세요"
30+
id="name"
31+
v-model="name"
32+
placeholder="이름을 입력해주세요"
5133
required
5234
class="input-box" />
5335
</div>
@@ -66,25 +48,19 @@ import { ref } from 'vue'
6648
import router from '../router/index'
6749
import ModalView from '../components/ModalView.vue'
6850
import TitleContainer from '@/components/common/TitleContainer.vue'
51+
import { postPasswordEmailSend } from '@/api/auth'
6952
70-
const id = ref('')
53+
const name = ref('')
7154
const email = ref('')
72-
const checkCode = ref('')
73-
const requestEmail = ref(false)
7455
const isModalOpen = ref(false)
7556
76-
const toggleModal = () => {
57+
const closeModal = () => {
7758
isModalOpen.value = !isModalOpen.value
78-
}
79-
80-
const handleRequestEmail = () => {
81-
toggleModal()
82-
requestEmail.value = true
83-
// 이메일 인증 코드 전송 API 추가 필요
59+
router.push('/login')
8460
}
8561
8662
const handleCheck = () => {
87-
// 이메일 인증 코드 확인 API 추가 필요
88-
router.push('/pw-change')
63+
postPasswordEmailSend(name.value, email.value)
64+
isModalOpen.value = !isModalOpen.value
8965
}
9066
</script>

src/views/PwCheck.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div class="py-16">
44
<TitleContainer
55
:title="'비밀번호\n재설정'"
6-
content="비밀번호 재설정을 위해\n현재 비밀번호를 입력해주세요" />
6+
:content="'비밀번호 재설정을 위해\n 현재 비밀번호를 입력해주세요'" />
77
</div>
88
<form
99
@submit.prevent="handleCheck"
@@ -33,11 +33,12 @@
3333
import { ref } from 'vue'
3434
import router from '../router/index'
3535
import TitleContainer from '@/components/common/TitleContainer.vue'
36+
import { postPasswordCheck } from '@/api/auth'
3637
3738
const pw = ref('')
3839
3940
const handleCheck = () => {
40-
// 기존 비밀번호 확인 API 추가 필요
41+
postPasswordCheck(pw.value)
4142
router.push('/pw-change')
4243
}
4344
</script>

0 commit comments

Comments
 (0)