Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 81 additions & 33 deletions src/components/EditInformation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,48 @@
class="mt-3"
:url="previewUrl || info.profileImageUrl"
:size="96" />

<label
for="fileInput"
class="mt-3 text-xs text-primary1 font-bold cursor-pointer"
>변경</label
>
<div class="flex gap-6">
<label
for="fileInput"
class="mt-3 text-xs text-primary1 font-bold cursor-pointer hover:underline"
>변경</label
>
<label
for="fileDelete"
class="mt-3 text-xs text-red-1 font-bold cursor-pointer hover:underline"
>삭제</label
>
</div>
<input
id="fileInput"
type="file"
@change="handleFileUpload"
accept="image/*"
class="hidden" />
<button
id="fileDelete"
type="button"
@click="handleFileDelete"
class="hidden" />
</div>

<div class="flex flex-col">
<div class="flex flex-col relative">
<p class="text-body text-xs font-bold">이름</p>
<span class="absolute top-1 right-2 text-xs text-gray-500"> {{ name.length }} / 10 </span>
<input
class="input-box h-11 mt-2 text-black"
:class="[
'block w-full px-4 py-4 border rounded focus:outline-none h-11 mt-2 text-black',
isInvalid ? 'border-red-1' : 'border-border-1'
]"
placeholder="이름을 입력해주세요"
v-model="name" />
v-model="name"
maxlength="10"
ref="nameInput"
@blur="validateName" />
<span
v-show="isInvalid"
class="text-red-1 text-xs font-bold mt-1"
>이름에는 특수문자가 포함될 수 없습니다.</span
>
</div>
<div class="flex flex-col">
<p class="text-body text-xs font-bold">아이디</p>
Expand Down Expand Up @@ -94,7 +116,7 @@
</template>

<script lang="ts" setup>
import { ref, watchEffect } from 'vue'
import { nextTick, ref, watchEffect } from 'vue'
import { useRouter } from 'vue-router'
import ModalView from './ModalView.vue'
import FormButtonContainer from './common/FormButtonContainer.vue'
Expand All @@ -112,10 +134,14 @@ const name = ref(info.value.name)
const agitCheck = ref(info.value.notificationSettingInfo.agit)
const emailCheck = ref(info.value.notificationSettingInfo.email)
const kakaoWorkCheck = ref(info.value.notificationSettingInfo.kakaoWork)
const imageDelete = ref(info.value.profileImageUrl == null ? true : false)

const selectedFile = ref<File | null>(null)
const previewUrl = ref<string | null>(null)

const isInvalid = ref(false)
const nameInput = ref<HTMLInputElement | null>(null)

const isModalVisible = ref(false)
const isWarnningModalVisible = ref(false)

Expand All @@ -128,6 +154,16 @@ watchEffect(() => {
}
})

const validateName = () => {
const regex = /[!@#$%^&*(),.?":{}|<>]/g
isInvalid.value = regex.test(name.value)

if (isInvalid.value) {
nextTick(() => {
nameInput.value?.focus()
})
}
}
const handleCancel = () => {
router.back()
}
Expand Down Expand Up @@ -160,31 +196,43 @@ const handleFileUpload = (event: Event) => {
selectedFile.value = target.files[0]
previewUrl.value = URL.createObjectURL(selectedFile.value)
}
imageDelete.value = false
}

