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

[Feature] - 데모데이 피드백 반영(리버) #444

Merged
merged 20 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2c7830b
feat(PlaceDetailCard): 여행기 사진 없을 경우 noImage이 아닌 아무것도 안나오도록 수정
0jenn0 Sep 20, 2024
b74deda
test(PlaceDetailCard): 이미지 없는 경우 테스트의 args 수정
0jenn0 Sep 20, 2024
7139021
feat(getDaysAndNights): 여행일자 텍스트 생성 util 함수 구현
0jenn0 Sep 22, 2024
45fbdb4
refactor(TravelogueDetailPage,TravelPlanDetailPage): 여행 일자 계산 util 함수 사용
0jenn0 Sep 22, 2024
767d056
feat(useInitialTripTitle): 여행기,여행계획 제목 초기값 생성 커스텀 훅 구현
0jenn0 Sep 22, 2024
d6eaf39
feat(TravelogueRegisterPage,useTravelPlanForm): 여행기,여행계획 변환시 제목 defau…
0jenn0 Sep 22, 2024
39d8f45
feat(usePreviousPage): 뒤로가기를 관리하는 훅 구현
0jenn0 Sep 22, 2024
cdda624
chore(useInitialTripTitle): Trip을 Travel로 수정
0jenn0 Sep 24, 2024
62d5aa7
feat(TravelogueRegisterPage): 제목 input에 placeholder 추가
0jenn0 Sep 24, 2024
62be1b9
fix(useInitialTravelTitle): 전환시에만 default title을 반환하도록 수정
0jenn0 Sep 24, 2024
a73e181
fix(interceptor): 리다이렉트 중이 아닐 때 alert,리다리렉트하도록 수정
0jenn0 Sep 25, 2024
58ac69d
feat(queryKey): search 쿼리키에 searchType 추가
0jenn0 Sep 25, 2024
6fafcd6
feat(useInfiniteSearchTravelogue): 여행기 검색 param에 searchType 추가
0jenn0 Sep 25, 2024
49e292d
style(Tab): 텍스트 세로 가운데 정렬 및 theme 사용 리팩토링
0jenn0 Sep 25, 2024
0010fd3
refactor(TravelogueList): 검색 결과 부분을 컴포넌트로 분리
0jenn0 Sep 25, 2024
c666cab
feat(SearchPage): 검색 타입 Tab 추가
0jenn0 Sep 25, 2024
eb6278c
feat(getInitialTravelTitle): 제목 초기값에서 사용자 닉네임 삭제
0jenn0 Sep 25, 2024
ef79495
refactor(usePreviousPage): type에서 interface로 수정
0jenn0 Sep 25, 2024
55dbc7f
refactor(usePreviousPage): 필요없는 state 삭제 및 그 전 페이지만 저장하도록 수정
0jenn0 Sep 25, 2024
59c9621
Merge branch 'develop/fe' into feature/fe/#422
0jenn0 Sep 26, 2024
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
6 changes: 4 additions & 2 deletions frontend/src/apis/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ import { HTTP_STATUS_CODE_MAP } from "@constants/httpStatusCode";
import { ROUTE_PATHS_MAP } from "@constants/route";
import { STORAGE_KEYS_MAP } from "@constants/storage";

let isRedirecting = false;

export const checkAccessToken = (
config: InternalAxiosRequestConfig,
accessToken: string | null,
) => {
if (!accessToken) {
if (!accessToken && !isRedirecting) {
isRedirecting = true;
alert(ERROR_MESSAGE_MAP.api.login);
window.location.href = ROUTE_PATHS_MAP.login;
}

return config;
};

Expand Down
8 changes: 3 additions & 5 deletions frontend/src/components/common/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useLocation, useNavigate } from "react-router-dom";

import usePreviousPage from "@hooks/usePreviousPage";
import useUser from "@hooks/useUser";

