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

feat: 지역 검색 기능을 구현한다 #837

Merged
merged 37 commits into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
689744e
refactor: StationSearchBar의 스타일 파일 분리
gabrielyoon7 Oct 6, 2023
3e5753c
refactor: fetchSearchedStations 스펙 변경
gabrielyoon7 Oct 6, 2023
e16d299
refactor: fetchSearchedStations 스펙 변경
gabrielyoon7 Oct 6, 2023
9c15435
refactor: SearchResult 스타일 분리
gabrielyoon7 Oct 6, 2023
a89de50
feat: regions을 검색 결과에 포함할 수 있는 프롭 전달
gabrielyoon7 Oct 6, 2023
400bdd0
refactor: SearchedStationCard 분리
gabrielyoon7 Oct 6, 2023
77b28bb
refactor: NoResult 분리
gabrielyoon7 Oct 6, 2023
f418431
refactor: SearchedRegionCard 구현
gabrielyoon7 Oct 6, 2023
c5a1d60
feat: SearchedRegionCard 디자인 추가
gabrielyoon7 Oct 6, 2023
047ab4f
refactor: SearchedRegionCard 디자인 개선
gabrielyoon7 Oct 6, 2023
fb384bf
rename: region ==> city
gabrielyoon7 Oct 6, 2023
c686118
rename: region ==> city
gabrielyoon7 Oct 6, 2023
bc3aabc
feat: /stations/search 에 도시 검색 결과 포함
gabrielyoon7 Oct 6, 2023
5869797
feat: 도시 검색 결과 연동
gabrielyoon7 Oct 6, 2023
d53670e
feat: 도시 검색 결과 클릭 시 해당 지역으로 이동하는 기능 구현
gabrielyoon7 Oct 6, 2023
8c04c6d
refactor: fragment 추가
gabrielyoon7 Oct 6, 2023
2a06e62
feat: 검색바 디자인 개선
feb-dain Oct 6, 2023
aea43ea
fix: msw에서 충전소 검색 시 주소가 고려되지 않는 문제 수정
gabrielyoon7 Oct 6, 2023
f8cae09
refactor: 도시 검색 시 이동하기 문구 삭제
gabrielyoon7 Oct 6, 2023
53889e8
refactor: SearchResult 구조 개선
gabrielyoon7 Oct 6, 2023
a10e3d8
fix: handleShowStationDetails 선언 순서 오류 수정
gabrielyoon7 Oct 6, 2023
2e5928c
fix: storybook 오류 수정
gabrielyoon7 Oct 6, 2023
4681d86
fix: storybook 오류 수정
gabrielyoon7 Oct 6, 2023
d374e96
Merge remote-tracking branch 'origin' into feat/834
gabrielyoon7 Oct 6, 2023
359cc78
Merge branch 'feat/834' of https://github.com/woowacourse-teams/2023-…
feb-dain Oct 7, 2023
0dbb3c3
design: 검색바 부분 돋보기랑 로더 가운데로 오게 개선
feb-dain Oct 7, 2023
3042c69
refactor: 필요없는 코드 제거
feb-dain Oct 7, 2023
5aeca43
refactor: 에러 컴포넌트 개선
feb-dain Oct 7, 2023
a8d348f
refactor: 필요없는 코드 제거
feb-dain Oct 7, 2023
ed40b7e
design: 검색 결과 부분 디자인 개선
feb-dain Oct 7, 2023
ed7888b
refactor: api에서 주소가 'null'인 경우도 대응
feb-dain Oct 7, 2023
9644097
fix: 검색 결과의 rowGap -> columnGap
gabrielyoon7 Oct 7, 2023
d698820
fix: 오류 방지 배열 추가
gabrielyoon7 Oct 7, 2023
03f0c08
fix: 검색 결과 텍스트가 너무 긴 경우를 대응
gabrielyoon7 Oct 7, 2023
16a175d
fix: 충전소 이름이 길어지면 아이콘 줄어드는 문제 개선
feb-dain Oct 7, 2023
225e175
fix: 주소가 1줄로만 보이게 개선 및 테스트 추가
feb-dain Oct 7, 2023
51efce6
refactor: 변수명 개선
feb-dain Oct 7, 2023
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
8 changes: 5 additions & 3 deletions frontend/src/components/common/Button/Button.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import styled, { css } from 'styled-components';

import type { ButtonProps } from '@common/Button/Button';
import { spacing } from '@common/styles/spacing';
import { addUnit } from '@common/utils/addUnit';

import { borderRadius, getSize, pillStyle } from '@style';
import { borderRadius, pillStyle } from '@style';

import type { BorderRadiusDirectionType } from '@type';

Expand All @@ -28,8 +29,9 @@ export type StyledButtonType = Omit<ButtonProps, 'noRadius'> & {
};

