Skip to content

Commit 4494e5e

Browse files
committed
feat: implements email input UI
1 parent dc823ac commit 4494e5e

File tree

8 files changed

+102
-11
lines changed

8 files changed

+102
-11
lines changed

.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
REACT_APP_API_HOST=http://localhost:5000/
1+
REACT_APP_API_HOST=http://localhost:5001/
22
PUBLIC_URL=/
33
REACT_APP_GRAPHQL_HOST=https://v2cdn.velog.io/
44
REACT_APP_GRAPHQL_HOST_NOCDN=https://v2.velog.io/

src/components/auth/AuthSocialButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const AuthSocialButton: React.FC<AuthSocialButtonProps> = ({
6262
const host =
6363
process.env.NODE_ENV === 'production'
6464
? process.env.REACT_APP_API_HOST
65-
: 'http://localhost:5000/';
65+
: 'http://localhost:5001/';
6666

6767
const redirectTo = `${host}api/v2/auth/social/redirect/${provider}?next=${currentPath}&isIntegrate=${
6868
isIntegrate ? 1 : 0
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React, { useState } from 'react';
2+
import SettingRow from './SettingRow';
3+
import useInput from '../../lib/hooks/useInput';
4+
import SettingInput from './SettingInput';
5+
import styled from 'styled-components';
6+
import Button from '../common/Button';
7+
8+
export type SettingEmailRowProps = {
9+
email: string;
10+
onUpdateEmail: (email: string) => Promise<void>;
11+
};
12+
13+
function SettingEmailRow({ email, onUpdateEmail }: SettingEmailRowProps) {
14+
const [edit, setEdit] = useState(false);
15+
const [value, onChange] = useInput(email);
16+
17+
const onSubmit = async (e: React.FormEvent) => {
18+
e.preventDefault();
19+
await onUpdateEmail(value);
20+
setEdit(false);
21+
};
22+
23+
return (
24+
<SettingRow
25+
title="이메일 주소"
26+
description="회원 인증 또는 시스템에서 발송하는 이메일을 수신하는 주소입니다."
27+
editButton={!edit}
28+
onClickEdit={() => setEdit(true)}
29+
editButtonText="변경"
30+
>
31+
{edit ? (
32+
<Form onSubmit={onSubmit}>
33+
<SettingInput
34+
value={value}
35+
onChange={onChange}
36+
placeholder="이메일"
37+
/>
38+
<Button>변경</Button>
39+
</Form>
40+
) : (
41+
email
42+
)}
43+
</SettingRow>
44+
);
45+
}
46+
47+
const Form = styled.form`
48+
display: flex;
49+
align-items: center;
50+
input {
51+
flex: 1;
52+
margin-right: 1rem;
53+
}
54+
`;
55+
56+
export default SettingEmailRow;

src/components/setting/SettingRow.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export type SettingRowProps = {
1010
onClickEdit?: () => void;
1111
editButton?: boolean;
1212
description?: string;
13+
editButtonText?: string;
1314
};
1415

1516
function SettingRow({
@@ -18,6 +19,7 @@ function SettingRow({
1819
editButton,
1920
description,
2021
onClickEdit,
22+
editButtonText,
2123
}: SettingRowProps) {
2224
return (
2325
<Row>
@@ -29,7 +31,10 @@ function SettingRow({
2931
<div className="contents">{children}</div>
3032
{editButton && (
3133
<div className="edit-wrapper">
32-
<SettingEditButton onClick={onClickEdit} />
34+
<SettingEditButton
35+
onClick={onClickEdit}
36+
customText={editButtonText}
37+
/>
3338
</div>
3439
)}
3540
</div>

src/components/setting/SettingRows.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import React from 'react';
22
import styled from 'styled-components';
3-
import SettingRow from './SettingRow';
43
import SettingTitleRow from './SettingTitleRow';
54
import SettingSocialInfoRow from './SettingSocialInfoRow';
65
import SettingEmailRulesRow from './SettingEmailRulesRow';
76
import { createFallbackTitle } from '../../lib/utils';
87
import { ProfileLinks } from '../../lib/graphql/user';
98
import SettingUnregisterRow from './SettingUnregisterRow';
109
import media from '../../lib/styles/media';
10+
import SettingEmailRow from './SettingEmailRow';
1111

1212
export type SettingRowsProps = {
1313
title: string | null;
1414
username: string;
1515
email: string;
1616
onUpdateTitle: (title: string) => Promise<any>;
17+
onUpdateEmail: (email: string) => Promise<any>;
1718
onUpdateSocialInfo: (profileLinks: ProfileLinks) => Promise<any>;
1819
onUpdateEmailRules: (params: {
1920
promotion: boolean;
@@ -41,6 +42,7 @@ function SettingRows({
4142
userMeta,
4243
email,
4344
onUpdateTitle,
45+
onUpdateEmail,
4446
onUpdateSocialInfo,
4547
onUpdateEmailRules,
4648
onUnregister,
@@ -52,12 +54,7 @@ function SettingRows({
5254
onUpdateTitle={onUpdateTitle}
5355
/>
5456
<SettingSocialInfoRow {...profileLinks} onUpdate={onUpdateSocialInfo} />
55-
<SettingRow
56-
title="이메일 주소"
57-
description="회원 인증 또는 시스템에서 발송하는 이메일을 수신하는 주소입니다."
58-
>
59-
{email}
60-
</SettingRow>
57+
<SettingEmailRow email={email} onUpdateEmail={onUpdateEmail} />
6158
{userMeta && (
6259
<SettingEmailRulesRow
6360
notification={userMeta.email_notification}

src/containers/setting/SettingRowsContainer.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import useUserProfile from './hooks/useUserProfile';
77
import useUpdateSocialInfo from './hooks/useUpdateSocialInfo';
88
import useUpdateEmailRules from './hooks/useUpdateEmailRules';
99
import useUnregister from './hooks/useUnregister';
10+
import useUpdateEmail from './hooks/useUpdateEmail';
1011

1112
export type SettingRowsContainerProps = {};
1213

@@ -16,6 +17,7 @@ function SettingRowsContainer(props: SettingRowsContainerProps) {
1617
const user = useSelector((state: RootState) => state.core.user);
1718
const updateSocialInfo = useUpdateSocialInfo();
1819
const { update: updateEmailRules } = useUpdateEmailRules();
20+
const { update: updateEmail } = useUpdateEmail();
1921
const unregister = useUnregister();
2022

2123
const onUpdateEmailRules = useCallback(
@@ -42,6 +44,7 @@ function SettingRowsContainer(props: SettingRowsContainerProps) {
4244
username={user.username}
4345
email={user.email}
4446
onUpdateTitle={updateTitle}
47+
onUpdateEmail={updateEmail}
4548
profileLinks={profile.profile_links}
4649
onUpdateSocialInfo={updateSocialInfo.update}
4750
onUpdateEmailRules={onUpdateEmailRules}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useMutation } from '@apollo/react-hooks';
2+
import gql from 'graphql-tag';
3+
import { useCallback } from 'react';
4+
5+
const UPDATE_USER_EMAIL = gql`
6+
mutation UpdateUserEmail($email: String!) {
7+
update_user_email(email: $email) {
8+
email
9+
}
10+
}
11+
`;
12+
13+
export default function useUpdateEmail() {
14+
const [updateUserEmail] = useMutation(UPDATE_USER_EMAIL);
15+
16+
const update = useCallback(
17+
(email: string) => {
18+
return updateUserEmail({
19+
variables: {
20+
email,
21+
},
22+
});
23+
},
24+
[updateUserEmail],
25+
);
26+
27+
return {
28+
update,
29+
};
30+
}

src/index.server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ app.use(
1717
);
1818

1919
const proxyMiddleware = proxy(
20-
process.env.REACT_APP_API_HOST ?? 'http://localhost:5000',
20+
process.env.REACT_APP_API_HOST ?? 'http://localhost:5001',
2121
{},
2222
);
2323

0 commit comments

Comments
 (0)