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

Devyouth94 김영진 #5

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ module.exports = {
webpack: {
alias: {
"@": path.resolve(__dirname, "src"),
"@contexts": path.resolve(__dirname, "src/contexts"),
"@apis": path.resolve(__dirname, "src/apis"),
"@components": path.resolve(__dirname, "src/components"),
"@hooks": path.resolve(__dirname, "src/hooks"),
"@pages": path.resolve(__dirname, "src/pages"),
"@routes": path.resolve(__dirname, "src/routes"),
"@utils": path.resolve(__dirname, "src/utils"),
"@icons": path.resolve(__dirname, "src/icons"),
"@styles": path.resolve(__dirname, "src/styles"),
},
},
};
55 changes: 55 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"axios": "^1.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet-async": "^1.3.0",
"react-router-dom": "^6.4.2",
"react-scripts": "5.0.1",
"styled-components": "^5.3.6",
Expand Down
16 changes: 15 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import Router from "@routes/Router";
import { CarListContextProvider } from "@contexts/CarListContext";
import { BrowserRouter } from "../node_modules/react-router-dom/dist/index";
import { theme } from "@styles/theme";
import { ThemeProvider } from "styled-components";

function App() {
return <h1>Hello React!</h1>;
return (
<CarListContextProvider>
<ThemeProvider theme={theme}>
<BrowserRouter>
<Router />
</BrowserRouter>
</ThemeProvider>
</CarListContextProvider>
);
}

export default App;
7 changes: 7 additions & 0 deletions src/apis/instance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import axios from "../../node_modules/axios/index";

const instance = axios.create({
baseURL: process.env.REACT_APP_API_URL,
});

export default instance;
134 changes: 134 additions & 0 deletions src/components/CarItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import React from "react";

import { convertDate } from "@utils/date";
import { fuelEnum, segmentEnum } from "@utils/enum";

import { GSInfoText } from "@styles/styled";
import styled from "styled-components";

const CarItem = ({ carItem }) => {
const { car, isLoading, isError } = carItem;

return (
<>
{isLoading && <GSInfoText>불러오는중</GSInfoText>}
{isError && <GSInfoText>에러가 발생했습니다</GSInfoText>}
{car && (
<>
<SCarImage>
<img src={car.attribute.imageUrl} alt="carItem" />
</SCarImage>

<SCarInfo>
<span>{car.attribute.brand}</span>
<span>{car.attribute.name}</span>
<span>월 {car.amount.toLocaleString("ko-KR")}원</span>
</SCarInfo>

<SSubTitle>차량정보</SSubTitle>
<SContent>
<span>차종</span>
<span>{segmentEnum[car.attribute.segment]}</span>
</SContent>
<SContent>
<span>연료</span>
<span>{fuelEnum[car.attribute.fuelType]}</span>
</SContent>
<SContent>
<span>이용 가능일</span>
<span>{convertDate(car.startDate)}</span>
</SContent>

{car.insurance.length !== 0 && (
<>
<SSubTitle>보험</SSubTitle>
{car.insurance.map((item) => (
<SContent key={item.name}>
<span>{item.name}</span>
<span>{item.description}</span>
</SContent>
))}
</>
)}

{car.additionalProducts.length !== 0 && (
<>
<SSubTitle>추가상품</SSubTitle>
{car.additionalProducts.map((item) => (
<SContent key={item.name}>
<span>{item.name}</span>
<span>월 {item.amount.toLocaleString("ko-KR")}원</span>
</SContent>
))}
</>
)}
</>
)}
</>
);
};

const SCarImage = styled.div`
display: flex;
justify-content: center;
align-items: center;

height: 205px;

img {
width: 100%;
}
`;

const SCarInfo = styled.div`
display: flex;
flex-direction: column;
padding: 0 20px;

> span:nth-child(1) {
font-size: 20px;
font-weight: 700;
}

> span:nth-child(2) {
font-size: 24px;
font-weight: 700;
}

> span:nth-child(3) {
height: 48px;
margin-top: 21px;
text-align: end;
}
`;

const SSubTitle = styled.div`
display: flex;
align-items: center;

width: 100%;
height: 48px;
padding: 0 20px;
background-color: ${({ theme }) => theme.color.blue};

font-size: 17px;
font-weight: 700;
color: ${({ theme }) => theme.color.white};
`;

const SContent = styled.div`
display: flex;
justify-content: space-between;
align-items: center;

height: 48px;
padding: 0 20px;

font-size: 17px;

> span:nth-child(1) {
font-weight: 700;
}
`;

export default CarItem;
92 changes: 92 additions & 0 deletions src/components/CarList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React from "react";
import { useNavigate } from "../../node_modules/react-router-dom/dist/index";
import { fuelEnum, segmentEnum } from "@/utils/enum";
import { GSInfoText } from "@styles/styled";
import styled from "styled-components";

const CarList = ({ carList }) => {
const navigate = useNavigate();
const { cars, isLoading, isError } = carList;

const handleClickCarItem = (id) => {
navigate(`/detail/${id}`);
};

return (
<SCarListContainer>
{isLoading && <GSInfoText>불러오는중</GSInfoText>}
{isError && <GSInfoText>에러가 발생했습니다</GSInfoText>}
{cars?.length === 0 && <GSInfoText>차량이 없습니다.</GSInfoText>}

{cars?.map((car) => (
<SCarItem key={car.id} onClick={() => handleClickCarItem(car.id)}>
<div>
<SCarName>
<span>{car.attribute.brand}</span>
<span>{car.attribute.name}</span>
</SCarName>
<SCarInfo>
<span>
{segmentEnum[car.attribute.segment]} / {fuelEnum[car.attribute.fuelType]}
</span>
<span>월 {car.amount.toLocaleString("ko-KR")}원 부터</span>
</SCarInfo>
</div>

<div>
<img src={car.attribute.imageUrl} alt={car.attribute.name} />
</div>
</SCarItem>
))}
</SCarListContainer>
);
};

const SCarListContainer = styled.main`
display: flex;
flex-direction: column;
`;

const SCarItem = styled.div`
display: flex;
justify-content: space-between;

height: 120px;
padding: 20px;
border-bottom: 1px solid ${({ theme }) => theme.color.black};

cursor: pointer;

> div:nth-child(1) {
display: flex;
flex-direction: column;
justify-content: space-between;
}

> div:nth-child(2) {
width: 152px;

img {
width: 100%;
}
}
`;

const SCarName = styled.div`
display: flex;
flex-direction: column;

font-size: 14px;
font-weight: 700;
line-height: 17px;
`;

const SCarInfo = styled.div`
display: flex;
flex-direction: column;

font-size: 12px;
line-height: 15px;
`;

export default CarList;
Loading