export const StyledButton = styled.button<StyledButtonType>`
width: ${({ width }) => getSize(width)};
height: ${({ height }) => getSize(height)};
${({ width }) => width !== undefined && `width: ${addUnit(width)}`};
${({ height }) => height !== undefined && `height: ${addUnit(height)}`};

padding: ${({ size }) => BUTTON_PADDING_SIZE[size] || 0};
background: ${({ background }) => background || '#fff'};
border: ${({ outlined }) => (outlined ? '0.15rem solid #000' : 'none')};
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/common/FlexBox/FlexBox.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CSSProp } from 'styled-components';

import { type HTMLAttributes, type ReactNode } from 'react';
import type { ReactNode, ComponentPropsWithoutRef, ElementType } from 'react';

import type { SpacingProps } from '@common/styles/spacing';

Expand All @@ -9,7 +9,7 @@ import type { AxisType, BorderRadiusDirectionType } from '@type/style';
import type { FLEX_BOX_ITEM_POSITION } from './FlexBox.style';
import { StyledFlexBox } from './FlexBox.style';

export interface FlexBoxProps extends HTMLAttributes<HTMLDivElement>, SpacingProps {
export interface FlexBoxProps extends ComponentPropsWithoutRef<ElementType>, SpacingProps {
tag?: string;
height?: number | string;
minHeight?: number | string;
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/components/ui/Error.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import Box from '@common/Box';
import ButtonNext from '@common/ButtonNext';
import FlexBox from '@common/FlexBox';
import type { FlexBoxProps } from '@common/FlexBox/FlexBox';
import Text from '@common/Text';

export interface ErrorProps {
export interface ErrorProps extends Partial<FlexBoxProps> {
fontSize?: number | string;
title: string;
message: string;
subMessage?: string;
handleRetry?: () => void;
minHeight?: string | number;
}

const Error = ({ title, message, subMessage, handleRetry, fontSize, minHeight }: ErrorProps) => {
const Error = ({ title, message, subMessage, handleRetry, fontSize, ...props }: ErrorProps) => {
return (
<FlexBox
width="100%"
height="100%"
justifyContent="center"
alignItems="center"
minHeight={minHeight}
{...props}
css={{
fontSize: typeof fontSize === 'string' ? fontSize : `${fontSize}rem`,
}}
>
<Box css={{ wordBreak: 'keep-all' }}>
<Text align="center" css={{ fontSize: '10em', fontWeight: 'bold' }} mb={7}>
<Text align="center" weight="bold" css={{ fontSize: '10em' }} mb={7}>
{title}
</Text>
<Text align="center" mb={2}>
<Text align="center" mb={1}>
{message}
</Text>
<Text align="center">{subMessage}</Text>
Expand All @@ -39,8 +39,10 @@ const Error = ({ title, message, subMessage, handleRetry, fontSize, minHeight }:
variant="outlined"
color="dark"
size="xs"
fullWidth
mt={6}
mb={8}
py={1}
>
다시 시도하기
</ButtonNext>
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/components/ui/StationSearchWindow/NoResult.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ListItem from '@common/ListItem';
import Text from '@common/Text';

const NoResult = () => {
return (
<ListItem>
<Text mt={3} fontSize={1.8} weight="bold">
검색 결과가 없습니다.
</Text>
<Text variant="subtitle" mt={1}>
검색어를 다시 한 번 확인해 주세요.
</Text>
<Text>·&nbsp; 오타는 없나요?</Text>
<Text mb={5}>·&nbsp; 띄어쓰기가 잘못되진 않았나요?</Text>
</ListItem>
);
};

export default NoResult;
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ const meta = {
tags: ['autodocs'],
component: SearchResult,
args: {
cities: [
{
cityName: '서울특별시 강동구 천호동',
latitude: 1,
longitude: 1,
},
{
cityName: '서울특별시 강동구 명일동',
latitude: 1,
longitude: 1,
},
{
cityName: '서울특별시 강동구 명일동 413-12번지 카페인 빌딩',
latitude: 1,
longitude: 1,
},
],
stations: [
{
stationId: '0',
Expand All @@ -26,6 +43,14 @@ const meta = {
latitude: 1,
longitude: 1,
},
{
stationId: '2',
stationName: '완전 엄청나게 이름이 긴 충전소를 테스트',
speed: 'standard',
address: '서울시 강남구 테헤란로 411 천호빌딩 지하 14층',
latitude: 1,
longitude: 1,
},
],
isLoading: false,
isError: false,
Expand Down Expand Up @@ -66,6 +91,7 @@ export const NoResult = () => {
return (
<SubContainer>
<SearchResult
cities={[]}
stations={[]}
closeResult={() => null}
isError={false}
Expand All @@ -80,6 +106,7 @@ export const Error = () => {
return (
<Container>
<SearchResult
cities={[]}
stations={[]}
closeResult={() => null}
isError={true}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { css } from 'styled-components';

import { MOBILE_BREAKPOINT } from '@constants';

export const searchResultListCss = css`
position: absolute;
z-index: 9999;
width: 29.6rem;
max-height: 46rem;
overflow: auto;
border: 1.5px solid #d9d9da;
border-radius: 10px;
background: #fcfcfc;
box-shadow: 0 3px 10px 0 #d9d9da;
font-size: 1.5rem;
line-height: 2;

