Skip to content

Commit

Permalink
나만의 칵테일과 관련된 프론트를 구현한다. (미완성) (#264)
Browse files Browse the repository at this point in the history
* feat: StepProgressBar 컴포넌트 추가

- 외부 모듈 사용

* feat: UserCocktail, Question 컴포넌트 추가

- 추천 질문과 구분
- 라우트 연결

* feat: url path에 따라 다른 컴포넌트를 보여주도록 설정

- Name 컴포넌트 생성

* feat: user cocktail에 대한 recoil atom 추가

* feat: user cocktail 생성에 필요한 컴포넌트 간단하게 구현

* refactor: StepProgressBar 수정

* feat: UserCocktail에 컴포넌트 리렌더링 구현

* refactor: Name을 변수로 관리하다가 전역 상태로 관리하도록 수정

* feat: Ingredient 임시 구현

- 클릭시 선택
- api 연결 필요
- 검색 기능 필요

* refactor: ProgressBar에 number를 넘기도록 수정

* feat: Glass 임시 구현

- Slider 필요
- api 필요

* refactor: Glass 선택시 전역 객체가 관리하도록 수정

* chore: 백엔드와 api 맞추기 위한 코멘트 추가

* fix: 전역변수 key를 수정 못한 부분 수정

* refactor: 리뷰 반영

- ===를 사용, null대신 빈 문자열을 사용

* refactor: for를 이용하여 중복 제거
  • Loading branch information
toneyparky authored Feb 20, 2021
1 parent e7e5968 commit 4f8492d
Show file tree
Hide file tree
Showing 18 changed files with 508 additions and 5 deletions.
34 changes: 34 additions & 0 deletions front/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 front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"react-router-dom": "^5.2.0",
"react-s-alert": "^1.4.1",
"react-scripts": "3.4.1",
"react-step-progress-bar": "^1.0.3",
"recoil": "0.0.10",
"recoil-persist": "^0.6.0",
"styled-components": "^5.1.1"
Expand Down
6 changes: 3 additions & 3 deletions front/src/component/recommend/Question.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import { questions } from "./const";
import { recommendationQuestions } from "./const";
import { createRecommend } from "../../api";
import Dislike from "./Dislike";
import Intro from "./Intro";
Expand All @@ -15,15 +15,15 @@ const INITIAL_STAGE = 1;
const Question = ({ setRecommendedCocktails }) => {
const [answers, setAnswers] = useState({});
const [stage, setStage] = useState(INITIAL_STAGE);
const [question, setQuestion] = useState(questions[stage - 1]);
const [question, setQuestion] = useState(recommendationQuestions[stage - 1]);

const addAnswer = (type, answer) => {
const wrappedAnswer = { [type]: answer };
if (stage !== INITIAL_STAGE) {
setAnswers({ ...answers, ...wrappedAnswer });
}
setStage(stage + 1);
setQuestion(questions[stage]);
setQuestion(recommendationQuestions[stage]);
};

const history = useHistory();
Expand Down
10 changes: 9 additions & 1 deletion front/src/component/recommend/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const bartenderSaying = [
"조심하세요🚨 칵테일의 매력에서 빠져나올 수 없으실테니까요😀",
];

export const questions = [
export const recommendationQuestions = [
intro[Math.floor(Math.random() * intro.length)], // INTRO
"첫 질문입니다!\n이런 느낌의 칵테일은 어떠세요?", // CONCEPT
"도수는 어느 정도가 좋으신가요?\n최저 도수와 최대 도수의 범위를 정해주세요!", // ABV
Expand All @@ -26,6 +26,14 @@ export const questions = [
"이제 한 가지만 더 여쭤볼게요.\n다음 중 먹고 싶지 않은 재료들을\n모두 골라주세요!", // DISLIKE
];

export const userCocktailQuestions = {
name: "칵테일의 이름은 무엇인가요?",
ingredients: "어떤 재료가 들어가요?",
glass: "어떤 잔으로 계량할까요?",
amount: "얼마나 넣으면 좋을까요?",
recipe: "입력하신 정보를 확인해보세요.",
};

export const answerList = [
{
yes: "매우 좋아요",
Expand Down
26 changes: 26 additions & 0 deletions front/src/component/userCocktail/Amount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import { useHistory } from "react-router-dom";
import { useRecoilState } from "recoil";
import { userCocktailState } from "../../recoil";

const Amount = ({ setStage }) => {
const history = useHistory();
const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState);

const onNext = (e) => {
e.preventDefault();
history.push("/my-cocktail/recipe");
setStage("recipe");
};

return (
<div>
<div>amount 화면입니다.</div>
<button className="next-button" type="submit" onClick={onNext}>
레시피 확인하러 고!
</button>
</div>
);
};

export default Amount;
80 changes: 80 additions & 0 deletions front/src/component/userCocktail/Glass.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { useState } from "react";
import { useHistory } from "react-router-dom";
import { useRecoilState } from "recoil";
import div from "infinite-react-carousel";
import { userCocktailState } from "../../recoil";
import GlassItem from "./GlassItem";

const Glass = ({ setStage }) => {
const history = useHistory();
const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState);
const [selected, setSelected] = useState({ id: 0, name: "기본값" });

const onNext = (e) => {
e.preventDefault();
const lastRecipe =
userCocktail.userRecipeItemRequests[
userCocktail.userRecipeItemRequests.length - 1
];
setUserCocktail({
...userCocktail,
userRecipeItemRequests: [
...userCocktail.userRecipeItemRequests.slice(0, -1),
{
ingredientId: lastRecipe.ingredientId,
ingredientName: lastRecipe.ingredientName,
glassId: selected.id,
glassName: selected.name,
},
],
});
history.push("/my-cocktail/amount");
setStage("amount");
};

const glasses =
// api로 받아오든 내부에 있는 값을 가져오든 해야한다.
// 값도 바뀌어야 한다. 백에서 원하는 SOJU BEER PAPER SHOT PIECE를 가지고 이미지 링크와 한글 이름이 필요하다.
[
{ id: 1, name: "반 잔" },
{ id: 2, name: "반의 반 잔" },
{ id: 3, name: "한 잔" },
{ id: 4, name: "두 잔" },
{ id: 5, name: "세 잔" },
{ id: 6, name: "네 잔" },
];

const onSelect = (e) => {
const selectedId = e.target.dataset.id;
const found = glasses.find((it) => it.id === parseInt(selectedId));
setSelected(found);
};

return (
<div className="glass-container">
<div>glass 화면입니다.</div>
<div>
<div>{selected.name}</div>
<button>X</button>
</div>
<div>
{"재료: " +
userCocktail.userRecipeItemRequests[
userCocktail.userRecipeItemRequests.length - 1
].ingredientName}
</div>
<div>
{/*Slider로 수정*/}
{glasses &&
glasses.map((it) => (
<GlassItem glass={it} key={it.id} onSelect={onSelect} />
))}
</div>
<button className="next-button" type="submit" onClick={onNext}>
얼마나 따라야 할까요?
</button>
</div>
);
};

export default Glass;
13 changes: 13 additions & 0 deletions front/src/component/userCocktail/GlassItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

const GlassItem = ({ glass, onSelect }) => {
return (
<div className="glass-item-container" onClick={onSelect}>
<div className="glass-item" data-id={glass.id}>
{glass.name}
</div>
</div>
);
};

export default GlassItem;
76 changes: 76 additions & 0 deletions front/src/component/userCocktail/Ingredient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from "react";
import { useRecoilState } from "recoil";
import { userCocktailState } from "../../recoil";
import { useHistory } from "react-router-dom";

const Ingredient = ({ setStage }) => {
const history = useHistory();
const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState);
const [selected, setSelected] = useState({ id: 0, name: "기본" });

const searchIngredient = (e) => {
// 자동완성 api 쏘고 받아오고 띄워주고. 그니가 구현한 자동완성처럼.
// 혹은 아래 ingredients를 받아올 때에 모든 ingredients를 다 받아오고 랜덤으로 몇 개만 아래에서 보여주고
// 여기서 자동완성도 api 안찌르고 미리 받아온거 내에서 처리하기.
};

const onNext = (e) => {
e.preventDefault();
setUserCocktail({
...userCocktail,
userRecipeItemRequests: [
...userCocktail.userRecipeItemRequests,
{ ingredientId: selected.id, ingredientName: selected.name },
],
});
history.push("/my-cocktail/glass");
setStage("glass");
};

const ingredients = () => {
// api를 쏴서 재료 리스트를 받아온다.
return [
{ id: 1, name: "소주" },
{ id: 2, name: "맥주" },
{ id: 3, name: "탕수육" },
{ id: 4, name: "짜장면" },
{ id: 5, name: "민트" },
{ id: 6, name: "게토레이" },
{ id: 7, name: "사이다" },
{ id: 8, name: "생크림" },
{ id: 9, name: "김치찌개" },
{ id: 10, name: "수육" },
];
};

const onSelect = (e) => {
const selectedId = e.target.dataset.id;
const found = ingredients().find((it) => it.id === parseInt(selectedId));
setSelected(found);
};

return (
<>
<div>ingredient 화면입니다.</div>
<div>
<div>{selected.name}</div>
<button>X</button>
</div>
<input type="text" placeholder="검색해보세요." />
<div>
{ingredients().map((it, index) => {
return (
<div key={"ingredient" + index} data-id={it.id} onClick={onSelect}>
{it.name}
</div>
);
})}
</div>
<button className="name-button" type="submit" onClick={onNext}>
다음 단계로 가보죠
</button>
</>
);
};

export default Ingredient;
36 changes: 36 additions & 0 deletions front/src/component/userCocktail/Name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from "react";
import { useRecoilState } from "recoil";
import { useHistory } from "react-router-dom";
import { userCocktailState } from "../../recoil";

const Name = ({ setStage }) => {
const history = useHistory();
const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState);
let name = "";

const onNameChange = (e) => {
name = e.target.value;
};

const onNext = (e) => {
e.preventDefault();
setUserCocktail({
...userCocktail,
name: name,
});
history.push("/my-cocktail/ingredients");
setStage("ingredients");
};

return (
<>
<div>name 화면입니다.</div>
<input className="name-input" onChange={onNameChange} type="text" />
<button className="next-button" type="submit" onClick={onNext}>
칵테일 재료를 정해보아요
</button>
</>
);
};

export default Name;
8 changes: 8 additions & 0 deletions front/src/component/userCocktail/Question.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from "react";
import { userCocktailQuestions } from "../recommend/const";

const Question = ({ stage }) => {
return <div>{userCocktailQuestions[stage]}</div>;
};

export default Question;
39 changes: 39 additions & 0 deletions front/src/component/userCocktail/Recipe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react";
import { useHistory } from "react-router-dom";
import { useRecoilState } from "recoil";
import { userCocktailState } from "../../recoil";

const Recipe = ({ setStage }) => {
const history = useHistory();
const [userCocktail, setUserCocktail] = useRecoilState(userCocktailState);

const onNext = (e) => {
e.preventDefault();
history.push("/my-cocktail/description");
setStage("description");
};

const onIngredient = (e) => {
e.preventDefault();
history.push("/my-cocktail/ingredients");
setStage("ingredients");
};

return (
<>
<div>recipe 화면입니다.</div>
<button
className="ingredient-button"
type="submit"
onClick={onIngredient}
>
재료 추가하기
</button>
<button className="next-button" type="submit" onClick={onNext}>
끝!
</button>
</>
);
};

export default Recipe;
Loading

0 comments on commit 4f8492d

Please sign in to comment.