const handleSubmit = async () => {
const formData = new FormData()
const memberInfo = {
name: name.value,
agitNotification: agitCheck.value,
emailNotification: emailCheck.value,
kakaoWorkNotification: kakaoWorkCheck.value
}
const jsonMemberInfo = JSON.stringify(memberInfo)
const newBlob = new Blob([jsonMemberInfo], { type: 'application/json' })

formData.append('memberInfo', newBlob)

if (selectedFile.value) {
formData.append('profileImage', selectedFile.value)
}
const handleFileDelete = () => {
imageDelete.value = true
previewUrl.value = ''
info.value.profileImageUrl = ''
}

try {
await patchEditInfo(formData)
isModalVisible.value = true
await memberStore.updateMemberInfoWithToken()
} catch (error) {
console.error('요청 실패:', error)
const handleSubmit = async () => {
if (isInvalid.value == false) {
const formData = new FormData()
const memberInfo = {
name: name.value,
isProfileImageDeleted: imageDelete.value,
agitNotification: agitCheck.value,
emailNotification: emailCheck.value,
kakaoWorkNotification: kakaoWorkCheck.value
}
const jsonMemberInfo = JSON.stringify(memberInfo)
const newBlob = new Blob([jsonMemberInfo], { type: 'application/json' })

formData.append('memberInfo', newBlob)

if (selectedFile.value && imageDelete.value == false) {
formData.append('profileImage', selectedFile.value)
} else if (imageDelete.value == true) {
selectedFile.value = null
}

try {
await patchEditInfo(formData)
isModalVisible.value = true
await memberStore.updateMemberInfoWithToken()
} catch (error) {
console.error('요청 실패:', error)
}
}
}
</script>
16 changes: 16 additions & 0 deletions src/constants/iconPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,19 @@ export const menuDotIcon = {
height: 20,
fill: '#71717A'
}

export const offEyeIcon = {
path: 'M23.257 10H23.262H23.252H23.257ZM22.552 9.48C22.652 9.798 22.94 9.998 23.257 10C23.327 10 23.404 9.98 23.482 9.96C23.872 9.84 24.092 9.41 23.962 9.02C23.932 8.93 20.932 0 12 0C3.06797 0 0.0669704 8.93 0.0369704 9.02C-0.0930296 9.41 0.12697 9.83 0.51697 9.96C0.91697 10.09 1.33697 9.87 1.46697 9.48L1.46997 9.475C1.60297 9.085 4.20697 1.5 12.01 1.5C19.852 1.5 22.442 9.15 22.552 9.48ZM8.49997 10C8.49997 9.07174 8.86872 8.1815 9.5251 7.52513C10.1815 6.86875 11.0717 6.5 12 6.5C12.9282 6.5 13.8185 6.86875 14.4748 7.52513C15.1312 8.1815 15.5 9.07174 15.5 10C15.5 10.9283 15.1312 11.8185 14.4748 12.4749C13.8185 13.1313 12.9282 13.5 12 13.5C11.0717 13.5 10.1815 13.1313 9.5251 12.4749C8.86872 11.8185 8.49997 10.9283 8.49997 10ZM12 5C10.6739 5 9.40212 5.52678 8.46444 6.46447C7.52675 7.40215 6.99997 8.67392 6.99997 10C6.99997 11.3261 7.52675 12.5979 8.46444 13.5355C9.40212 14.4732 10.6739 15 12 15C13.3261 15 14.5978 14.4732 15.5355 13.5355C16.4732 12.5979 17 11.3261 17 10C17 8.67392 16.4732 7.40215 15.5355 6.46447C14.5978 5.52678 13.3261 5 12 5Z',
width: 24,
height: 15,
fill: 'black'
}
export const onEyeIcon = {
path: 'M23.257 10H23.262H23.252H23.257ZM22.552 9.48C22.652 9.798 22.94 9.998 23.257 10C23.327 10 23.404 9.98 23.482 9.96C23.872 9.84 24.092 9.41 23.962 9.02C23.932 8.93 20.932 0 12 0C3.06797 0 0.0669704 8.93 0.0369704 9.02C-0.0930296 9.41 0.12697 9.83 0.51697 9.96C0.91697 10.09 1.33697 9.87 1.46697 9.48L1.46997 9.475C1.60297 9.085 4.20697 1.5 12.01 1.5C19.852 1.5 22.442 9.15 22.552 9.48ZM6.99997 10C6.99997 8.67392 7.52675 7.40215 8.46444 6.46447C9.40212 5.52678 10.6739 5 12 5C13.3261 5 14.5978 5.52678 15.5355 6.46447C16.4732 7.40215 17 8.67392 17 10C17 11.3261 16.4732 12.5979 15.5355 13.5355C14.5978 14.4732 13.3261 15 12 15C10.6739 15 9.40212 14.4732 8.46444 13.5355C7.52675 12.5979 6.99997 11.3261 6.99997 10Z',
width: 24,
height: 15,
fill: 'black'
// fill: 'none',
// Option: {
// }
}
33 changes: 31 additions & 2 deletions src/views/LoginView.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<template>
<div class="max-w-400">
<ModalView
:is-open="isModalVisible"
type="failType"
@close="closeModal">
<template #header>{{ messageHeader }}</template>
<template #body>{{ messageBody }}</template>
</ModalView>
<div class="py-16">
<TitleContainer
:title="'TaskFlow\n로그인'"
Expand Down Expand Up @@ -34,7 +41,7 @@
</form>
<div class="flex w-full justify-center">
<RouterLink
class="text-body font-bold text-[12px] hover:underline"
class="text-body font-bold text-[12px]"
to="/pw-change-email"
>비밀번호 재설정</RouterLink
>
Expand All @@ -49,13 +56,23 @@ import { postLogin } from '@/api/auth'
import { useMemberStore } from '@/stores/member'
import TitleContainer from '@/components/common/TitleContainer.vue'
import Cookies from 'js-cookie'
import ModalView from '@/components/ModalView.vue'

const router = useRouter()

const nickname = ref('')
const password = ref('')
const memberStore = useMemberStore()

const messageHeader = ref('')
const messageBody = ref('')

const isModalVisible = ref(false)

const closeModal = () => {
isModalVisible.value = false
}

const handleLogin = async () => {
try {
const loginData = {
Expand Down Expand Up @@ -83,7 +100,19 @@ const handleLogin = async () => {
}
}
} catch (error) {
console.error('로그인 실패:', error)
switch (error?.response?.status) {
case 401:
isModalVisible.value = !isModalVisible.value
messageHeader.value = '일치하는 정보가 없습니다'
messageBody.value = '닉네임과 비밀번호를 다시 확인해 주세요'
break

case 500:
isModalVisible.value = !isModalVisible.value
messageHeader.value = '서버에 문제가 발생했습니다'
messageBody.value = '잠시후 다시 이용해주세요'
break
}
}
}
</script>
56 changes: 48 additions & 8 deletions src/views/PwChange.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ModalView
:isOpen="isModalOpen"
type="successType"
@close="pwChange">
@close="closeModal">
<template #header> 비밀번호가 변경 되었습니다 </template>
<template #body> 다시 로그인 해주세요 </template>
</ModalView>
Expand All @@ -27,16 +27,35 @@
v-model="newPw"
placeholder="새 비밀번호를 입력해주세요"
required
class="input-box" />
ref="passwordInput"
:class="[
'block w-full px-4 py-4 border rounded focus:outline-none',
isInvalid ? 'border-red-1' : 'border-border-1'
]"
@blur="validatePassword" />
<p
v-show="isInvalid"
class="text-red-1 text-xs font-bold mt-1">
대문자, 소문자, 숫자, 특수문자 포함 8자-20자 입력해주세요
</p>
</div>
<div class="mb-8">
<input
type="password"
id="checkPw"
v-model="checkPw"
ref="checkPwInput"
placeholder="새 비밀번호를 다시 입력해주세요"
required
class="input-box" />
:class="[
'block w-full px-4 py-4 border rounded focus:outline-none',
isDifferent ? 'border-red-1' : 'border-border-1'
]" />
<p
v-show="isDifferent"
class="text-red-1 text-xs font-bold mt-1">
비밀번호가 일치하지 않아요
</p>
</div>
<button
type="submit"
Expand All @@ -49,7 +68,7 @@
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { nextTick, ref } from 'vue'
import { useRouter } from 'vue-router'
import ModalView from '../components/ModalView.vue'
import { deleteLogout, patchPassword } from '@/api/auth'
Expand All @@ -65,22 +84,43 @@ const newPw = ref('')
const checkPw = ref('')
const isModalOpen = ref(false)
const router = useRouter()
const isDifferent = ref(false)
const checkPwInput = ref<HTMLInputElement | null>(null)
const isInvalid = ref(false)
const passwordInput = ref<HTMLInputElement | null>(null)

const toggleModal = () => {
const validatePassword = () => {
const regex = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[!@#$%^&*()_+{}\[\]:;<>,.?/~`-]).{8,20}$/
isInvalid.value = !regex.test(newPw.value)

if (isInvalid.value) {
nextTick(() => {
passwordInput.value?.focus()
})
}
}

const openModal = () => {
isModalOpen.value = !isModalOpen.value
}
const closeModal = () => {
isModalOpen.value = !isModalOpen.value
router.push('/login')
deleteLogout()
}

const handleChange = () => {
if (newPw.value === checkPw.value) {
patchPassword(newPw.value)
toggleModal()
pwChange()
openModal()
} else {
isDifferent.value = true
checkPwInput.value?.focus()
}
}

const pwChange = () => {
isLogined.value = false
deleteLogout()
router.push('/login')
}
</script>
Loading