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

[1단계 미션] 배강현 미션 제출합니다 #24

Open
wants to merge 10 commits into
base: bae-kh
Choose a base branch
from
20,200 changes: 17,202 additions & 2,998 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"start": "react-scripts start",
"dev": "vite",
"build": "vite build",
"lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0",
Expand All @@ -12,7 +13,8 @@
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-scripts": "^5.0.1"
},
"devDependencies": {
"@types/react": "^18.2.66",
Expand Down
52 changes: 52 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

ul,
li {
list-style: none;
}

html,
body {
font-family: sans-serif;
font-size: 16px;
}

/* Colors *****************************************/
:root {
--primary-color: #ec4a0a;
--lighten-color: #f6a88a;
--grey-100: #ffffff;
--grey-200: #d0d5dd;
--grey-300: #667085;
--grey-400: #344054;
--grey-500: #000000;
}

/* Typography *************************************/
.text-title {
font-size: 20px;
line-height: 24px;
font-weight: 600;
}

.text-subtitle {
font-size: 18px;
line-height: 28px;
font-weight: 600;
}

.text-body {
font-size: 16px;
line-height: 24px;
font-weight: 400;
}

.text-caption {
font-size: 14px;
line-height: 20px;
font-weight: 400;
}
21 changes: 20 additions & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import "./App.css";
import Header from "./header/Header.jsx";
import CategoryFilter from "./mainbody/CategoryFilter.jsx";
import RestaurantList from "./mainbody/RestaurantList.jsx";
import RestaurantDetailModal from "./aside/RestaurantDetailModal.jsx";
import AddRestaurantModal from "./aside/AddRestaurantModal.jsx";
Comment on lines +2 to +6

Choose a reason for hiding this comment

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

다른 여러 컨벤션에서는 함수는 카멜 케이스를 사용하는 것이 관례라고 적혀 있을텐데, 여기에서 import하는 Header, CategoryFilter, ... 는 모두 파스칼 케이스에요. 비록 코드를 가져오는 작업에 가깝지만 의문이 혹시 들지는 않으셨나요?

Copy link
Author

Choose a reason for hiding this comment

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

아 약간 적혀있는데로 가져오는 바람에 거기까진 생각 못해봤네요.. 다음부턴 항상 의식하면서 짜야겠네요!

Copy link
Author

Choose a reason for hiding this comment

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

위에 import하는 것은 함수형 컴포넌트이므로 파스칼케이스로 작성하는게 맞는것같다고 생각합니다!



function App() {
return <h1>Self-Paced React</h1>;
return (
<>
<Header />
<main>
<CategoryFilter />
<RestaurantList />
</main>
<aside>
<RestaurantDetailModal />
<AddRestaurantModal />
</aside>
</>
);
}


export default App;
48 changes: 48 additions & 0 deletions src/aside/AddRestaurantModal.jsx

Choose a reason for hiding this comment

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

오, css module를 잘 활용해 주셨네요 😊 선택사항인데 수고 많으셨어요
그런데 css module을 혹시 사용하시고자 한 이유는 있으셨나요? 있으시다면 어떤 이유로 사용하셨는지, 그냥 css를 사용할 때랑 어떤 차이가 있는지 설명을 부탁드려도 괜찮을까요?

Copy link
Author

Choose a reason for hiding this comment

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

처음에 css module을 사용하게 된 이유는 선택사항에 있어서 그냥 무턱대고 해봤습니다.
나중에 궁금해서 찾아보니 클래스 충돌을 막는다는 장점이 있는다는 걸 알게되었습니다.
나중에 다른 사람들과 프로젝트를 할 때 만약 그냥 css를 사용한다면 잘못해서 클래스 이름이 겹쳤을 때 각자의 역할을 못하고 하나가 잡아먹을 수 있습니다. css module을 사용하게되면 충돌이 날 문제를 생각하지 않고 편하게 코딩할 수 있습니다.

Copy link

Choose a reason for hiding this comment

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

맞습니다. 컴포넌트가 어떤 단점들을 해결하기 위해 탄생했는지, 컴포넌트로 챙길 수 있는 장점들이 무엇인지를 고민해 보시면 더 와닿을 수 있을 거라고 생각합니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import styles from "../css/RestaurantDetailModal.module.css";
import { options } from "../datas/RestaurantData";

function AddRestaurantModal() {
return (
<div className={`${styles.modal} ${styles.modalOpen}`}>
<div className={styles.modalBackdrop}></div>
<div className={styles.modalContainer}>
<h2 className={`${styles.modalTitle} text-title`}>새로운 음식점</h2>
<form>
{/* <!-- 카테고리 --> */}
<div className={`${styles.formItem} ${styles.formItemRequired}`}>
<label htmlFor="category" className="text-caption">카테고리</label>
<select name="category" id="category" required>
{options.map((option, index) => (
<option key={index} value={option}>
{option}
</option>
))}
</select>
</div>

{/* <!-- 음식점 이름 --> */}
<div className={`${styles.formItem} ${styles.formItemRequired}`}>
<label htmlFor="name" className="text-caption">이름</label>
<input type="text" name="name" id="name" required />
</div>

{/* <!-- 설명 --> */}
<div className={styles.formItem}>
<label htmlFor="description" className="text-caption">설명</label>
<textarea name="description" id="description" cols="30" rows="5"></textarea>
<span className="help-text text-caption">메뉴 등 추가 정보를 입력해 주세요.</span>
</div>

{/* <!-- 추가 버튼 --> */}
<div className={styles.buttonContainer}>
<button className={`${styles.button} ${styles.buttonPrimary} text-caption`}>
추가하기
</button>
</div>
</form>
</div>
</div>
);
}

export default AddRestaurantModal;
25 changes: 25 additions & 0 deletions src/aside/RestaurantDetailModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import styles from "../css/RestaurantDetailModal.module.css";

function RestaurantDetailModal() {
return (
<div className={`${styles.modal} ${styles["modal--open"]}`}>
<div className={styles["modal-backdrop"]}></div>
<div className={styles["modal-container"]}>
<h2 className={`${styles["modal-title"]} text-title`}>음식점 이름</h2>
<div className={styles["restaurant-info"]}>
<p className={`${styles["restaurant-info__description"]} text-body`}>
음식점 소개 문구
</p>
</div>

<div className={styles["button-container"]}>
<button className={`${styles.button} ${styles["button--primary"]} text-caption`}>
닫기
</button>
</div>
</div>
</div>
);
}

export default RestaurantDetailModal;
22 changes: 22 additions & 0 deletions src/css/CategoryFilter.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.restaurant-filter-container {
display: flex;
justify-content: space-between;

padding: 0 16px;
margin-top: 24px;
}

.restaurant-filter-container select {
height: 44px;
min-width: 125px;

border: 1px solid #d0d5dd;
border-radius: 8px;
background: transparent;

font-size: 16px;
}

.restaurant-filter {
padding: 8px;
}
32 changes: 32 additions & 0 deletions src/css/Header.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.gnb {
display: flex;
justify-content: space-between;
align-items: center;
height: 64px;

padding: 0 16px;

background-color: var(--primary-color);
}

.gnb__title {
color: #fcfcfd;
}

.gnb__button {
height: 40px;

border: none;
border-radius: 8px;
background: transparent;

font-size: 24px;
cursor: pointer;
}

.gnb__button img {
display: block;
width: 40px;
height: 40px;
object-fit: contain;
}
125 changes: 125 additions & 0 deletions src/css/RestaurantDetailModal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
.modal {
display: none;
}

.modal--open {
display: none;
}

.modal-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;

background: rgba(0, 0, 0, 0.35);
}

