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

Hemudi 김수민 #6

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
4 changes: 4 additions & 0 deletions craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ module.exports = {
"@pages": path.resolve(__dirname, "src/pages"),
"@routes": path.resolve(__dirname, "src/routes"),
"@utils": path.resolve(__dirname, "src/utils"),
"@layouts": path.resolve(__dirname, "src/layouts"),
"@assets": path.resolve(__dirname, "src/assets"),
"@styles": path.resolve(__dirname, "src/styles"),
"@contexts": path.resolve(__dirname, "src/contexts"),
},
},
};
5 changes: 0 additions & 5 deletions src/App.js

This file was deleted.

18 changes: 18 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ThemeProvider } from "styled-components";
import GlobalStyle from "@styles/GlobalStyle";
import * as CommonStyle from "@styles/common";
import Router from "@/routes/index";
import ContextProvider from "@contexts";

function App() {
return (
<ThemeProvider theme={CommonStyle}>
<GlobalStyle />
<ContextProvider>
<Router />
</ContextProvider>
</ThemeProvider>
);
}

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

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

export const getCarList = async (params) => {
const response = await instance.get("/cars", { params });
return response;
};
4 changes: 4 additions & 0 deletions src/assets/icons/back.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/assets/icons/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ReactComponent as Back } from "@assets/icons/back.svg";

const icon = {
back: Back,
};

export default icon;
39 changes: 39 additions & 0 deletions src/components/CarDetailList/List.styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import styled from "styled-components";

const List = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;

const ListHeader = styled.div`
display: flex;
height: 45px;
align-items: center;
color: ${({ theme }) => theme.COLORS.WHITE};
background-color: ${({ theme }) => theme.COLORS.BLUE};
font-size: ${({ theme }) => theme.FONT.SIZE.LARGE};
font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD};
padding-left: 20px;
`;

const ListItem = styled.li`
display: flex;
justify-content: space-between;
align-items: center;
height: 48px;
padding: 0 20px;
`;

const Name = styled.span`
font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD};
font-size: ${({ theme }) => theme.FONT.SIZE.LARGE};
color: ${({ theme }) => theme.COLORS.BLACK};
`;

const Contents = styled.span`
font-size: ${({ theme }) => theme.FONT.SIZE.LARGE};
color: ${({ theme }) => theme.COLORS.BLACK};
`;

export { List, ListHeader, ListItem, Name, Contents };
19 changes: 19 additions & 0 deletions src/components/CarDetailList/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as S from "@components/CarDetailList/List.styled";

const CarDetailList = ({ title, contents }) => {
return (
<S.List>
<S.ListHeader>{title}</S.ListHeader>
<ul>
{contents.map(({ name, contents }, index) => (
<S.ListItem key={index}>
<S.Name>{name}</S.Name>
<S.Contents>{contents}</S.Contents>
</S.ListItem>
))}
</ul>
</S.List>
);
};

export default CarDetailList;
41 changes: 41 additions & 0 deletions src/components/CarItem/CarItem.styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import styled from "styled-components";
import Tag from "@components/Tag";

const CarItem = styled.li`
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row;
width: 390px;
height: 120px;
padding: 0 20px;
border-bottom: 1px solid ${({ theme }) => theme.COLORS.BLACK};
cursor: pointer;
`;

