Skip to content

Commit

Permalink
Merge pull request #300 from Team-Lecue/SP1/Mypage
Browse files Browse the repository at this point in the history
마이페이지를 데브로!!!
  • Loading branch information
jungwoo3490 committed Apr 16, 2024
2 parents 2a64c68 + 1868242 commit 194651d
Show file tree
Hide file tree
Showing 85 changed files with 1,755 additions and 333 deletions.
110 changes: 65 additions & 45 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,53 +1,73 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="./src/assets/favicon.svg" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=0"
/>
<meta name="title" content="레큐 lecue" />
<meta name="description" content="레큐노트에 우리의 마음을 담아 전달해요" />

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="./src/assets/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />
<meta name="title" content="레큐 lecue" />
<meta name="description" content="레큐노트에 우리의 마음을 담아 전달해요" />
<meta property="og:type" content="website" />
<meta property="og:title" content="레큐 lecue" />
<meta
property="og:description"
content="레큐노트에 우리의 마음을 담아 전달해요"
/>
<meta
property="og:image"
content="https://dzfv99wxq6tx0.cloudfront.net/lecue.png"
/>

<meta property="og:type" content="website" />
<meta property="og:title" content="레큐 lecue" />
<meta property="og:description" content="레큐노트에 우리의 마음을 담아 전달해요" />
<meta property="og:image" content="https://dzfv99wxq6tx0.cloudfront.net/lecue.png" />
<meta name="twitter:title" content="레큐 lecue" />
<meta
name="twitter:description"
content="레큐노트에 우리의 마음을 담아 전달해요"
/>
<meta
name="twitter:image"
content="https://dzfv99wxq6tx0.cloudfront.net/lecue.png"
/>

<meta name="twitter:title" content="레큐 lecue" />
<meta name="twitter:description" content="레큐노트에 우리의 마음을 담아 전달해요" />
<meta name="twitter:image" content="https://dzfv99wxq6tx0.cloudfront.net/lecue.png" />
<title>Lecue</title>
</head>

<title>Lecue</title>
</head>
<!-- Google Tag Manager -->
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(),
event: 'gtm.js',
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-PS49HW2G');
</script>
<!-- End Google Tag Manager -->

<!-- Google Tag Manager -->
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(),
event: 'gtm.js',
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-PS49HW2G');
</script>
<!-- End Google Tag Manager -->
<body>
<div id="root"></div>
<div id="lecuenote-modal"></div>
<div id="historyselect-modal"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

<body>
<div id="root"></div>
<div id="lecuenote-modal"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PS49HW2G" height="0" width="0"
style="display: none; visibility: hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

</html>
<!-- Google Tag Manager (noscript) -->
<noscript
><iframe
src="https://www.googletagmanager.com/ns.html?id=GTM-PS49HW2G"
height="0"
width="0"
style="display: none; visibility: hidden"
></iframe
></noscript>
<!-- End Google Tag Manager (noscript) -->
</html>
16 changes: 16 additions & 0 deletions src/EditNickname/api/patchNickname.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { api } from '../../libs/api';

export const patchNickname = async (token: string, nickname: string) => {
const response = await api.patch(
'/api/nickname',
{ nickname: nickname },
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
},
);

return { code: response.data.code };
};
11 changes: 11 additions & 0 deletions src/EditNickname/components/EditButton/EditButton.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import styled from '@emotion/styled';

export const ButtonWrapper = styled.section`
display: flex;
justify-content: center;
align-items: end;
width: 100%;
height: calc(100% - 12.1rem);
margin-bottom: 2rem;
`;
43 changes: 43 additions & 0 deletions src/EditNickname/components/EditButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Button from '../../../components/common/Button';
import usePatchNickname from '../../hooks/usePatchNickname';
import { EditButtonProps } from '../../types/editNicknameTypes';
import * as S from './EditButton.style';

function EditButton({
isActive,
token,
nickname,
handleSetIsValid,
handleSetIsActive,
}: EditButtonProps) {
const patchMutation = usePatchNickname({
handleSetIsValid,
handleSetIsActive,
token,
nickname,
});

const handelClickSubmitBtn = (token: string, nickname: string) => {
const patchNickname = nickname.trim();

patchMutation.mutate({
nickname: patchNickname,
token: token,
});
};

return (
<S.ButtonWrapper>
<Button
type="button"
variant="complete"
disabled={!isActive}
onClick={() => handelClickSubmitBtn(token, nickname)}
>
완료
</Button>
</S.ButtonWrapper>
);
}

export default EditButton;
56 changes: 56 additions & 0 deletions src/EditNickname/components/NicknameInput/NicknameInput.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import styled from '@emotion/styled';

export const NicknameInputWrapper = styled.section`
display: flex;
align-items: center;
flex-direction: column;
width: 100%;
margin-top: 1.2rem;
`;