.modal-container {
position: fixed;
bottom: 0;
width: 100%;

padding: 32px 16px;

border-radius: 8px 8px 0px 0px;
background: var(--grey-100);
}

.modal-title {
margin-bottom: 36px;
}

.form-item {
display: flex;
flex-direction: column;

margin-bottom: 36px;
}

.form-item label {
color: var(--grey-400);
font-size: 14px;
}

.form-item--required label::after {
padding-left: 4px;

color: var(--primary-color);
content: "*";
}

.form-item .help-text {
color: var(--grey-300);
}

.form-item input,
.form-item textarea,
.form-item select {
padding: 8px;
margin: 6px 0;

border: 1px solid var(--grey-200);
border-radius: 8px;

font-size: 16px;
}

.form-item textarea {
resize: none;
}

.form-item select {
height: 44px;

padding: 8px;

border: 1px solid var(--grey-200);
border-radius: 8px;

color: var(--grey-300);
}

input[name="name"],
input[name="link"] {
height: 44px;
}

.button-container {
display: flex;
}

.button {
width: 100%;
height: 44px;

margin-right: 16px;

border: none;
border-radius: 8px;

font-weight: 600;
cursor: pointer;
}

.button:last-child {
margin-right: 0;
}

.button--secondary {
border: 1px solid var(--grey-300);
background: transparent;

color: var(--grey-300);
}

.button--primary {
background: var(--primary-color);

color: var(--grey-100);
}

.restaurant-info {
margin-bottom: 24px;
}
Loading