const CarInfo = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
`;

const Title = styled.div`
display: flex;
flex-direction: column;
font-size: ${({ theme }) => theme.FONT.SIZE.BASE};
font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD};
`;

const Contents = styled.div`
display: flex;
flex-direction: column;
font-size: ${({ theme }) => theme.FONT.SIZE.SMALL};
`;

const Badge = styled(Tag)`
position: absolute;
z-index: 10;
`;

export { CarItem, CarInfo, Title, Contents, Badge };
40 changes: 40 additions & 0 deletions src/components/CarItem/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useNavigate } from "react-router-dom";

import ROUTE_PATH from "@/routes/routerPaths";
import Image from "@components/common/Image";
import * as S from "@components/CarItem/CarItem.styled";
import { useCarInfoContext } from "@contexts/carInfo";

const CarItem = ({ carInfo }) => {
const navigate = useNavigate();
const { setSelectedCarInfo } = useCarInfoContext();

const { id, amount, attribute } = carInfo;
const { brand, name, segment, imageUrl, fuelType } = attribute;

const handleClick = () => {
setSelectedCarInfo(carInfo);
navigate(`${ROUTE_PATH.DETAIL}/${id}`);
};

const isNew = false;

return (
<S.CarItem onClick={handleClick}>
<S.CarInfo>
<S.Title>
<span>{brand}</span>
<span>{name}</span>
</S.Title>
<S.Contents>
<span>{`${segment} / ${fuelType}`}</span>
<span>{`월 ${amount.toLocaleString()} 원 부터`}</span>
</S.Contents>
</S.CarInfo>
<Image url={imageUrl} />
{isNew && <S.Badge name="신규" size="small" />}
</S.CarItem>
);
};

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

const Category = styled.ul`
display: flex;
width: 100%;
height: 40px;
overflow-x: scroll;
gap: 8px;
border-bottom: 1px solid ${({ theme }) => theme.COLORS.BLACK};
`;

const CategoryItem = styled.li`
display: flex;
align-items: center;
justify-content: center;
`;

export { Category, CategoryItem };
23 changes: 23 additions & 0 deletions src/components/Category/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as S from "@components/Category/Category.styled";
import Tag from "@components/Tag";
import { useCategoryContext } from "@contexts/category";

const Category = ({ categories }) => {
const { selectedCategory, setSelectedCategory } = useCategoryContext();

const handleClick = ({ target }) => {
setSelectedCategory(target.id);
};

return (
<S.Category>
{categories.map(({ id, name }) => (
<S.CategoryItem key={id}>
<Tag id={id} name={name} isSelected={id === selectedCategory} onClick={handleClick} />
</S.CategoryItem>
))}
</S.Category>
);
};

export default Category;
36 changes: 36 additions & 0 deletions src/components/Tag/Tag.styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import styled, { css, ThemeConsumer } from "styled-components";

const ITEM_TAG_STYLE = css`
width: 52px;
height: 22px;
border-radius: 42px;
font-size: ${({ theme }) => theme.FONT.SIZE.SMALL};
color: ${({ theme }) => theme.COLORS.WHITE};
background-color: ${({ theme }) => theme.COLORS.BLUE};
`;

const DEFAULT_TAG_STYLE = css`
width: 62px;
height: 27px;
border-radius: 62px;
font-size: ${({ theme }) => theme.FONT.SIZE.BASE};
color: ${({ isSelected, theme }) => (isSelected ? theme.COLORS.WHITE : theme.COLORS.BLACK)};
background-color: ${({ isSelected, theme }) =>
isSelected ? theme.COLORS.BLACK : theme.COLORS.GREY};
`;

const TAG_STYLE = {
small: ITEM_TAG_STYLE,
default: DEFAULT_TAG_STYLE,
};

const Tag = styled.button`
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-weight: ${({ theme }) => theme.FONT.WEIGHT.BOLD};
${({ size = "default" }) => TAG_STYLE[size]}
`;

export { Tag };
11 changes: 11 additions & 0 deletions src/components/Tag/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as S from "@components/Tag/Tag.styled";

const Tag = ({ size = "default", id, name, isSelected, onClick }) => {
return (
<S.Tag id={id} size={size} isSelected={isSelected} onClick={onClick}>
{name}
</S.Tag>
);
};

export default Tag;
8 changes: 8 additions & 0 deletions src/components/common/Icon/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import icon from "@/assets/icons/index";

const Icon = ({ iconName }) => {
const IconComponent = icon[iconName];
return <IconComponent />;
};

export default Icon;
23 changes: 23 additions & 0 deletions src/components/common/Image/Image.styled.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import styled, { css } from "styled-components";

const BIG_IMAGE = css`
width: 390px;
height: 205px;
`;

const DEFAULT_IMAGE = css`
width: 152px;
height: 80px;
`;

const IMAGE_STYLE = {
default: DEFAULT_IMAGE,
big: BIG_IMAGE,
};

const Image = styled.img`
object-fit: cover;
${({ size = "default" }) => IMAGE_STYLE[size]}
`;

export { Image };
4 changes: 4 additions & 0 deletions src/components/common/Image/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as S from "@components/common/Image/Image.styled";
const Image = ({ url, size = "default" }) => <S.Image src={url} size={size} />;

export default Image;
12 changes: 12 additions & 0 deletions src/constants/carInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const SEGMENT = {
C: "소형",
D: "중형",
E: "대형",
SUV: "SUV",
};

export const FUEL_TYPE = {
gasoline: "가솔린",
ev: "전기",
hybrid: "하이브리드",
};
20 changes: 20 additions & 0 deletions src/contexts/carInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createContext, useContext, useState } from "react";

const CarInfoContext = createContext();
CarInfoContext.displayName = "CarInfoContext";

const useCarInfoContext = () => {
const context = useContext(CarInfoContext);
if (!context) {
throw new Error("useCarInfoContext should be used within CarInfoContext.Provider");
}
return context;
};

const CarInfoProvider = ({ children }) => {
const [selectedCarInfo, setSelectedCarInfo] = useState();
const value = { selectedCarInfo, setSelectedCarInfo };
return <CarInfoContext.Provider value={value}>{children}</CarInfoContext.Provider>;
};

export { useCarInfoContext, CarInfoProvider };
20 changes: 20 additions & 0 deletions src/contexts/category.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createContext, useContext, useState } from "react";

const CategoryContext = createContext();
CategoryContext.displayName = "CategoryContext";

const useCategoryContext = () => {
const context = useContext(CategoryContext);
if (!context) {
throw new Error("useCategoryContext should be used within CategoryContext.Provider");
}
return context;
};

const CategoryProvider = ({ children }) => {
const [selectedCategory, setSelectedCategory] = useState("all");
const value = { selectedCategory, setSelectedCategory };
return <CategoryContext.Provider value={value}>{children}</CategoryContext.Provider>;
};

export { useCategoryContext, CategoryProvider };
10 changes: 10 additions & 0 deletions src/contexts/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { CarInfoProvider } from "@contexts/carInfo";
import { CategoryProvider } from "@contexts/category";

const ContextProvider = ({ children }) => (
<CategoryProvider>
<CarInfoProvider>{children}</CarInfoProvider>
</CategoryProvider>
);

export default ContextProvider;
Loading