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

[#15] 차량 목록 리스트 컴포넌트 구현 #16

Merged
merged 5 commits into from
Nov 3, 2022
33 changes: 33 additions & 0 deletions src/components/feature/CarListItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as S from './styled';
import { Car } from '@src/types/car';
import Image from '../../shared/Image';
import { carAttributeTable } from '@src/constants/car';
import { isNewDate } from '@src/utils/DateUtils';
import { numberWithCommasConverter } from '@src/utils/StringUtils';

const CarListItem = ({ car }: { car: Car }) => {
return (
<S.Container>
<S.SLink to={`/detail/${car.id}`}>
<S.Information>
<S.Brand>
<span>{car.attribute.brand}</span>
<span>{car.attribute.name}</span>
</S.Brand>
<S.Segment>
<span>
{carAttributeTable.segmentTable[car.attribute.segment]} / {carAttributeTable.fuelTable[car.attribute.fuelType]}
</span>
<span>월 {numberWithCommasConverter(car.amount)} 원 부터</span>
</S.Segment>
</S.Information>
<S.Img>
<Image imgUrl={car.attribute.imageUrl} />
<p>{isNewDate(car.createdAt) && '신규'}</p>
</S.Img>
</S.SLink>
</S.Container>
);
};

export default CarListItem;
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import styled from 'styled-components';
import { Link } from 'react-router-dom';

export const Container = styled.section`
export const Container = styled.li`
list-style: none;
`;

export const SLink = styled(Link)`
display: flex;
width: 100%;
padding: 1.2rem;
border-bottom: 1px solid black;
justify-content: space-between;
height: 7.5rem;
text-decoration: none;
color: ${({ theme }) => theme.colors.black};
`;

Expand Down
30 changes: 0 additions & 30 deletions src/components/feature/VehicleItem/index.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export { default as Header } from '@src/components/layout/Header';
// Feature Components
export { default as DetailForm } from '@src/components/feature/DetailForm';
export { default as Nav } from '@src/components/feature/Nav';
export { default as VehicleItem } from '@src/components/feature/VehicleItem';
export { default as CarListItem } from '@src/components/feature/CarListItem';
17 changes: 17 additions & 0 deletions src/constants/car.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint no-unused-vars: 0 */
import { Fuel, Segment } from '@src/types/car';

const fuelTable: { [fuel in Fuel]: string } = {
gasoline: '가솔린',
hybrid: '하이브리드',
ev: '전기',
};

const segmentTable: { [segment in Segment]: string } = {
C: '소형',
D: '중형',
E: '대형',
SUV: 'SUV',
};

export const carAttributeTable = { fuelTable, segmentTable };
13 changes: 13 additions & 0 deletions src/hooks/useCars.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useQuery } from '@tanstack/react-query';
import { getCars } from '@src/apis/car';
import { Car } from '@src/types/car';

const useCars = (queyString: string = '') => {
const { data: cars, isLoading, isError } = useQuery<Car[]>(['getCars', queyString], () => getCars(queyString));

const isEmptyCars = (cars: Car[] | undefined) => !cars || cars.length === 0;

return { cars, isLoading, isError, isEmtpy: isEmptyCars(cars) };
};

export default useCars;
9 changes: 9 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ const queryClient = new QueryClient({
},
});

const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 1,
useErrorBoundary: true,
},
},
});

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<BrowserRouter>
Expand Down
13 changes: 7 additions & 6 deletions src/pages/CarList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import * as S from './styled';
import Nav from '../../components/feature/Nav';
import VehicleItem from '../../components/feature/VehicleItem';
import { segmentDummyData, fuelTypeDummyData } from '@src/constants/attributeDummyData';
import { useRecoilState } from 'recoil';
import { SegmentAtom, fuelTypeAtom } from '../../recoil/atoms/ChipAtom';
import { CarListItem } from '@src/components';
import useCars from '@src/hooks/useCars';

const CarList = () => {
const [segmentInfo, setSegmentInfo] = useRecoilState(SegmentAtom);
const [fuelTypeInfo, setFuelTypeInfo] = useRecoilState(fuelTypeAtom);
const { cars, isLoading, isEmtpy } = useCars();

return (
<S.Container>
<Nav dummy={segmentDummyData} perview={4.4} state={segmentInfo} setState={setSegmentInfo} />
<Nav dummy={fuelTypeDummyData} perview={4} state={fuelTypeInfo} setState={setFuelTypeInfo} />
<VehicleItem />
{false && <S.Message>차량이 없습니다.</S.Message>}
{true && <S.Message>불러오는 중</S.Message>}
{isLoading && <S.Message>불러오는 중</S.Message>}
{isEmtpy ? <S.Message>차량이 없습니다.</S.Message> : cars?.map((car) => <CarListItem key={car.id} car={car} />)}
</S.Container>
);
};
Expand Down
2 changes: 2 additions & 0 deletions src/pages/CarList/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export const Container = styled.section`
height: 27px;
border-radius: 62px;
}

.active {
background-color: ${({ theme }) => theme.colors.black};
color: ${({ theme }) => theme.colors.white};
}

.new {
background-color: ${({ theme }) => theme.colors.primary};
color: ${({ theme }) => theme.colors.white};
Expand Down
2 changes: 1 addition & 1 deletion src/router/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Route, Routes } from 'react-router-dom';
import { checkArray } from '../utils/checkArray';
import { checkArray } from '../utils/ArrayUtils';
import ROUTE_PATH from './routePath';
import { CarList, CarDetail } from '../pages';

Expand Down
5 changes: 5 additions & 0 deletions src/styles/GlobalStyle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ const GlobalStyle = styled.createGlobalStyle`
body {
font-size: 16px;
}

ul,
li {
list-style: none;
}
`;

export default GlobalStyle;
6 changes: 3 additions & 3 deletions src/styles/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { DefaultTheme } from 'styled-components';
const pixelToRem = (size: number) => `${size / 16}rem`;

export const size = {
mobile: 360,
desktop: 450,
mobile: 450,
desktop: 1280,
};

const theme: DefaultTheme = {
Expand All @@ -28,7 +28,7 @@ const theme: DefaultTheme = {
primary: '#0094ff',
},
device: {
mobile: `screen and (max-width: ${size.mobile}px)`,
mobile: `screen and (min-width: ${size.mobile}px)`,
},
};

Expand Down
2 changes: 1 addition & 1 deletion src/types/car.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type Fuel = 'gasoline' | 'hybrid' | 'ev' | 'hybrid';
export type Fuel = 'gasoline' | 'hybrid' | 'ev';
export type Segment = 'C' | 'D' | 'E' | 'SUV';

export type Insurance = {
Expand Down
File renamed without changes.
5 changes: 5 additions & 0 deletions src/utils/DateUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const MILLISECOND_TO_HOUR = 1000 * 60 * 60 * 24;
const DAY1 = 1;

export const isNewDate = (createdDateString: string) =>
(new Date().getTime() - new Date(createdDateString).getTime()) / MILLISECOND_TO_HOUR <= DAY1;
1 change: 1 addition & 0 deletions src/utils/StringUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const numberWithCommasConverter = (n: number) => n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');