Skip to content

Commit

Permalink
[Feature] - 프로필 이미지 수정 기능 및 여행기 등록 시 여행 장소마다 국가 코드 주도록 구현 (#535)
Browse files Browse the repository at this point in the history
* refactor(Drawer): 기존 헤드와 높이 달라 선 위치가 다른 문제 개선

* feat: 장소 필터링을 위하여 장소 등록시 countryCode를 보내도록 기능 구현

* refactor(AvatarCircle): props $네이밍 수정

* refactor(MyTravelogue):$ 제거에 따른 수정

* refactor(usePostUploadImages): resize 와 convert 처리 내부에서 하도록 수정

* refactor(MainPage): div semantic 태그인 button으로 수정

* feat(ProfileImageEditModalBottomSheet): 기능 구현

* feat(usePutProfile): api 명세 변경에 따라 patch를 put으로, imageUrl body 값에 부여

* refactor(AvatarCircle): props 유연하게 수정

* feat(useMyPage): 훅 구현

* feat(MyPage): 프로필 이미지 수정 기능 구현

* refactor(MyPage): 기능 단위로 pr 분리하기 위한 수정

* refactor(SearchPage): 기능 단위로 pr 분리하기 위한 수정

* refactor(useMyPage): useToggle 사용하도록 수정

* refactor(common): 반복되는 타입PlaceInfo 타입으로 선언 및 수정

* refactor(constants): 상수들 파일로 분리

* refactor(useMyPage): 책임에 따라 각각 커스텀 훅으로 분리

* refactor(constants): 상수 파일로 분리

* refactor(usePostUploadImages): max width, height 값 받을 수 있도록 수정

* refactor(usePostUploadImages): max width, height 값 받을 수 있도록 수정

* refactor(useProfileInitialization): 의존성 배열 추가

* refactor: useCallback으로 update 함수 감싸주도록 수정
  • Loading branch information
simorimi authored Oct 21, 2024
1 parent 267a0ff commit b1371a0
Show file tree
Hide file tree
Showing 32 changed files with 607 additions and 239 deletions.
7 changes: 5 additions & 2 deletions frontend/__tests__/travelPlanRegisterPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const REGISTER_TRAVEL_PLAN = {
lng: 126.977,
},
description: "조선 시대에 지어진 다섯 개의 궁궐 중 가장 큰 궁궐입니다.",
countryCode: "kr",
},
],
},
Expand Down Expand Up @@ -113,13 +114,14 @@ describe("여행 계획 등록 페이지 테스트", () => {
test("사용자는 1일차에 '경복궁'이라는 장소를 추가할 수 있다.", () => {
// given
const { result } = renderHook(() => useTravelPlanDays([]));
const newPlace: Pick<TravelPlanPlace, "placeName" | "position" | "todos"> = {
const newPlace: Pick<TravelPlanPlace, "placeName" | "position" | "todos" | "countryCode"> = {
placeName: "경복궁",
position: {
lat: 37.5796,
lng: 126.977,
},
todos: [],
countryCode: "kr",
};

// when
Expand All @@ -139,13 +141,14 @@ describe("여행 계획 등록 페이지 테스트", () => {
test("사용자는 추가한 경복궁을 삭제할 수 있다.", () => {
// given
const { result } = renderHook(() => useTravelPlanDays([]));
const newPlace: Pick<TravelPlanPlace, "placeName" | "position" | "todos"> = {
const newPlace: Pick<TravelPlanPlace, "placeName" | "position" | "todos" | "countryCode"> = {
placeName: "경복궁",
position: {
lat: 37.5796,
lng: 126.977,
},
todos: [],
countryCode: "kr",
};

// when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const meta = {
title: "Components/AvatarCircle",
component: AvatarCircle,
argTypes: {
$size: {
size: {
control: {
type: "select",
options: ["small", "medium", "large"],
Expand All @@ -31,42 +31,42 @@ type Story = StoryObj<typeof meta>;

export const Small: Story = {
args: {
$size: "small",
size: "small",
profileImageUrl: "https://i.pinimg.com/564x/c0/d6/5e/c0d65ef2ff5b3e752b70fe54d94d6206.jpg",
},
};

export const Medium: Story = {
args: {
$size: "medium",
size: "medium",
profileImageUrl: "https://i.pinimg.com/564x/c0/d6/5e/c0d65ef2ff5b3e752b70fe54d94d6206.jpg",
},
};

export const Large: Story = {
args: {
$size: "large",
size: "large",
profileImageUrl: "https://i.pinimg.com/564x/4c/a5/a1/4ca5a1de62690b5615925ce3def4636d.jpg",
},
};

export const WithDefaultAvatar: Story = {
args: {
$size: "small",
size: "small",
profileImageUrl: "https://invalid-image-url.jpg",
},
};

export const MediumWithDefaultAvatar: Story = {
args: {
$size: "medium",
size: "medium",
profileImageUrl: "https://invalid-image-url.jpg",
},
};

export const LargeWithDefaultAvatar: Story = {
args: {
$size: "large",
size: "large",
profileImageUrl: "https://invalid-image-url.jpg",
},
};
13 changes: 6 additions & 7 deletions frontend/src/components/common/AvatarCircle/AvatarCircle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ import useImageError from "@hooks/useImageError";
import * as S from "./AvatarCircle.styled";
import type { AvatarCircleSize } from "./AvatarCircle.type";

interface AvatarCircleProps {
$size?: AvatarCircleSize;
interface AvatarCircleProps extends React.ImgHTMLAttributes<HTMLImageElement> {
size?: AvatarCircleSize;
profileImageUrl?: string;
imageAlt?: string;
}

const AvatarCircle = ({ $size = "small", profileImageUrl, imageAlt }: AvatarCircleProps) => {
const AvatarCircle = ({ size = "small", profileImageUrl, ...props }: AvatarCircleProps) => {
const { imageError, handleImageError } = useImageError({ imageUrl: profileImageUrl });

return (
<S.AvatarCircleContainer $size={$size}>
<S.AvatarCircleContainer $size={size}>
{!imageError ? (
<img src={profileImageUrl} alt={imageAlt} onError={handleImageError} />
<img src={profileImageUrl} onError={handleImageError} {...props} />
) : (
<S.FallbackIcon $size={$size}>
<S.FallbackIcon $size={size}>
<svg
width="11"
height="11"
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/common/Drawer/Drawer.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ export const Overlay = styled.div<{ isOpen: boolean }>`
export const DrawerHeader = styled.div`
display: flex;
align-items: center;
height: calc(5.6rem + 1px);
padding: 1rem;
height: 6rem;
padding: ${({ theme }) => theme.spacing.m};
border-bottom: 1px solid #e0e0e0;
`;

export const DrawerContent = styled.div`
flex: 1;
overflow-y: auto;
padding: 1rem;
padding: ${({ theme }) => theme.spacing.m};
`;

export const TriggerButton = styled.button`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Global, css } from "@emotion/react";

import { Autocomplete } from "@react-google-maps/api";

import type { TravelTransformPlace } from "@type/domain/travelTransform";
import { PlaceInfo } from "@type/domain/common";

import { Button } from "@components/common";

Expand All @@ -14,7 +14,7 @@ import * as S from "./GoogleSearchPopup.styled";

interface GoogleSearchPopupProps {
onClosePopup: () => void;
onSearchPlaceInfo: (placeInfo: Pick<TravelTransformPlace, "placeName" | "position">) => void;
onSearchPlaceInfo: (placeInfo: PlaceInfo) => void;
}

const GoogleSearchPopup = ({ onClosePopup, onSearchPlaceInfo }: GoogleSearchPopupProps) => {
Expand All @@ -31,15 +31,21 @@ const GoogleSearchPopup = ({ onClosePopup, onSearchPlaceInfo }: GoogleSearchPopu
const onPlaceChanged = useCallback(() => {
if (autocomplete !== null) {
const place = autocomplete.getPlace();
if (place.geometry && place.geometry.location) {

if (place.geometry && place.geometry.location && place.address_components) {
const newCenter = {
lat: place.geometry.location.lat(),
lng: place.geometry.location.lng(),
};

const placeInfo: Pick<TravelTransformPlace, "placeName" | "position"> = {
const countryCode = place.address_components.find((component) =>
component.types.includes("country"),
)?.short_name;

const placeInfo: PlaceInfo = {
placeName: place.name || "",
position: newCenter,
countryCode: countryCode || "",
};

onSearchPlaceInfo(placeInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ const SearchHeader = () => {
)
}
autoFocus
maxLength={20}
placeholder="제목 또는 작성자명으로 검색해 주세요."
maxLength={FORM_VALIDATIONS_MAP.title.maxLength}
placeholder="여행기 검색"
css={css`
height: 4rem;
padding-right: 7.8rem;
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/components/pages/main/MainPage.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,11 @@ export const MainPageTraveloguesList = styled.ul`
gap: ${({ theme }) => theme.spacing.m};
`;

export const OptionContainer = styled.div`
export const OptionContainer = styled.button`
display: flex;
justify-content: space-between;
width: 100%;
cursor: pointer;
`;

export const LastElement = styled.div`
Expand Down
88 changes: 61 additions & 27 deletions frontend/src/components/pages/my/MyPage.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,111 @@ import { css } from "@emotion/react";
import styled from "@emotion/styled";

import theme from "@styles/theme";
import { PRIMITIVE_COLORS } from "@styles/tokens";

export const Layout = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
gap: ${(props) => props.theme.spacing.xl};
width: 100%;
padding: ${(props) => props.theme.spacing.l};
`;

export const TabContentContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
gap: ${(props) => props.theme.spacing.m};
`;
export const ColorButtonStyle = css`
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
height: 6.8rem;
padding: ${theme.spacing.m};
border-radius: 10px;
background-color: ${PRIMITIVE_COLORS.blue[50]};
gap: ${theme.spacing.m};
`;

export const ListStyle = css`
export const listStyle = css`
li {
${theme.typography.mobile.body};
font-weight: 700;
${theme.typography.mobile.bodyBold};
}
`;

export const FormWrapper = styled.form`
export const ProfileContainer = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
gap: ${({ theme }) => theme.spacing.m};
width: 100%;
`;

export const ButtonWrapper = styled.div`
export const ProfileEditButtonContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing.xs};
`;

export const EditButtonContainer = styled.div`
display: flex;
justify-content: flex-end;
width: 100%;
`;

export const Button = styled.button`
export const EditButton = styled.button`
padding: ${({ theme }) => theme.spacing.s} ${({ theme }) => theme.spacing.m};
border: solid 1px ${({ theme }) => theme.colors.border};
${({ theme }) => theme.typography.mobile.detail};
border-radius: 10px;
`;

export const NicknameWrapper = styled.div`
export const ProfileImageContainer = styled.div`
display: flex;
position: relative;
`;

export const ProfileImageWrapper = styled.div<{ $isProfileImageLoading: boolean }>`
display: ${({ $isProfileImageLoading }) => ($isProfileImageLoading ? "none" : "block")};
`;

export const ProfileImageLoadingWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 12.9rem;
height: 12.9rem;
`;

export const ProfileImageHiddenInput = styled.input`
display: none;
`;

export const NicknameWrapper = styled.div`
display: flex;
justify-content: center;
align-items: flex-start;
width: 100%;
height: 3rem;
height: 6.5rem;
`;

export const InputContainer = styled.div`
export const NickNameEditContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${({ theme }) => theme.spacing.s};
width: 100%;
height: 6.5rem;
`;

export const Button = styled.button`
width: 100%;
`;

export const profileImageEditButtonStyle = css`
justify-content: flex-end;
align-items: flex-end;
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
`;

export const inputStyle = css`
Expand Down Expand Up @@ -103,8 +135,10 @@ export const inputStyle = css`
}
`;

export const NicknameStyle = css`
margin-bottom: calc(1.2rem + 2px);
export const nicknameStyle = css`
padding: 1.2rem 1.6rem;
`;

font-weight: 700;
export const deleteTextColor = css`
color: ${theme.colors.text.required};
`;
Loading

0 comments on commit b1371a0

Please sign in to comment.