@media screen and (max-width: ${MOBILE_BREAKPOINT}px) {
width: calc(100vw - 2rem);

max-height: 22.6rem;
}
`;

export const foundStationListCss = css`
display: flex;

&:hover {
background: #f5f5f5;
}
`;
126 changes: 42 additions & 84 deletions frontend/src/components/ui/StationSearchWindow/SearchResult.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import { css } from 'styled-components';

import { useEffect } from 'react';

import Button from '@common/Button';
import List from '@common/List';
import ListItem from '@common/ListItem';
import Text from '@common/Text';

import Error from '@ui/Error';

import { MOBILE_BREAKPOINT } from '@constants';
import type { SearchedCity, SearchedStation, StationPosition } from '@type/stations';

import type { SearchedStation, StationPosition } from '@type/stations';
import NoResult from './NoResult';
import { searchResultListCss } from './SearchResult.style';
import SearchedCityCard from './SearchedCityCard';
import SearchedStationCard from './SearchedStationCard';

export interface SearchResultProps {
cities: SearchedCity[];
stations: SearchedStation[];
isLoading: boolean;
isError: boolean;
showStationDetails: (param: StationPosition) => void;
closeResult: () => void;
}

const SearchResult = (props: SearchResultProps) => {
const { stations, isLoading, isError, showStationDetails, closeResult } = props;

const handleShowStationDetails = (handlerProps: StationPosition) => {
const { stationId, latitude, longitude } = handlerProps;

const SearchResult = ({
cities = [],
stations = [],
isLoading,
isError,
showStationDetails,
closeResult,
}: SearchResultProps) => {
const handleShowStationDetails = ({ stationId, latitude, longitude }: StationPosition) => {
showStationDetails({ stationId, latitude, longitude });
};

Expand All @@ -38,85 +40,41 @@ const SearchResult = (props: SearchResultProps) => {
};
}, []);

if (isLoading) return <></>;
const isExistResults = stations.length !== 0 || cities.length !== 0;
const renderResults = [
...cities.map((city) => <SearchedCityCard city={city} key={city.cityName} />),
...stations.map((station) => (
<SearchedStationCard
station={station}
handleShowStationDetails={handleShowStationDetails}
key={station.stationId}
/>
)),
];

if (isLoading) {
return <></>;
}

if (isError)
return (
<Error
title="문제가 발생했어요!"
message="예상하지 못한 오류로"
subMessage="검색 결과를 가져오지 못했습니다."
fontSize="40%"
/>
<List aria-live="assertive" mt={1} css={searchResultListCss}>
<Error
title="문제가 발생했어요!"
message="예상하지 못한 오류로"
subMessage="검색 결과를 가져오지 못했습니다."
fontSize="20%"
pt={6}
pb={3}
/>
</List>
);

return (
<List aria-live="assertive" mt={1} css={searchResultList}>
{stations.length ? (
stations.map(({ stationId, stationName, address, latitude, longitude }) => (
<ListItem divider NoLastDivider key={stationId} pt={2} pb={3} css={foundStationList}>
<Button
width="100%"
noRadius="all"
background="transparent"
onMouseDown={() => handleShowStationDetails({ stationId, latitude, longitude })}
>
<Text variant="h6" align="left" title={stationName} lineClamp={1}>
{stationName}
</Text>
<Text variant="label" align="left" lineClamp={1} color="#585858">
{address || '주소 미확인'}
</Text>
</Button>
</ListItem>
))
) : (
<>
<ListItem mt={3} css={noSearchResult} pb={0}>
검색 결과가 없습니다.
</ListItem>
<ListItem mt={1} mb={5}>
<Text variant="subtitle">검색어를 다시 한 번 확인해 주세요.</Text>
<Text tag="span" css={{ display: 'block' }}>
·&nbsp; 오타는 없나요?
</Text>
<Text tag="span">·&nbsp; 띄어쓰기가 잘못되진 않았나요?</Text>
</ListItem>
</>
)}
<List aria-live="assertive" mt={1} css={searchResultListCss}>
{isExistResults ? renderResults : <NoResult />}
</List>
);
};

export const searchResultList = css`
position: absolute;
z-index: 9999;
width: 29.6rem;
max-height: 46rem;
overflow: auto;
border: 1.5px solid #d9d9da;
border-radius: 10px;
background: #fcfcfc;
box-shadow: 0 3px 10px 0 #d9d9da;
font-size: 1.5rem;
line-height: 2;

@media screen and (max-width: ${MOBILE_BREAKPOINT}px) {
width: calc(100vw - 2rem);

max-height: 22.6rem;
}
`;

export const foundStationList = css`
&:hover {
background: #f5f5f5;
}
`;

export const noSearchResult = css`
font-size: 1.8rem;
font-weight: 600;
`;

export default SearchResult;
Loading
Loading