Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 프로필 페이지 뷰 추가 #59

Merged
merged 6 commits into from
May 22, 2020
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
4 changes: 4 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import SignIn from 'frameworks/web/components/pages/SignIn/SignIn';
import SignUp from 'frameworks/web/components/pages/SignUp/SignUp';
import Footer from 'frameworks/web/components/organisms/Footer/Footer';
import SpeakerApply from 'frameworks/web/components/pages/SpeakerApply/SpeakerApply';
import Profile from 'frameworks/web/components/pages/Profile/Profile';
import StatusPage from 'frameworks/web/components/pages/StatusPage/StatusPage';

import apolloClient, { initStorage } from 'frameworks/web/apollo';
Expand Down Expand Up @@ -48,6 +49,9 @@ function App() {
<Route path={ROUTES.STATUS}>
<StatusPage />
</Route>
<Route path={ROUTES.PROFILE}>
<Profile email="[email protected]" name="테스트" phone="010-1234-5678" />
</Route>
</Switch>
<Footer />
</Router>
Expand Down
10 changes: 9 additions & 1 deletion src/frameworks/web/components/atoms/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ export default {
export const DefaultButton = () => {
const label = text('Text', '바로가기');
const isPrimary = boolean('IsPrimary', true);
return <Button label={label} isPrimary={isPrimary} onClick={action('button-clicked')} />;
const isEnabled = boolean('isEnabled', true);
return (
<Button
label={label}
isPrimary={isPrimary}
isEnabled={isEnabled}
onClick={action('button-clicked')}
/>
);
};

export const FieldButton = () => {
Expand Down
34 changes: 24 additions & 10 deletions src/frameworks/web/components/atoms/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import { IBaseButton, IButton } from 'interfaces/frameworks/web/components/atoms

const BaseButton = styled.button`
font-family: 'Muli', 'Noto Sans KR', sans-serif;
background-color: ${(props: IBaseButton) =>
props.isPrimary ? theme.color.primary.Scarlet : theme.color.primary.Black};
color: ${theme.color.primary.White} !important;
opacity: ${(props: IBaseButton) => (props.isEnabled ? '1' : '0.3')};
border: none;
background-color: ${(props: IBaseButton) => props.bgColor};
color: ${(props: IBaseButton) =>
props.isEnabled ? theme.color.primary.White : theme.color.secondary.Moon} !important;
border: 1px solid
${(props: IBaseButton) => (props.isEnabled ? props.bgColor : theme.color.secondary.Ash)};
outline: none;
cursor: ${(props: IBaseButton) => (props.isEnabled ? 'pointer' : 'inherit')};
border-radius: 10px;
Expand All @@ -19,8 +19,9 @@ const BaseButton = styled.button`

@media (hover: hover) {
&:hover {
background-color: ${(props: IBaseButton) =>
props.isPrimary ? theme.color.primary.Salmon : theme.color.secondary.Nickel};
background-color: ${(props: IBaseButton) => props.hoverColor};
border-color: ${(props: IBaseButton) =>
props.isEnabled ? props.hoverColor : theme.color.secondary.Ash};
}
}
`;
Expand Down Expand Up @@ -71,16 +72,29 @@ export default function Button({
type = 'default',
label,
isPrimary = false,
onClick = null,
onClick = () => undefined,
isEnabled = true,
style,
}: IButton): React.ReactElement {
const ButtonComponent = BUTTONS[type];
let bgColor: string;
let hoverColor: string;
if (!isEnabled) {
bgColor = theme.color.primary.White;
hoverColor = bgColor;
} else if (isPrimary) {
bgColor = theme.color.primary.Scarlet;
hoverColor = theme.color.primary.Salmon;
} else {
bgColor = theme.color.primary.Black;
hoverColor = theme.color.secondary.Nickel;
}
return (
<ButtonComponent
isPrimary={isPrimary}
onClick={isEnabled ? onClick : undefined}
bgColor={bgColor}
hoverColor={hoverColor}
isEnabled={isEnabled}
onClick={() => (isEnabled ? onClick() : undefined)}
style={style}
>
{label}
Expand Down
6 changes: 3 additions & 3 deletions src/frameworks/web/components/atoms/TextField/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ export default function TextField(props: ITextField): React.ReactElement {
const {
defaultLabel,
style,
type,
readOnly,
type = 'text',
readOnly = false,
value,
isButton,
isButton = false,
isError,
buttonSrc,
onButtonClicked,
Expand Down
171 changes: 171 additions & 0 deletions src/frameworks/web/components/organisms/Profile/ProfileInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* eslint-disable react/no-unused-state */
/* eslint-disable no-undef */
/* eslint-disable no-alert */
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import styled from 'styled-components';
import theme from 'theme';
import DividedCard from 'frameworks/web/components/molecules/DividedCard/DividedCard';
import Label from 'frameworks/web/components/atoms/Label/Label';
import TextField from 'frameworks/web/components/atoms/TextField/TextField';
import Button from 'frameworks/web/components/atoms/Button/Button';
import { IProfile } from 'interfaces/frameworks/web/components/pages/Profile/IProfile';
import { IProfileInfoState } from 'interfaces/frameworks/web/components/organisms/Profile/IProfileInfo';
import ProfileIllust from 'assets/illust/speaker-apply-illustration.png';

const TextLabelContainer = styled.div`
width: 93px;
float: left;
text-align: right;
`;

const TextFieldContainer = styled.div`
width: 445px;
float: right;
padding-bottom: 64px;
`;

const WarningTextContainer = styled.div`
float: right;
width: 400px;
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 16px;
`;

const WithdrawContainer = styled.div`
width: 289px;
margin-top: 17px;
float: right;
display: flex;
justify-content: space-between;
`;

export default function ProfileInfo(props: IProfile): React.ReactElement {
const { name, email, phone } = props;
const [state, setState] = useState<IProfileInfoState>({ name, phone, password: '' });
const history = useHistory();
const onPasswordChangeClicked = () => {
// 비밀번호 변경 버튼 클릭시 작동되는 함수
};

const onSaveButtonClicked = () => {
// save 버튼 클릭시 작동되는 함수
};

const onWithdrawClicked = () => {
history.push('/profile/withdraw');
};
return (
<div>
<DividedCard title="PROFILE" leftPadding="70px 0 0 0">
{{
left: (
<div>
<img
src={ProfileIllust}
alt="강연자 지원 이미지"
style={{ width: '380px', height: '450px', margin: '75px 0 0 0' }}
/>
</div>
),
right: (
<div style={{ margin: '16px 95px 0 68px' }}>
<TextLabelContainer>
<Label type="H5" style={{ marginTop: '14px' }} color={theme.color.secondary.Nickel}>
이름
</Label>
<Label type="H5" style={{ margin: '54px 0' }} color={theme.color.secondary.Nickel}>
이메일
</Label>
<Label
type="H5"
style={{ marginBottom: '54px' }}
color={theme.color.secondary.Nickel}
>
휴대폰
</Label>
<Label type="H5" color={theme.color.secondary.Nickel}>
현재 비밀번호
</Label>
</TextLabelContainer>
<TextFieldContainer>
<TextField
defaultLabel="이름을 입력하세요"
onValueChange={(data: string) =>
setState({ name: data, phone: state.phone, password: state.password })
}
style={{ width: 'auto' }}
value={state.name}
/>
<TextField
defaultLabel=""
onValueChange={() => undefined}
style={{ width: 'auto', margin: '24px 0' }}
readOnly
value={email}
/>
<TextField
defaultLabel="전화번호를 입력하세요"
onValueChange={(data: string) =>
setState({ name: state.name, phone: data, password: state.password })
}
style={{ width: 'auto' }}
value={state.phone}
/>
<div>
<Button
label="비밀번호 변경"
onClick={onPasswordChangeClicked}
style={{ float: 'right' }}
/>
<TextField
defaultLabel="현재 비밀번호를 입력하세요"
onValueChange={(data: string) =>
setState({ name: state.name, phone: state.phone, password: data })
}
style={{ width: '228px', marginTop: '24px' }}
value={state.password}
/>
</div>
<WarningTextContainer>
<img
src="warning.svg"
alt="경고 아이콘"
style={{ width: '20px', height: '18px' }}
/>
<div style={{ display: 'flex' }}>
<Label type="P2" color={theme.color.alert.Warning}>
현재 비밀번호
</Label>
<Label type="P2" color={theme.color.secondary.Moon}>
를 입력하셔야 개인정보 수정을 완료할 수 있습니다.
</Label>
</div>
</WarningTextContainer>
</TextFieldContainer>
<Button
type="default"
label="저장하기"
isPrimary
onClick={onSaveButtonClicked}
style={{ float: 'right' }}
/>
</div>
),
}}
</DividedCard>
<div style={{ width: '1100px', margin: '0 auto' }}>
<WithdrawContainer>
<Label type="P1" color={theme.color.secondary.Nickel}>
계정을 삭제하시겠습니까?
</Label>
<Label type="H5" color={theme.color.secondary.Nickel} onClick={onWithdrawClicked}>
계정 삭제하기
</Label>
</WithdrawContainer>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import styled from 'styled-components';
import theme from 'theme';
import Label from 'frameworks/web/components/atoms/Label/Label';
import Button from 'frameworks/web/components/atoms/Button/Button';
import ContentsBox from 'frameworks/web/components/atoms/ContentsBox/ContentsBox';
import TextField from 'frameworks/web/components/atoms/TextField/TextField';

const CardContainer = styled(ContentsBox)`
width: 730px;
height: auto;
padding: 64px 0 64px 0;
margin: 0 auto;
background-color: white;
text-align: center;
`;

const ContextContainer = styled.div`
margin: 40px 0;
`;

const ButtonContainer = styled.div`
text-align: center;
margin-top: 48px;
`;

const EachButtonContainer = styled.div`
display: inline-block;
margin: 0 15px 0 15px;
`;

export default function ProfileWithdraw(): React.ReactElement {
const [checkText, setCheckText] = useState('');
const history = useHistory();

const onTextValueChange = (data: string) => {
setCheckText(data);
};

const onCancleButtonClicked = () => {
history.goBack();
};

const onDeleteButtonClicked = () => {
// 계정 삭제 로직 추가
};
return (
<CardContainer isDarkBackground={false}>
<Label type="H4" color={theme.color.primary.Azure}>
계정 삭제
</Label>
<ContextContainer>
<Label type="P1" color={theme.color.secondary.Moon} style={{ marginTop: '24px' }}>
계정을 삭제하시면 해당 홈페이지와 관련된 서비스를 이용할 수 없으며,
</Label>
<Label type="P1" color={theme.color.secondary.Moon}>
작성중인 신청폼이 모두 없어집니다. 계정 삭제를 완료하시려면
</Label>
<Label type="P1" color={theme.color.secondary.Moon}>
아래 빈칸에 <span style={{ color: '#F5503D', fontWeight: 'bold' }}>삭제하겠습니다</span>를
입력해주세요.
</Label>
</ContextContainer>
<TextField
defaultLabel="삭제하겠습니다"
onValueChange={onTextValueChange}
style={{ width: '350px', margin: '0 auto' }}
/>
<ButtonContainer>
<EachButtonContainer>
<Button label="취소" onClick={onCancleButtonClicked} />
</EachButtonContainer>
<EachButtonContainer>
<Button
label="삭제하기"
isPrimary
isEnabled={checkText === '삭제하겠습니다'}
onClick={onDeleteButtonClicked}
/>
</EachButtonContainer>
</ButtonContainer>
</CardContainer>
);
}
30 changes: 30 additions & 0 deletions src/frameworks/web/components/pages/Profile/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import styled from 'styled-components';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import theme from 'theme';
import { IProfile } from 'interfaces/frameworks/web/components/pages/Profile/IProfile';
import ProfileInfo from 'frameworks/web/components/organisms/Profile/ProfileInfo';
import ProfileWithdraw from 'frameworks/web/components/organisms/Profile/ProfileWithdraw';
import * as ROUTES from 'utils/routes';

const ProfileContainer = styled.div`
padding: 200px 0 120px 0;
background-color: ${theme.color.secondary.Ash};
`;

export default function Profile({ name, email, phone }: IProfile): React.ReactElement {
return (
<Router>
<ProfileContainer>
<Switch>
<Route exact path={ROUTES.PROFILE}>
<ProfileInfo name={name} email={email} phone={phone} />
</Route>
<Route path={ROUTES.PROFILE_WITHDRAW}>
<ProfileWithdraw />
</Route>
</Switch>
</ProfileContainer>
</Router>
);
}
Loading