Skip to content

Commit

Permalink
Merge pull request #152 from Leets-Official/feature/#151/닉네임수정페이지-회원탈퇴추가
Browse files Browse the repository at this point in the history
[feat] #152 닉네임 수정 페이지 및 회원탈퇴 추가
  • Loading branch information
One-HyeWon authored May 28, 2024
2 parents 61da8ab + c28f866 commit b5d1062
Show file tree
Hide file tree
Showing 14 changed files with 364 additions and 29 deletions.
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,14 @@

<br />

> 서비스 바로가기 <br /> ( 현재 리팩토링중인 서비스입니다 :) 5월 출시를 기다려주세요! )


## [💗💗💗 서비스 바로가기 💗💗💗](https://www.moodmate.site/main)



<br/>

<p align=center>
<a href="https://plum-lightyear-dd5.notion.site/MoodMate-328ba219563f46118193cd5d7a5acf8f?pvs=4">팀 노션</a>
&nbsp; | &nbsp;
<a href="https://github.com/orgs/Leets-Official/projects/2">백로그</a>
&nbsp; | &nbsp;
<a href="https://www.figma.com/file/Pf9BoSgENbbP5DgxTFz7sg/MM-Design?node-id=1%3A2&mode=dev">figma</a>
<br />

<div align=center>
<a href="https://hits.seeyoufarm.com"><img src="https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2FLeets-Official%2FMoodMate-FE&count_bg=%23333333&title_bg=%23FC4F59&icon=&icon_color=%23FC4F59&title=hits&edge_flat=false)](https://hits.seeyoufarm.com"/></a>
Expand Down
2 changes: 1 addition & 1 deletion public/sw.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/app/_atom/userinfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ export const editUserInfoState = atom<EditUserInfoData>({
preferMood: '',
},
})

export const editUserNickname = atom({
key: 'editUserNickname',
default: {
isNicknameEdit: false,
userNickname: '',
},
})
60 changes: 54 additions & 6 deletions src/app/_components/common/userinfo/UserNickname.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import Input from '../Input'
import Loading from '../Loading'
import ErrorPage from '@/(route)/error'
import { useMyPageQuery } from '@/_hooks/useMypageQuery'
import { useMutation } from '@tanstack/react-query'
import { postCheckNickname } from '@/_service/mypage'