import { ROUTE_PATHS_MAP } from "@constants/route";
Expand Down Expand Up @@ -44,6 +45,7 @@ const Header = ({
};

const handleClickMyPage = () => navigate(ROUTE_PATHS_MAP.my);
const goBack = usePreviousPage();

return (
<Drawer>
Expand All @@ -52,11 +54,7 @@ const Header = ({
<IconButton
color={isLogoUsed ? theme.colors.primary : PRIMITIVE_COLORS.black}
iconType={isLogoUsed ? "korean-logo" : "back-icon"}
onClick={
isLogoUsed
? () => navigate(ROUTE_PATHS_MAP.root)
: () => navigate(ROUTE_PATHS_MAP.back)
}
onClick={isLogoUsed ? () => navigate(ROUTE_PATHS_MAP.root) : () => goBack()}
Copy link
Contributor

Choose a reason for hiding this comment

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

이전 페이지가 마이페이지고 현재 페이지가 로그인 페이지라면 goBack을 통해 뒤로가기 버튼을 눌러도 마이 페이지로 가는 것이 아닌 루트 페이지로 이동하는 방식이군여 좋습니다 ! !

/>
</S.LeftWrapper>

Expand Down
16 changes: 11 additions & 5 deletions frontend/src/components/common/Tab/Tab.styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ export const TabList = styled.ul`
`;

export const TabItem = styled.li<{ isSelected: boolean; $tabCount: number }>`
display: flex;
flex: 0 0 calc(100% / ${({ $tabCount }) => ($tabCount <= 3 ? $tabCount : 3.5)});
padding: 1rem 2rem;
border-bottom: 2px solid ${(props) => (props.isSelected ? "#0090ff" : "transparent")};
justify-content: center;
align-items: center;

padding: ${({ theme }) => theme.spacing.s} ${({ theme }) => theme.spacing.l};
border-bottom: 2px solid
${({ isSelected, theme }) => (isSelected ? `${theme.colors.primary}` : "transparent")};

color: ${(props) => (props.isSelected ? "#0090ff" : "#616161")};
font-weight: ${(props) => (props.isSelected ? "bold" : "normal")};
font-size: 12px;
color: ${({ isSelected, theme }) =>
isSelected ? `${theme.colors.primary}` : `${theme.colors.text.secondary}`};
${({ isSelected, theme }) =>
isSelected ? theme.typography.mobile.detailBold : theme.typography.mobile.detail};
text-align: center;
white-space: nowrap;
cursor: pointer;
Expand Down
22 changes: 8 additions & 14 deletions frontend/src/components/pages/search/SearchPage.styled.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { css } from "@emotion/react";
import styled from "@emotion/styled";

import { SPACING } from "@styles/tokens";
import { PRIMITIVE_COLORS, SPACING } from "@styles/tokens";

export const Layout = styled.div`
display: flex;
flex-direction: column;
gap: ${SPACING.m};

margin-top: ${SPACING.m};
min-height: calc(100vh - 6rem);
padding: ${SPACING.m};
padding-top: 0;
`;

export const SearchFallbackWrapper = styled.div`
flex: 1;
position: relative;
`;

export const MainPageTraveloguesList = styled.ul`
Expand All @@ -25,15 +23,11 @@ export const MainPageTraveloguesList = styled.ul`
gap: ${SPACING.m};
`;

export const searchResultTextStyle = css`
display: -webkit-box;
overflow: hidden;
width: 100%;
max-width: 100%;
export const TabStyle = css`
position: fixed;
z-index: 1000;
width: 45rem;
height: 5rem;

line-height: 1.5;
white-space: normal;
word-break: break-word;
overflow-wrap: break-word;
text-overflow: ellipsis;
background-color: ${PRIMITIVE_COLORS.white};
`;
82 changes: 11 additions & 71 deletions frontend/src/components/pages/search/SearchPage.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,18 @@
import { useLocation } from "react-router-dom";

import { css } from "@emotion/react";

import useInfiniteSearchTravelogues from "@queries/useInfiniteSearchTravelogues";

import { FloatingButton, SearchFallback, Text } from "@components/common";
import TravelogueCard from "@components/pages/main/TravelogueCard/TravelogueCard";

import useIntersectionObserver from "@hooks/useIntersectionObserver";

import { ERROR_MESSAGE_MAP } from "@constants/errorMessage";
import { FloatingButton, SearchFallback, Tab } from "@components/common";

import { extractLastPath } from "@utils/extractId";

import TravelogueCardSkeleton from "../main/TravelogueCard/skeleton/TravelogueCardSkeleton";
import * as S from "./SearchPage.styled";
import TravelogueList from "./TravelogueList/TravelogueList";

const SearchPage = () => {
const SKELETON_COUNT = 5;

const location = useLocation();
const encodedKeyword =
location.pathname.split("/").length > 2 ? extractLastPath(location.pathname) : "";
const keyword = encodedKeyword ? decodeURIComponent(encodedKeyword) : "";

const { travelogues, status, fetchNextPage, isPaused, error } =
useInfiniteSearchTravelogues(keyword);

const { lastElementRef } = useIntersectionObserver(fetchNextPage);

if (!keyword) {
return (
<S.Layout>
Expand All @@ -42,63 +26,19 @@ const SearchPage = () => {
);
}

if (travelogues.length === 0 && status === "success") {
return (
<S.Layout>
{keyword && (
<Text css={S.searchResultTextStyle} textType="title">{`"${keyword}" 검색 결과`}</Text>
)}
<S.SearchFallbackWrapper>
<SearchFallback title="휑" text="검색 결과가 없어요." />
</S.SearchFallbackWrapper>
</S.Layout>
);
}

if (status === "error") {
error && alert(error.message);

return <SearchFallback title="휑" text="검색 결과가 없어요." />;
}

if (isPaused) alert(ERROR_MESSAGE_MAP.network);

return (
<S.Layout>
<FloatingButton />
{keyword && (
<Text css={S.searchResultTextStyle} textType="title">{`"${keyword}" 검색 결과`}</Text>
)}
{status === "pending" && (
<S.MainPageTraveloguesList>
{Array.from({ length: SKELETON_COUNT }, (_, index) => (
<TravelogueCardSkeleton key={index} />
))}
</S.MainPageTraveloguesList>
)}
<S.MainPageTraveloguesList>
{travelogues.map(
({ id, title, thumbnail, authorProfileUrl, likeCount, tags, authorNickname }) => (
<TravelogueCard
key={id}
travelogueOverview={{
id,
title,
thumbnail,
authorProfileUrl,
likeCount,
tags,
authorNickname,
}}
/>
),
<Tab
labels={["제목", "작성자"]}
tabContent={(selectedIndex) => (
<TravelogueList
key={`${keyword}-${selectedIndex}`}
keyword={keyword}
searchType={selectedIndex === 0 ? "TITLE" : "AUTHOR"}
/>
)}
</S.MainPageTraveloguesList>
<div
ref={lastElementRef}
css={css`
height: 1px;
`}
css={S.TabStyle}
/>
</S.Layout>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { css } from "@emotion/react";
import styled from "@emotion/styled";

import { SPACING } from "@styles/tokens";

export const Layout = styled.div`
display: flex;
flex-direction: column;
margin-top: ${SPACING.xxxl};
min-height: calc(100vh - 16rem);
`;

export const searchResultTextStyle = css`
display: -webkit-box;
overflow: hidden;
width: 100%;
max-width: 100%;

line-height: 1.5;
white-space: normal;
word-break: break-word;
overflow-wrap: break-word;
text-overflow: ellipsis;
`;

export const SearchFallbackWrapper = styled.div`
flex: 1;
position: relative;
`;

export const MainPageTraveloguesList = styled.ul`
display: flex;
flex-direction: column;

gap: ${SPACING.m};
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { css } from "@emotion/react";

import type { SearchType } from "@type/domain/travelogue";

import useInfiniteSearchTravelogues from "@queries/useInfiniteSearchTravelogues";

import { SearchFallback, Text } from "@components/common";
import TravelogueCard from "@components/pages/main/TravelogueCard/TravelogueCard";
import TravelogueCardSkeleton from "@components/pages/main/TravelogueCard/skeleton/TravelogueCardSkeleton";

import useIntersectionObserver from "@hooks/useIntersectionObserver";

import { ERROR_MESSAGE_MAP } from "@constants/errorMessage";

import * as S from "./TravelogueList.styled";

const SKELETON_COUNT = 5;

interface TravelogueListProps {
keyword: string;
searchType: SearchType;
}

const TravelogueList = ({ keyword, searchType }: TravelogueListProps) => {
const { travelogues, status, fetchNextPage, isPaused, error } = useInfiniteSearchTravelogues(
keyword,
searchType,
);
const { lastElementRef } = useIntersectionObserver(fetchNextPage);

if (travelogues.length === 0 && status === "success") {
return (
<S.Layout>
{keyword && (
<Text css={S.searchResultTextStyle} textType="title">{`"${keyword}" 검색 결과`}</Text>
)}
<S.SearchFallbackWrapper>
<SearchFallback title="휑" text="검색 결과가 없어요." />
</S.SearchFallbackWrapper>
</S.Layout>
);
}

if (status === "error") {
error && alert(error.message);

return <SearchFallback title="휑" text="검색 결과가 없어요." />;
}

if (isPaused) alert(ERROR_MESSAGE_MAP.network);

return (
<S.Layout>
<S.MainPageTraveloguesList>
{keyword && (
<Text css={S.searchResultTextStyle} textType="title">{`"${keyword}" 검색 결과`}</Text>
)}

{status === "pending" && (
<S.MainPageTraveloguesList>
{Array.from({ length: SKELETON_COUNT }, (_, index) => (
<TravelogueCardSkeleton key={index} />
))}
</S.MainPageTraveloguesList>
)}
{travelogues.map(
({ id, title, thumbnail, authorProfileUrl, likeCount, tags, authorNickname }) => (
<TravelogueCard
key={id}
travelogueOverview={{
id,
title,
thumbnail,
authorProfileUrl,
likeCount,
tags,
authorNickname,
}}
/>
),
)}
<div
ref={lastElementRef}
css={css`
height: 1px;
`}
/>
</S.MainPageTraveloguesList>
</S.Layout>
);
};

export default TravelogueList;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ROUTE_PATHS_MAP } from "@constants/route";

import { extractLastPath } from "@utils/extractId";
import getDateRange from "@utils/getDateRange";
import getDaysAndNights from "@utils/getDaysAndNights";
import { isUUID } from "@utils/uuid";

import theme from "@styles/theme";
Expand All @@ -35,10 +36,7 @@ const TravelPlanDetailPage = () => {

const navigate = useNavigate();

const daysAndNights =
data?.days.length && data?.days.length > 1
? `${data?.days.length - 1}박 ${data?.days.length}일`
: "당일치기";
const daysAndNights = getDaysAndNights(data?.days);

Choose a reason for hiding this comment

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

util로 분리한 거 좋네요


const { mutate: mutateDeleteTravelPlan, isPending: isDeletingPending } = useDeleteTravelPlan();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { ERROR_MESSAGE_MAP } from "@constants/errorMessage";
import { ROUTE_PATHS_MAP } from "@constants/route";

import { extractID } from "@utils/extractId";
import getDaysAndNights from "@utils/getDaysAndNights";

import theme from "@styles/theme";
import { SEMANTIC_COLORS } from "@styles/tokens";
Expand All @@ -49,10 +50,7 @@ const TravelogueDetailPage = () => {

const navigate = useNavigate();

const daysAndNights =
data?.days.length && data?.days.length > 1
? `${data?.days.length - 1}박 ${data?.days.length}일`
: "당일치기";
const daysAndNights = getDaysAndNights(data?.days);
Copy link
Contributor

Choose a reason for hiding this comment

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

반복되는 로직 분리해주셔서 감사합니다 :)


const { onTransformTravelDetail } = useTravelTransformDetailContext();
const {
Expand Down
Loading
Loading