Skip to content

Commit

Permalink
Feat/#174: 프로필 이미지 기본 이미지로 설정 기능 (#176)
Browse files Browse the repository at this point in the history
* feat: 회원 가입 시 프로필 이미지를 기본 이미지로 설정하는 기능 추가

* feat: 프로필 수정 시 프로필 이미지를 기본 이미지로 설정하는 기능 추가

* refactor: profile image url이 null 일 경우 기본 이미지를 보여주도록 변경

* refactor: 프로필 기본 이미지 변경 로직 보완 및 커스텀 훅 분리

* refactor: profileImageUrlRequest 파생 상태 제거
  • Loading branch information
semnil5202 authored Jul 5, 2024
1 parent b8e2954 commit 9d5bd71
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 50 deletions.
6 changes: 2 additions & 4 deletions src/pages/FeedDetail/components/ProfileInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Text, Box, Flex, ImageView, PNGDefaultProfileInfo36 } from 'concept-be-design-system';
import { Box, Flex, ImageView, PNGDefaultProfileInfo36, Text } from 'concept-be-design-system';

import useNavigatePage from '../../hooks/useNavigatePage';

Expand All @@ -10,8 +10,6 @@ interface Props {
owner: boolean;
}

// TODO: 프로필 이미지 사진 오류 시 보여줄 기본 프로필 이미지 사진 URL