export const InputContainer = styled.div<{
isEmpty: boolean;
isValid: string;
}>`
display: flex;
gap: 1.6rem;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 1.9rem 2rem;
${({ theme }) => theme.fonts.Body3_R_14};
border: 0.1rem solid
${({ theme, isEmpty, isValid }) =>
isValid === 'special' || isValid === 'duplicate' || isValid === 'space'
? theme.colors.red
: isEmpty || isValid === 'enter'
? theme.colors.LG
: theme.colors.BG};
border-radius: 0.8rem;
background-color: ${({ theme }) => theme.colors.white};
`;

export const Input = styled.input<{ isValid: string }>`
width: 100%;
color: ${({ theme, isValid }) =>
isValid === 'enter' ? theme.colors.MG : theme.colors.BG};
${({ theme }) => theme.fonts.Body2_M_14};
`;

export const WordCount = styled.p`
color: ${({ theme }) => theme.colors.WG};
${({ theme }) => theme.fonts.E_Body2_R_14};
`;

export const WarnigMsg = styled.p`
width: 100%;
padding-top: 0.9rem;
${({ theme }) => theme.fonts.Caption1_R_12};
color: ${({ theme }) => theme.colors.red};
`;
52 changes: 52 additions & 0 deletions src/EditNickname/components/NicknameInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useState } from 'react';

import { NicknameInputProps } from '../../types/editNicknameTypes';
import handleChangeInput from '../../utils/handleCheckInput';
import * as S from './NicknameInput.style';

function NicknameInput({
nickname,
isValid,
handleSetNickname,
handleSetIsValid,
}: NicknameInputProps) {
const [wordCnt, setWordCnt] = useState(0);
const currentNickname: string = localStorage.getItem('nickname') || '';

const handleSetWordCnt = (wordCnt: number) => {
setWordCnt(wordCnt);
};

return (
<S.NicknameInputWrapper>
<S.InputContainer isEmpty={wordCnt === 0} isValid={isValid}>
<S.Input
isValid={isValid}
type="text"
value={nickname}
onChange={(e) => {
handleChangeInput({
handleSetNickname,
handleSetWordCnt,
handleSetIsValid,
currentNickname,
e,
});
}}
/>
<S.WordCount>({wordCnt}/8)</S.WordCount>
</S.InputContainer>
{isValid === 'special' ? (
<S.WarnigMsg>특수문자/이모지는 사용 불가능해요</S.WarnigMsg>
) : isValid === 'duplicate' ? (
<S.WarnigMsg>이미 있는 닉네임이에요</S.WarnigMsg>
) : (
isValid === 'space' && (
<S.WarnigMsg>마지막 공백 제외 2자 이상 입력해주세요</S.WarnigMsg>
)
)}
</S.NicknameInputWrapper>
);
}

export default NicknameInput;
Empty file.
43 changes: 43 additions & 0 deletions src/EditNickname/hooks/usePatchNickname.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { AxiosError } from 'axios';
import { useMutation } from 'react-query';
import { useNavigate } from 'react-router-dom';

import { patchNickname } from '../api/patchNickname';
import {
patchNicknameProps,
usePatchNicknameProps,
} from '../types/editNicknameTypes';

const usePatchNickname = (props: usePatchNicknameProps) => {
const { handleSetIsValid, handleSetIsActive, token, nickname } = props;

const navigate = useNavigate();

const mutation = useMutation({
mutationFn: async ({ token, nickname }: patchNicknameProps) => {
return await patchNickname(token, nickname);
},
onError: (err: AxiosError) => {
const code = err.response?.status;
if (code === 409) {
// 닉네임 중복코드 : 409
handleSetIsValid('duplicate');
handleSetIsActive(false);
} else if (code === 400) {
handleSetIsValid('space');
handleSetIsActive(false);
} else {
navigate('/error');
}
},
onSuccess: () => {
window.localStorage.setItem('token', token);
window.localStorage.setItem('nickname', nickname);
navigate('/');
},
});

return mutation;
};

export default usePatchNickname;
23 changes: 23 additions & 0 deletions src/EditNickname/page/EditNickname.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import styled from '@emotion/styled';

export const EditNicknameBodyWrapper = styled.div`
display: flex;
align-items: center;
flex-direction: column;
width: 100%;
height: calc(100dvh - 5.4rem);
padding: 0 1.6rem;
margin-top: 5.4rem;
`;

export const NicknameInputSection = styled.section`
width: 100%;
margin-top: 3.4rem;
`;

export const NicknameInputSectionTitle = styled.h2`
color: ${({ theme }) => theme.colors.BG};
${({ theme }) => theme.fonts.Head2_SB_18}
`;
Loading

0 comments on commit 194651d

Please sign in to comment.