Skip to content
ProfileEditPage학습 기록

Building the ProfileEditPage UI

1 min readLearningMoved from my Tistory blogRead the Korean original

Today I built the UI for ProfileEditPage, the page where users edit their account information.

Nothing was especially hard, but I wasn't sure how to implement password recovery, and I decided to open a popup when the find-password button is pressed.

In the change-password popup, I think pressing the find-password button should send a reset password by email.

Until now I had typed values in directly instead of using data. For an image, for example, I wrote the image URL straight into src. Now that the markup stage is wrapping up, I need to get ready to actually fetch data through API calls, so I created a Mock folder, wrote user information into a users.ts file, and changed the code to read it from there.

I also installed and tried spellChecker, which my mentor recommended for collaboration.

Edit account information
Figure 1. Edit account information
Change password popup
Figure 2. Change password popup
Preview of the selected image file
Figure 3. Preview of the selected image file
  • Starting tomorrow I'll check the details of every page, and from Wednesday I'll start on the responsive layout!
tsx
import React, {useState} from 'react'
import MyPageBanner from '../Common/MyPageBanner'
import styled from 'styled-components'

import ChangePassword from '../Popups/ChangePassword'

import {users} from '../Mock/users'

export default function ProfileEditPage() {
  const {email, password, nickName, myPage} = users[0]

  const [changePassword, setChangePassword] = useState<boolean>(false)
  const [profilePreview, setProfilePreview] = useState<string>(myPage.profile)
  const [profileBackgroundPreview, setProfileBackgroundPreview] = useState<string>(myPage.background)

  const handlePasswordChange = (e: React.MouseEvent) => {
    e.preventDefault()
    setChangePassword(true)
  }

  const handleProfileImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files && e.target.files[0]

    if (file) {
      const reader = new FileReader()

      reader.onload = () => {
        setProfilePreview(reader.result as string)
      }

      reader.readAsDataURL(file)
    }
  }

  const handleProfileBackgroundImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files && e.target.files[0]

    if (file) {
      const reader = new FileReader()

      reader.onload = () => {
        setProfileBackgroundPreview(reader.result as string)
      }

      reader.readAsDataURL(file)
    }
  }

  const handleEditForm = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    console.log(e)
  }

  return (
    <>
      <MyPageBanner />

      <EditForm onSubmit={handleEditForm} onKeyUp={e => e.key === 'Enter' && e.preventDefault()}>
        <PageTitle>회원정보 수정</PageTitle>
        <Content>
          <Title># 이메일</Title>
          <Input value={email} type='email' readOnly />
        </Content>
        <Content>
          <Title># 비밀번호</Title>
          <Input type='password' required />
          <PassWordChange
            onClick={e => {
              handlePasswordChange(e)
            }}
          >
            *비밀번호 변경
          </PassWordChange>
        </Content>
        <Content>
          <Title># 닉네임</Title>
          <Input value={nickName} type='text' readOnly />
        </Content>
        <Content>
          <Title># 나를 소개하는 한 줄</Title>
          <Input type='text' maxLength={40} placeholder={myPage.ment} />
        </Content>
        <Content>
          <Title># 프로필 이미지</Title>
          <ProfileImgBox>
            <ProfileImg src={profilePreview} alt='ProfileImg' />
            <ImgLabel htmlFor='profileImg'>이미지 선택</ImgLabel>
            <InputImg id='profileImg' type='file' accept='.jpg, .jpeg, .png' onChange={handleProfileImageChange} />
          </ProfileImgBox>
        </Content>
        <Content>
          <Title># 배경 이미지</Title>
          <ProfileImgBox>
            <ProfileBackgroundImg src={profileBackgroundPreview} alt='ProfileBackgroundImg' />
            <ImgLabel htmlFor='profileBackgroundImg'>배경이미지 선택</ImgLabel>
            <InputImg
              id='profileBackgroundImg'
              type='file'
              accept='.jpg, .jpeg, .png'
              onChange={handleProfileBackgroundImageChange}
            />
          </ProfileImgBox>
        </Content>
        <SubmitInput type='submit' value={'작성 완료'} />
      </EditForm>
      <ChangePassword show={changePassword} setChangePassword={setChangePassword} />
    </>
  )
}

const PageTitle = styled.h1`
  font-size: 2rem;
  margin-top: 4rem;
  text-align: center;
`
const EditForm = styled.form`
  width: 92%;
  display: flex;
  flex-direction: column;
  margin: 4rem auto;
  background: rgb(247, 247, 247);
  border-radius: 1rem;
  padding: 0px 2rem 2rem;
  box-sizing: border-box;
`

const Content = styled.div`
  display: flex;
  align-items: center;
  margin-top: 3rem;
`

const Title = styled.h2`
  font-size: 1.5rem;
  margin-right: 2rem;
  width: 15rem;
  text-align: center;
`

const Input = styled.input`
  font-size: 1.3rem;
  width: 27rem;
  border: none;
  padding: 0.8rem 0.8rem 0.8rem 1.3rem;
  border-radius: 1.5rem;
  &:focus {
    outline: none;
  }
`
const PassWordChange = styled.button`
  margin-left: 1rem;
  font-size: 1rem;
  border: none;
  cursor: pointer;
  background: inherit;
  cursor: pointer;

  &:hover {
    color: #1877f2;
  }
`

const ProfileImgBox = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  background: #fff;
  border-radius: 1rem;
`

const ProfileImg = styled.img`
  width: 12rem;
  height: 12rem;
  border-radius: 50%;
  padding: 0.5rem;
`

const ProfileBackgroundImg = styled.img`
  width: 100%;
  height: 25rem;
  border-radius: 1rem;
  padding: 0.3rem;
`

const InputImg = styled.input`
  display: none;
`

const ImgLabel = styled.label`
  cursor: pointer;
  font-size: 1.2rem;
  height: 2rem;
  display: flex;
  width: 100%;
  justify-content: center;
  align-items: center;
  border-dasharray: 100px;
  &:hover {
    color: #1877f2;
    background: #fff;
    border-color: #1877fe;
  }
`
const SubmitInput = styled.input`
  margin-top: 5rem;
  margin-left: auto;
  padding: 0.7rem 1.5rem;
  font-size: 1.2rem;
  cursor: pointer;
  color: #fff;
  background: #1877f2;
  border: none;
  border-radius: 0.5rem;
`
  • #ProfileEditPage UI

More in Learning