Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

[feat] my profile page 구현 #27

Merged
merged 8 commits into from
Oct 19, 2023
Merged

Conversation

altmit
Copy link
Member

@altmit altmit commented Oct 19, 2023

구현한 것

  • 디자인적 요소를 제외하고 MyProfile에 필요한 대부분의 기능을 구현 했습니다.
    • NavButton은 MUI 사용법을 확인할 겸 MUI를 사용해서 구현 했습니다. MUI 링크
    • 프로필 이미지 추가, 삭제 구현 했습니다.
    • 추가 작업이 필요한 부분 TODO 남겨 놨습니다.
    • 1천 단위로 콤마 추가하는 유틸 함수 추가 했습니다.
이미지

내 프로필

1

내 포트폴리오

2

ToReviewers

  • 네이밍 관련 제 임의로 결정한게 많아 확인 한번 부탁 드립니다.
  • 아직 카카모토비와 박하의 코드의 컨벤션을 잘 따라가지 못하고 있을 것 같아 그 부분도 피드백 해주세요.

프로필 삭제, 저장 로직

  • 이미지를 삭제 했을 경우 FineAnts의 기본 프로필로 변경되어야 한다 생각하는데 삭제 상태를 저장하면 이미지를 서버로부터 받을 것 인가? 아니면 서버는 단순 프로필이 비어있다는 값만 전달하고 프론트에서 이미지를 보여줄 것인가?
  • 위 세부적인 로직에 따라서 버튼의 disabled, 이미지 관련 state 관리가 변경될 것 같아 아직 구현하지 않았습니다

내 프로필 변경의 구조

  • 지금 임시 디자인에서는 닉네임, 비밀번호 input 아래 하나의 저장 버튼이 있는데 이때 저장 버튼을 눌렀을 경우 두개의 값을 보낼 것인가, 아니면 입력된 값만 보낼 것 인가
    • 비밀번호 변경의 경우 회원가입과 똑같이 비밀번호 확인 input도 필요해 보입니다.
  • 또는 개별의 저장 버튼을 놓을 것 인가 결정이 필요해 보입니다.

테이블 컴포넌트

  • 저희 서비스에서 생각보다 여러 곳에서 테이블 구조를 사용하고 있는데 박하의 pr을 보며 합성 컴포넌트를 이용한다면 재사용 가능한 테이블 컴포넌트도 만들 수 있지 않을까 생각도 들었습니다.
    • 이유는 obj의 property값에 맞는 td하나씩 만드는게 상당히 귀찮을 것 같아서
  • 디자인에 따라, api로 주고 받을 값의 네이밍에 따라 구현이 조금 달라질 수 있을 것 같아 우선은 jsx로 대충 구현만 해놓았습니다.

@altmit altmit added frontend 프론트 이슈 feat 새로운 기능 추가 labels Oct 19, 2023
@altmit altmit self-assigned this Oct 19, 2023
@altmit altmit mentioned this pull request Oct 19, 2023
@altmit altmit changed the title Fe/feat/#11 my profile page [feat] my profile page 구현 Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

말씀하신대로 컴포넌트로 만들어서 watchlist 표도 적용하면 좋을 것 같네요 👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전 프로젝트에서 프로필 사진 관련한 훅을 만들어놔서 재사용해도 좋을 것 같네요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전 프로젝트에서 hook으로 따로 만드셨군요.
저는 이전 프로젝트에서 그냥 프로필을 클릭하면 업로더가 나오는 하나의 버튼을 component로 만들었어서 그냥 그 부분 내용을 가져왔네요.

custom hook을 만들면 꼭 프로필이 아니더라도 이미지를 업로드하는데 재사용 가능한 hook 만들 수 있을 것 같습니다.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후에 리팩토링하며 만들어 놓겠습니다!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pages/ProfilePage/ 안에 MyProfilePage.tsx, PortfoliosSection.tsx, ProfileEditSection.tsx 형태로 파일이 정리되면 구조를 파악하기 훨씬 쉬울 것 같습니다👍

const { section } = useParams();
const [selectedSection, setSelectedSection] = useState(section || "edit");

const onChange = (_: React.MouseEvent<HTMLElement>, section: string) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onSectionChange가 좋을 것 같습니다

type Props = { portfolio: Portfolio };