const ProfileInfo = ({ memberId, imageUrl, nickname, mainSkill, owner }: Props) => {
const { goProfilePage } = useNavigatePage();

Expand All @@ -24,7 +22,7 @@ const ProfileInfo = ({ memberId, imageUrl, nickname, mainSkill, owner }: Props)
return (
<Flex alignItems="center" gap={10} onClick={onClickProfileInfo} cursor={owner ? '' : 'pointer'}>
<Box width={36} height={36} overflow="hidden" borderRadius="0 150px 150px 0">
<ImageView src={imageUrl} alt="프로필" defaultSrc={PNGDefaultProfileInfo36} />
<ImageView src={imageUrl || PNGDefaultProfileInfo36} alt="프로필" defaultSrc={PNGDefaultProfileInfo36} />
</Box>
<Flex direction="column" gap={4}>
<Text font="suit14m" color="b4">
Expand Down
6 changes: 2 additions & 4 deletions src/pages/FeedDetail/components/WriteCommentProfileInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { Text, Box, Flex, ImageView, PNGDefaultProfileInfo36 } from 'concept-be-design-system';
import { Box, Flex, ImageView, PNGDefaultProfileInfo36, Text } from 'concept-be-design-system';

interface Props {
imageUrl: string;
nickname: string;
}

// TODO: 프로필 이미지 사진 오류 시 보여줄 기본 프로필 이미지 사진 URL

const WriteCommentProfileInfo = ({ imageUrl, nickname }: Props) => {
return (
<Flex alignItems="center" gap={10}>
<Box width={36} height={36} overflow="hidden" borderRadius="0 150px 150px 0">
<ImageView src={imageUrl} alt="프로필" defaultSrc={PNGDefaultProfileInfo36} />
<ImageView src={imageUrl || PNGDefaultProfileInfo36} alt="프로필" defaultSrc={PNGDefaultProfileInfo36} />
</Box>
<Text font="suit14m" color="b4">
{nickname}
Expand Down
8 changes: 6 additions & 2 deletions src/pages/Profile/components/ProfileInfoSection.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from '@emotion/styled';
import { theme, Badge, Spacer, Text, Flex, ImageView, PNGDefaultProfileBackground } from 'concept-be-design-system';
import { Badge, Flex, ImageView, PNGDefaultProfileBackground, Spacer, Text, theme } from 'concept-be-design-system';
import { useNavigate } from 'react-router-dom';

import HyperLinkText from '../../components/HyperLinkText/HyperLinkText';
Expand Down Expand Up @@ -39,7 +39,11 @@ const ProfileInfoSection = ({ memberInfo }: Props) => {
return (
<>
<ImageWrapper>
<ImageView src={profileImageUrl} alt="프로필 이미지" defaultSrc={PNGDefaultProfileBackground} />
<ImageView
src={profileImageUrl || PNGDefaultProfileBackground}
alt="프로필 이미지"
defaultSrc={PNGDefaultProfileBackground}
/>
</ImageWrapper>

<Spacer size={300} />
Expand Down
35 changes: 21 additions & 14 deletions src/pages/ProfileEdit/ProfileEdit.page.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import styled from '@emotion/styled';
import {
useCheckbox,
useField,
Box,
Button,
CheckboxContainer,
Dropdown,
Field,
Text,
theme,
Flex,
Header,
ImageView,
PNGDefaultProfileInfo100,
SVGLoginImageWrite,
Spacer,
Tag,
SVGLoginImageWrite,
Text,
theme,
useCheckbox,
useDropdown,
Flex,
Box,
ImageView,
PNGDefaultProfileInfo100,
useField,
} from 'concept-be-design-system';
import { FormEvent } from 'react';

import useProfileEditQuery from './hooks/useProfileEditQuery.ts';
import usePutProfileMutation from './hooks/usePutProfileMutation.ts';
import { DropdownValue, FieldValue } from './types';
import { ReactComponent as SVGToolTip24 } from '../../../public/assets/tool_tip_24.svg';
import { NICKNAME_REG_EXP } from '../../constants/index.ts';
import useAlert from '../../hooks/useAlert.tsx';
import Back from '../../layouts/Back.tsx';
import { getUserId } from '../Profile/utils/getUserId.ts';
import useCheckDuplicateNickname from '../SignUp/hooks/useCheckDuplicateNickname.ts';
import useDefaultProfileImage from '../SignUp/hooks/useDefaultProfileImage.ts';
import useSetDetailSkills from '../SignUp/hooks/useSetDetailSkills.ts';
import useProfileEditQuery from './hooks/useProfileEditQuery.ts';
import usePutProfileMutation from './hooks/usePutProfileMutation.ts';
import { DropdownValue, FieldValue } from './types';

interface CheckboxValue {
goal: CheckboxOption[];
Expand Down Expand Up @@ -66,6 +67,11 @@ const ProfileEdit = () => {
dropdownValue,
onResetDropdown,
});
const { profileImageUrl, onClickSetDefaultProfileImage } = useDefaultProfileImage({
currentProfileImage: my.profileImageUrl,
defaultProfileImage: PNGDefaultProfileInfo100,
});

const { putProfile } = usePutProfileMutation(getUserId(), fieldValue.nickname);

useCheckDuplicateNickname({ nickname: fieldValue.nickname, setFieldErrorValue });
Expand Down Expand Up @@ -109,7 +115,7 @@ const ProfileEdit = () => {
putProfile({
nickname: fieldValue.nickname,
mainSkillId: mainSkills.find(({ name }) => dropdownValue.mainSkill === name)?.id || 0,
profileImageUrl: my.profileImageUrl || '',
profileImageUrl: profileImageUrl === PNGDefaultProfileInfo100 ? null : my.profileImageUrl,
skills: selectedSkillDepths.map(({ id, name }) => ({ skillId: id, level: name.split(', ')[1] })),
joinPurposes: selectedCheckboxId.goal,
livingPlaceId: regions.find((place) => place.name === dropdownValue.region)?.id || 1,
Expand Down Expand Up @@ -145,7 +151,7 @@ const ProfileEdit = () => {
>
<Box position="relative" top={-50} left={0} right={0} margin="auto" width={100} height={100} cursor="pointer">
<Box width={100} height={100} overflow="hidden" borderRadius="0 150px 150px 0">
<ImageView src={my.profileImageUrl} alt="프로필 이미지" defaultSrc={PNGDefaultProfileInfo100} />
<ImageView src={profileImageUrl} alt="프로필 이미지" defaultSrc={PNGDefaultProfileInfo100} />
</Box>
<Flex
justifyContent="center"
Expand All @@ -159,6 +165,7 @@ const ProfileEdit = () => {
shadow="rgba(100, 100, 111, 0.2) 0px 7px 29px"
bottom={0}
right={0}
onClick={onClickSetDefaultProfileImage}
>
<SVGLoginImageWrite />
</Flex>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/ProfileEdit/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ export type DetailSkills = Record<number, DetailSkillOption[]>;
export interface PutSignUp {
nickname: string;
mainSkillId: number;
profileImageUrl: string;
profileImageUrl: string | null;
skills: Omit<ProfileSkill, 'skillName'>[];
joinPurposes: number[];
livingPlaceId: number;
workingPlace?: string;
introduction?: string;
workingPlace: string | null;
introduction: string | null;
}

export interface ProfileSkill {
Expand Down
40 changes: 21 additions & 19 deletions src/pages/SignUp/SignUp.page.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
import styled from '@emotion/styled';
import {
useCheckbox,
useField,
Box,
Button,
CheckboxContainer,
Dropdown,
Field,
Text,
theme,
Flex,
Header,
ImageView,
PNGDefaultProfileInfo100,
SVGLoginImageWrite,
Spacer,
Tag,
SVGLoginImageWrite,
Text,
theme,
useCheckbox,
useDropdown,
Flex,
Box,
ImageView,
PNGDefaultProfileInfo100,
useField,
} from 'concept-be-design-system';
import { FormEvent } from 'react';
import { useLocation } from 'react-router-dom';

import SEOMeta from '../../components/SEOMeta/SEOMeta.tsx';
import { NICKNAME_REG_EXP } from '../../constants/index.ts';
import useAlert from '../../hooks/useAlert.tsx';
import { OauthMemberInfo } from '../../types/login.ts';
import useCheckDuplicateNickname from './hooks/useCheckDuplicateNickname.ts';
import useDefaultProfileImage from './hooks/useDefaultProfileImage.ts';
import useSetDetailSkills from './hooks/useSetDetailSkills.ts';
import useSignUpMutation from './hooks/useSignUpMutation.ts';
import useSignUpQuery from './hooks/useSignUpQuery.ts';
import useValidateUserInfo from './hooks/useValidateUserInfo.ts';
import { DropdownValue, FieldValue } from './types';
import SEOMeta from '../../components/SEOMeta/SEOMeta.tsx';
import { NICKNAME_REG_EXP } from '../../constants/index.ts';
import useAlert from '../../hooks/useAlert.tsx';
import { OauthMemberInfo } from '../../types/login.ts';

interface CheckboxValue {
goal: CheckboxOption[];
Expand Down Expand Up @@ -68,6 +69,10 @@ const SignUpPage = () => {
dropdownValue,
onResetDropdown,
});
const { profileImageUrl, onClickSetDefaultProfileImage } = useDefaultProfileImage({
currentProfileImage: memberInfo?.profileImageUrl || '',
defaultProfileImage: PNGDefaultProfileInfo100,
});

useValidateUserInfo(memberInfo);
useCheckDuplicateNickname({ nickname: fieldValue.nickname, setFieldErrorValue });
Expand Down Expand Up @@ -111,7 +116,7 @@ const SignUpPage = () => {
postSignUp({
nickname: fieldValue.nickname,
mainSkillId: mainSkills.find(({ name }) => dropdownValue.mainSkill === name)?.id || 0,
profileImageUrl: memberInfo?.profileImageUrl || '',
profileImageUrl: profileImageUrl === PNGDefaultProfileInfo100 ? null : memberInfo?.profileImageUrl || '',
skills: selectedSkillDepths.map(({ id, name }) => ({ skillId: id, level: name.split(', ')[1] })),
joinPurposes: selectedCheckboxId.goal,
livingPlaceId: regions.find((place) => place.name === dropdownValue.region)?.id || 1,
Expand Down Expand Up @@ -162,11 +167,7 @@ const SignUpPage = () => {
cursor="pointer"
>
<Box width={100} height={100} overflow="hidden" borderRadius="0 150px 150px 0">
<ImageView
src={memberInfo?.profileImageUrl || PNGDefaultProfileInfo100}
alt="프로필 이미지"
defaultSrc={PNGDefaultProfileInfo100}
/>
<ImageView src={profileImageUrl} alt="프로필 이미지" defaultSrc={PNGDefaultProfileInfo100} />
</Box>
<Flex
justifyContent="center"
Expand All @@ -180,6 +181,7 @@ const SignUpPage = () => {
shadow="rgba(100, 100, 111, 0.2) 0px 7px 29px"
bottom={0}
right={0}
onClick={onClickSetDefaultProfileImage}
>
<SVGLoginImageWrite />
</Flex>
Expand Down
24 changes: 24 additions & 0 deletions src/pages/SignUp/hooks/useDefaultProfileImage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useState } from 'react';
import useConfirm from '../../../hooks/useConfirm';

interface Props {
currentProfileImage: string | null;
defaultProfileImage: string;
}

const useDefaultProfileImage = ({ currentProfileImage, defaultProfileImage }: Props) => {
const openConfirm = useConfirm();
const [profileImageUrl, setProfileImageUrl] = useState<string>(currentProfileImage || defaultProfileImage);

const onClickSetDefaultProfileImage = async () => {
const isDeleteProfileImage = await openConfirm({
content: '기본 프로필 이미지로 변경하시겠습니까?',
});

if (isDeleteProfileImage) setProfileImageUrl(defaultProfileImage);
};

return { profileImageUrl, onClickSetDefaultProfileImage };
};

export default useDefaultProfileImage;
6 changes: 3 additions & 3 deletions src/pages/SignUp/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ export type DetailSkills = Record<number, DetailSkillOption[]>;
export interface PostSignUp {
nickname: string;
mainSkillId: number;
profileImageUrl: string;
profileImageUrl: string | null;
skills: {
skillId: number;
level: string;
}[];
joinPurposes: number[];
livingPlaceId: number;
workingPlace?: string;
introduction?: string;
workingPlace: string | null;
introduction: string | null;
email: string;
oauthId: string;
oauthServerType: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ const Profile = ({ onClickProfile }: Props) => {
<ProfileWrapper>
<ProfileBox onClick={handleClickProfile}>
<Box width={36} height={36} overflow="hidden" borderRadius="0 150px 150px 0">
<ImageView src={profileImageUrl} alt="프로필" defaultSrc={PNGDefaultProfileInfo36} />
<ImageView
src={profileImageUrl || PNGDefaultProfileInfo36}
alt="프로필"
defaultSrc={PNGDefaultProfileInfo36}
/>
</Box>

<Box paddingTop={2}>
Expand Down

0 comments on commit 9d5bd71

Please sign in to comment.