interface UserNicknameProps {
pageNum: string
Expand All @@ -17,6 +19,8 @@ interface UserNicknameProps {
const UserNickname = ({ pageNum, isEdit }: UserNicknameProps) => {
const [editUserInfo, setEditUserInfoState] = useRecoilState(editUserInfoState)
const route = useRouter()
const [canUseNickname, setCanUseNickname] = useState(false)
const [canNext, setCanNext] = useState(false)
const [nickname, setNickname] = useRecoilState(userInfoState)
const userInfo = useRecoilValue(userInfoState)
const [inputValue, setInputValue] = useState(
Expand Down Expand Up @@ -61,6 +65,7 @@ const UserNickname = ({ pageNum, isEdit }: UserNicknameProps) => {
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value.slice(0, INPUT_NICKNAME.MAX)
const koeranOnly = /^[ㄱ-ㅎㅏ-ㅣ가-힣]*$/g
setCanUseNickname(false)
if (!koeranOnly.test(newValue)) {
alert('한글만 입력 가능합니다.')
} else {
Expand All @@ -69,6 +74,14 @@ const UserNickname = ({ pageNum, isEdit }: UserNicknameProps) => {
}
}

useEffect(() => {
if (canUseNickname && inputValue.length > 0) {
setCanNext(true)
} else {
setCanNext(false)
}
}, [inputValue, canUseNickname])

const nextRoute = () => {
if (inputValue.trim() === '') {
alert('닉네임을 입력해주세요.')
Expand All @@ -87,6 +100,34 @@ const UserNickname = ({ pageNum, isEdit }: UserNicknameProps) => {
}
}

const postUserDataMutation = useMutation({
mutationFn: () => postCheckNickname(inputValue.trim()),
onSuccess: (data) => {
if (data.isDuplicate) {
setCanUseNickname(false)
alert('이미 사용중인 닉네임입니다.')
} else {
setCanUseNickname(true)
if (inputValue.length > 0) {
setCanNext(true)
}
alert('사용 가능한 닉네임입니다!')
}
},
onError: () => {
setCanUseNickname(false)
alert('다시 시도해 주세요.')
},
})

const checkCanUseNickname = () => {
if (inputValue.trim().length !== 0) {
postUserDataMutation.mutate()
} else {
alert('닉네임을 입력해주세요.')
}
}

const inputStyles = {
defaultStyles: 'bg-lightgray',
activeStyles: 'bg-primary',
Expand Down Expand Up @@ -125,8 +166,17 @@ const UserNickname = ({ pageNum, isEdit }: UserNicknameProps) => {
: inputStyles.defaultStyles
}`}
/>
<div className="text-secondary font-normal text-xs font-notosans mt-[8px] text-right">
{NICK_NAME_PAGE.GUIDE}
<div className="w-full flex relative justify-between">
<button
type="button"
className="w-[30%] mt-2 text-sm py-1 rounded-md bg-gray-200"
onClick={() => checkCanUseNickname()}
>
중복확인
</button>
<div className="text-secondary font-normal text-xs font-notosans mt-[8px] text-right">
{NICK_NAME_PAGE.GUIDE}
</div>
</div>
</div>

Expand All @@ -135,11 +185,9 @@ const UserNickname = ({ pageNum, isEdit }: UserNicknameProps) => {
onClick={nextRoute}
buttonType="userinfo"
className={`relative mb-7 rounded-md text-darkgray ${
inputValue.length > 0
? buttonStyles.activeStyles
: buttonStyles.defaultStyles
canNext ? buttonStyles.activeStyles : buttonStyles.defaultStyles
}`}
isActive={inputValue.trim() !== ''}
isActive={canNext}
/>
</div>
)
Expand Down
133 changes: 133 additions & 0 deletions src/app/_components/information/EditNickname.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
'use client'

import { useEffect, useState } from 'react'
import Input from '../common/Input'
import { INPUT_NICKNAME, NICK_NAME_PAGE } from '@/_constants/info'
import { useRecoilState } from 'recoil'
import { editUserNickname } from '@/_atom/userinfo'
import { useMutation } from '@tanstack/react-query'
import { postCheckNickname } from '@/_service/mypage'
import { putUserNickname } from '@/_service/userinfo'
import Icons from '../common/Icons'
import { exit } from '@/_ui/IconsPath'

interface EditNicknameProps {
userNickname: string
}

const EditNickname = ({ userNickname }: EditNicknameProps) => {
const [inputValue, setInputValue] = useState(userNickname)
const [inputCount, setinputCount] = useState(`${userNickname.length}/5`)
const [editUserInfo, setEditUserInfoState] = useRecoilState(editUserNickname)
const [canUseNickname, setCanUseNickname] = useState(false)

useEffect(() => {
setInputValue(userNickname)
setEditUserInfoState({ ...editUserInfo, userNickname: userNickname })
}, [])

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value.slice(0, INPUT_NICKNAME.MAX)
const koeranOnly = /^[ㄱ-ㅎㅏ-ㅣ가-힣]*$/g
if (!koeranOnly.test(newValue)) {
alert('한글만 입력 가능합니다.')
} else {
setCanUseNickname(false)
setInputValue(newValue)
setEditUserInfoState({ ...editUserInfo, userNickname: newValue })
setinputCount(`${newValue.length}/${INPUT_NICKNAME.MAX}`)
}
}

const inputStyles = {
defaultStyles: 'bg-lightgray',
activeStyles: 'bg-primary',
}

const postUserDataMutation = useMutation({
mutationFn: () => postCheckNickname(editUserInfo.userNickname),
onSuccess: (data) => {
if (data.isDuplicate) {
setCanUseNickname(false)
alert('이미 사용중인 닉네임입니다.')
} else {
setCanUseNickname(true)
alert('사용 가능한 닉네임입니다!')
}
},
onError: () => {
setCanUseNickname(false)
alert('다시 시도해 주세요.')
},
})

const putUserNicknameMutation = useMutation({
mutationFn: () => putUserNickname(editUserInfo.userNickname),
onSuccess: (data) => {
window.location.reload()
},
onError: () => alert('다시 시도해 주세요.'),
})

const checkCanUseNickname = () => {
postUserDataMutation.mutate()
}

const changeNickname = () => {
putUserNicknameMutation.mutate()
}

return (
<div className="w-[100%] mt-4 flex-col">
<div className="w-full flex justify-between items-center px-2">
<Input
sort="info"
textValue={inputValue}
placeholder={NICK_NAME_PAGE.INPUTBOX}
onChange={handleInputChange}
className="w-[73%] text-sm placeholder:text-secondary placeholder:text-xs placeholder:leading-[174%] focus:outline-none"
/>
<span className="block text-sm w-7 relative text-secondary">
{inputCount}
</span>
</div>
<div
className={`w-full h-[2px] mt-[3px] rounded-[2.415px] ${
inputValue.length > 0
? inputStyles.activeStyles
: inputStyles.defaultStyles
}`}
/>
<div className="w-full text-xs px-2 text-black flex items-center justify-between mt-4">
<button
type="button"
className="w-[40%] py-1 rounded-md bg-gray-200"
onClick={checkCanUseNickname}
>
중복확인
</button>
<button
type="button"
className={`w-[40%] py-1 rounded-md ${
canUseNickname ? 'text-primary bg-onepink' : 'bg-gray-200'
}`}
onClick={changeNickname}
disabled={!canUseNickname}
>
수정하기
</button>
<div className="cursor-pointer">
<Icons
name={exit}
className="w-3 h-3"
onClick={() =>
setEditUserInfoState({ ...editUserInfo, isNicknameEdit: false })
}
/>
</div>
</div>
</div>
)
}

export default EditNickname
Loading

0 comments on commit b5d1062

Please sign in to comment.