function PortfolioItem({ portfolio }: Props) {
const onClickPortfolio = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on + Target/Subject + Event 형태로 handler 네이밍하는거 어떠신가요?

export default function ProfileEditPage() {
// TODO : isCheckedNickname state를 이용해 닉네임 중복 체크 여부를 화면에 css color 또는 icon으로 표시

const [isCheckedNickname, setIsCheckedNickname] = useState(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isNicknameChecked이 더 잘 읽히는 것 같습니다

const [profileImg, setProfileImg] = useState<String | undefined>(SAMPLE_IMG);

const nickname = useText({
initialValue: "",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useText에서 기본으로 ""이기 때문에 initialValue를 인자로 안넣으셔도 됩니다

Comment on lines 54 to 62
const onSaveProfile = () => {
// TODO : api 추가 예정

if (!imgFile) return;

console.log(imgFile);
};

const onNicknameCheck = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on + Event/Action + Target/Subject로 할지,
아니면 on + Target/Subject + Event/Action으로 할지 정하면 좋을 것 같습니다 👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on + Target/Subject + Event/Action 으로 통일 하도록 노력해 보겠습니다!

};

return (
<ProfileEdit>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

styled-components docs 예시에도 그렇고, 전 주로 최상단의 태그를 해당 함수에 Styled를 prefix로 주고 있는데 어떻게 생각하시나요? 이렇게 통일하면 파악이 빨라지는 것 같습니다

Ex: 컴포넌트 이름이 ProfileEditPage이면, styled components으로 StyledProfileEditPage.

@Kakamotobi
Copy link
Member

프로필 삭제, 저장 로직

  • 이미지를 삭제 했을 경우 FineAnts의 기본 프로필로 변경되어야 한다 생각하는데 삭제 상태를 저장하면 이미지를 서버로부터 받을 것 인가? 아니면 서버는 단순 프로필이 비어있다는 값만 전달하고 프론트에서 이미지를 보여줄 것인가?
  • 위 세부적인 로직에 따라서 버튼의 disabled, 이미지 관련 state 관리가 변경될 것 같아 아직 구현하지 않았습니다
  • 저는 클라이언트에서 기본 이미지를 가지고 있고 서버에서는 예를 들어서 profileImgUrl을 빈값으로 주는게 좋을 것 같습니다.

내 프로필 변경의 구조

  • 지금 임시 디자인에서는 닉네임, 비밀번호 input 아래 하나의 저장 버튼이 있는데 이때 저장 버튼을 눌렀을 경우 두개의 값을 보낼 것인가, 아니면 입력된 값만 보낼 것 인가

    • 비밀번호 변경의 경우 회원가입과 똑같이 비밀번호 확인 input도 필요해 보입니다.
  • 또는 개별의 저장 버튼을 놓을 것 인가 결정이 필요해 보입니다.

  • 하나의 저장 버튼이 있고, input 중 변경이 된게 있으면 버튼을 활성화하는게 좋을 것 같습니다.
  • 그리고 변경된 필드만 서버로 보내주는게 낫지 않을까 싶습니다.

@altmit altmit mentioned this pull request Oct 19, 2023
export default function MyProfilePage() {
const navigate = useNavigate();
const { section } = useParams();
const [selectedSection, setSelectedSection] = useState(section || "edit");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

시도해보지는 않아서 될지 잘 모르겠지만, 아래처럼 useState을 제거하고도 가능하지 않을까요?

const { section = "portfolios" } = useParams(); // 기본을 "portfolios" section으로 (혹시 다른 곳에서 "/portfolio/portfolios"간 아닌 "/portfolio"로 이동했을 시)

const onSectionChange = (
  _: MouseEvent<HTMLElement>,
  newSection: string
) => {
  navigate(`${Routes.PROFILE}/${newSection}`);
}

return (
  <ToggleButtonGroup value={section} onChange={onSectionChange}>
    // ...
  </ToggleButtonGroup>
);

Copy link
Member Author

@altmit altmit Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우선 카카모토비가 작성해 주신 코드를 사용하면 state 없이 동작이 가능 합니다!

혹시 다른 곳에서 "/portfolio/portfolios"가 아닌 "/portfolio"로 이동했을 시

위 로직을 처리하려면 route에서 따로 리다이렉트를 시키든,
MyProfilePage 컴포넌트에서 section이 비어 있는 경우 /profile/portfolios 로 리다이렉트 시키는 방법이 필요 할 것 같습니다.

추가

route에서 이미 걸러지기 때문에 route에서 리다이렉트 시켜야 할 것 같네요.

ex)

  <Route
    path={Routes.PROFILE}
    element={<Navigate to={`${Routes.PROFILE}/${Routes.PORTFOLIOS}`} />}
  />
  <Route
    path={`${Routes.PROFILE}/:section`}
    element={<MyProfilePage />}
  />

- 불필요한 state 제거
- MyProfilePage에 section 없이 이동시 portfoliosPage로 리다이렉트
@Kakamotobi Kakamotobi merged commit 7c3d052 into dev-fe Oct 19, 2023
@altmit altmit deleted the fe/feat/#11-myProfile-page branch October 23, 2023 01:54
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feat 새로운 기능 추가 frontend 프론트 이슈
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants