diff --git a/src/App.js b/src/App.js index 8df143e..f1bc47c 100644 --- a/src/App.js +++ b/src/App.js @@ -1,14 +1,7 @@ import React, { Component } from "react"; import { Route, Switch, withRouter } from "react-router-dom"; import { connect } from "react-redux"; -import { - MainView, - Header, - LoginPopup, - Enrolment, - ViewRecipe, - MyMenu -} from "./containers"; +import { MainView, Header, Enrolment, ViewRecipe, MyMenu } from "./containers"; import classNames from "classnames/bind"; import styles from "./App.scss"; const cx = classNames.bind(styles); @@ -20,8 +13,10 @@ const mapDispatchToProps = dispatch => ({}); class App extends Component { render() { + const bEnrolment = + this.props.location.pathname.indexOf("enrolment") > 0 ? true : false; return ( -
+
@@ -29,13 +24,16 @@ class App extends Component {
-
- - - - - -
+ {!bEnrolment && ( +
+ + + + + + +
+ )}
); } diff --git a/src/App.scss b/src/App.scss index e6cb884..de8aeca 100644 --- a/src/App.scss +++ b/src/App.scss @@ -2,9 +2,13 @@ position: absolute; display: grid; grid-template-rows: 80px auto; + &.one { + grid-template-rows: auto; + } height: 100%; width: 100%; .top { + position: absolute; grid-row: 1 / span 1; height: 100%; width: 100%; diff --git a/src/api/userAPI.js b/src/api/userAPI.js index 39ccb3e..7f37e1e 100644 --- a/src/api/userAPI.js +++ b/src/api/userAPI.js @@ -69,3 +69,12 @@ export async function setUserDelete(userid, password) { const res = await webRequestUtil.post({ url, body }); return res.data; } + +export async function deleteCocktail(id) { + const url = "del/"; + const body = { + id + }; + const res = await webRequestUtil.get({ url, body }); + return res.data; +} diff --git a/src/components/SearchResultItem/SearchResultItem.jsx b/src/components/SearchResultItem/SearchResultItem.jsx index 0a62176..99ed284 100644 --- a/src/components/SearchResultItem/SearchResultItem.jsx +++ b/src/components/SearchResultItem/SearchResultItem.jsx @@ -1,7 +1,7 @@ import React from "react"; import classNames from "classnames/bind"; import styles from "./SearchResultItem.scss"; -import xbox from "../../static/images/a1.jpeg"; +import xbox from "../../static/images/ErrorImage.svg"; const cx = classNames.bind(styles); @@ -26,6 +26,7 @@ const SearchResultItem = ({ onError={e => { e.target.onerror = null; e.target.src = xbox; + e.target.className = cx("item_img", "_xbox"); }} src={image} alt="사진" @@ -41,13 +42,13 @@ const SearchResultItem = ({
)} -
+
{name}
{owner}
-
+
{scrap}
diff --git a/src/components/SearchResultItem/SearchResultItem.scss b/src/components/SearchResultItem/SearchResultItem.scss index c2442aa..bd93c94 100644 --- a/src/components/SearchResultItem/SearchResultItem.scss +++ b/src/components/SearchResultItem/SearchResultItem.scss @@ -2,6 +2,12 @@ .item_img { width: inherit; height: inherit; + + &._xbox { + min-width: 360px; + background-color: gray; + opacity: 0.5; + } } .modify_rect { @@ -60,7 +66,6 @@ letter-spacing: normal; text-align: left; color: #ffffff; - cursor: pointer; } .bottom { @@ -100,6 +105,7 @@ background-position: center; background-size: inherit; margin-right: 10.2px; + cursor: pointer; } .number { height: 100%; diff --git a/src/containers/Header/Header.jsx b/src/containers/Header/Header.jsx index a1c5394..15239e5 100644 --- a/src/containers/Header/Header.jsx +++ b/src/containers/Header/Header.jsx @@ -12,6 +12,9 @@ import SearchResult from "../SearchResult/SearchResult"; import { loginRequest, logout } from "../../action/userAction"; import { searchRequest } from "../../action/searchAction"; import { withRouter } from "react-router-dom"; + +import { CircleSpinner } from "react-spinners-kit"; + const cx = classNames.bind(styles); const mapStateToProps = state => { @@ -88,11 +91,13 @@ class Header extends Component { bHideSearch: false, popupID: "login", userID: "", - password: "" + password: "", + bSearchAction: false, + isScroll: false }; componentDidMount() { - const auth = JSON.parse(localStorage.getItem("myData")); //localstorage에서 가져옴\ + const auth = JSON.parse(localStorage.getItem("myData")); //localstorage에서 가져옴 //자동 로그인 기능 if (auth) { this.setState({ userID: auth.userid, password: auth.password }); @@ -105,7 +110,8 @@ class Header extends Component { bShowLogin, bShowSearch, selectedOption, - bsearchRequest + bsearchRequest, + bSearchAction } = this.state; const { searchReducer } = this.props; if (this.props.bLoginResult && bShowLogin) { @@ -120,8 +126,10 @@ class Header extends Component { } } - if (!bShowSearch && searchReducer.searchresult.cocktails.length) { + if (!bShowSearch && searchReducer.searchword) { searchReducer.searchresult.cocktails = []; + searchReducer.searchword = ""; + return; } //filter 변경에 의한 searchAPI 호출 @@ -129,7 +137,9 @@ class Header extends Component { const word = searchReducer.searchword; const filter = selectedOption.value; const type = searchReducer.type; + this.setState({ bsearchRequest: true }); this.props.searchRequest({ word, filter, type }); + return; } // 결과창 떠있는 상태에서 검색 종류 or 단어 변경하여 검색 시 필터콤보 초기값으로 변경 @@ -137,8 +147,15 @@ class Header extends Component { prevProps.searchReducer.searchword !== searchReducer.searchword || prevProps.searchReducer.type !== searchReducer.type ) { - this.setState({ selectedOption: filter[0] }); - return; + if (bSearchAction && bsearchRequest) { + this.setState({ + selectedOption: filter[0], + bsearchRequest: false, + isScroll: false + }); + } else { + this.setState({ selectedOption: filter[0], isScroll: false }); + } } if ( @@ -146,12 +163,22 @@ class Header extends Component { prevProps.searchReducer.searchresult.cocktails !== searchReducer.searchresult.cocktails ) { - this.setState({ bsearchRequest: false }); + this.setState({ bsearchRequest: false, isScroll: false }); } } onChangeSearchStatus = event => { - this.setState({ bShowSearch: !this.state.bShowSearch, bHideSearch: false }); + if (this.state.bHideSearch && this.state.bShowSearch) { + this.setState({ + bHideSearch: false + }); + } else if (!this.state.bHideSearch) { + this.setState({ + bShowSearch: !this.state.bShowSearch, + bHideSearch: false, + bSearchAction: false + }); + } }; handleChangeFilter = selectedOption => { @@ -173,7 +200,7 @@ class Header extends Component { const filter = selectedOption.value; const type = searchReducer.type; - this.setState({ bsearchRequest: true }); + this.setState({ bsearchRequest: true, isScroll: true }); this.props.searchRequest({ word, filter, type, index: nextPage }); } }; @@ -218,6 +245,10 @@ class Header extends Component { if (this.props.bLoginResult && this.state.bShowUser) { this.setState({ bShowUser: false, popupID: "login" }); this.props.logout(); + + const { history } = this.props; + if (history && history.location.pathname !== "/") + this.props.history.push("/"); } }; @@ -254,13 +285,21 @@ class Header extends Component { } }; + //검색 유/무 알려고 만든 것(SearchPopup에 넘김) + onSearchAction = (action = false) => { + this.setState({ bSearchAction: action, bsearchRequest: action }); + }; + render() { const { bShowSearch, bShowLogin, bShowUser, selectedOption, - bHideSearch + bHideSearch, + bSearchAction, + bsearchRequest, + isScroll } = this.state; const { searchresult } = this.props.searchReducer; @@ -269,16 +308,27 @@ class Header extends Component { className={cx( "container", bShowSearch ? "_over" : "", - searchresult.cocktails.length ? "_result" : "" + bSearchAction ? "_result" : "" )} >
-
+
); @@ -128,6 +189,40 @@ class SearchResult extends Component { }); }; + onLikeClick = event => { + event.preventDefault(); + event.stopPropagation(); + const id = event.target.id; + const { searchList, page } = this.state; + + //서버 통신 + + //state.list에 반영 + this.setState({ + searchList: searchList.map(item => + item.page === page + ? { + ...item, + list: item.list.map(cocktail => + cocktail.props.props._id === id + ? { + ...cocktail, + props: { + ...cocktail.props, + props: { + ...cocktail.props.props, + scrap: cocktail.props.props.scrap + 1 + } + } + } + : cocktail + ) + } + : item + ) + }); + }; + loadItems(groupKey, list) { const items = []; const start = this.start || 0; @@ -152,6 +247,7 @@ class SearchResult extends Component { modify={modify} modifyClick={this.onModifyClick} informationClick={this.onCocktailClick} + likeClick={this.onLikeClick} /> ); } @@ -243,8 +339,10 @@ class SearchResult extends Component { window.event.target.scrollHeight <= scrollPos + window.event.target.clientHeight ) { - if (this.props.pages > this.props.page) + if (this.props.pages > this.props.page) { + this.setState({ bLoding: true }); this.props.handleNotifyScroll({ next: this.props.page + 1 }); + } } } }; @@ -255,6 +353,9 @@ class SearchResult extends Component { return (
+ {this.state.bShowDelete && ( +
{this.showNotifyPopup()}
+ )} { return item.list; })} + {this.state.bLoding && ( +
+ +
+ )} {this.state.showModify && this.showModifyPopup()}
diff --git a/src/containers/SearchResult/SearchResult.scss b/src/containers/SearchResult/SearchResult.scss index 195b93f..d1b002d 100644 --- a/src/containers/SearchResult/SearchResult.scss +++ b/src/containers/SearchResult/SearchResult.scss @@ -58,3 +58,74 @@ } } } + +.notifypopup_rect { + position: absolute; + background-color: #080f24ee; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + .showNotifyPopup { + width: 250px; + height: 100px; + background-color: #0f1835; + + .text { + display: inline-block; + width: 100%; + height: 40px; + background-color: transparent; + font-family: NotoSansCJKkr; + font-weight: bold; + font-size: 25px; + line-height: 1.8; + color: #ff365d; + cursor: default; + } + + .container { + width: 100%; + height: 60px; + background-color: transparent; + display: flex; + justify-content: space-around; + align-items: center; + + .ok { + width: 100px; + height: 30px; + + border-radius: 18px; + border-color: transparent; + background-color: #bbbbbb; + font-family: NotoSansCJKkr; + font-size: 20px; + color: #080f24; + text-align: center; + cursor: pointer; + } + .cancel { + width: 100px; + height: 30px; + + border-radius: 18px; + border-color: transparent; + background-color: #7a7a7a; + font-family: NotoSansCJKkr; + font-size: 20px; + color: #080f24; + cursor: pointer; + } + } + } +} +.loding_rect { + position: relative; + width: 100%; + height: auto; + display: flex; + justify-content: center; +} diff --git a/src/containers/ViewRecipe/ViewRecipe.jsx b/src/containers/ViewRecipe/ViewRecipe.jsx index dbe93c7..f75d94b 100644 --- a/src/containers/ViewRecipe/ViewRecipe.jsx +++ b/src/containers/ViewRecipe/ViewRecipe.jsx @@ -201,11 +201,11 @@ class ViewRecipe extends Component { comment.style.opacity = 1; } - } + }; onAddComment = () => { let comment = document.querySelector("#commentText").value; - if (comment !== '' && comment !== undefined && comment !== null) { + if (comment !== "" && comment !== undefined && comment !== null) { let now = new Date(); let time = now.getHours > 9 ? `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}` : `0${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`; let comments = this.state.comments; @@ -252,9 +252,7 @@ class ViewRecipe extends Component {
- - {this.state.main} - + {this.state.main}
@@ -274,10 +272,8 @@ class ViewRecipe extends Component {
{this.state.side} -
-
@@ -307,7 +303,6 @@ class ViewRecipe extends Component { className={cx("recipe-view-detail")} content={this.viewRecipe_form()} /> - ); } } diff --git a/src/reducer/userReducer.js b/src/reducer/userReducer.js index 88836c2..d43628b 100644 --- a/src/reducer/userReducer.js +++ b/src/reducer/userReducer.js @@ -6,7 +6,8 @@ const initialState = { bLoginResult: false, mymenu: { scrap: [], - recipes: [] + recipes: [], + bRecipeDelete: false }, user: { state: "none", @@ -82,6 +83,45 @@ const reducer = (state = initialState, action) => { recipes: result } }; + } else if (type === 2) { + return { + ...state, + mymenu: { + ...state.mymenu, + bRecipeDelete: result + } + }; + } + return { + ...state + }; + } + case actions.COMMUNICATION.ERROR: { + const { type, result } = action.payload; + if (type === 0) { + return { + ...state, + mymenu: { + ...state.mymenu, + scrap: [] + } + }; + } else if (type === 1) { + return { + ...state, + mymenu: { + ...state.mymenu, + recipes: [] + } + }; + } else if (type === 2) { + return { + ...state, + mymenu: { + ...state.mymenu, + bRecipeDelete: result + } + }; } return { ...state diff --git a/src/saga/userSaga.js b/src/saga/userSaga.js index 1602f38..e26a8a5 100644 --- a/src/saga/userSaga.js +++ b/src/saga/userSaga.js @@ -20,7 +20,8 @@ import { getMyScrap, getMyRecipes, setUserEdit, - setUserDelete + setUserDelete, + deleteCocktail } from "../api/userAPI"; const dumy_data = [ @@ -371,10 +372,13 @@ function* getUserData(action) { } else if (type === 1) { // result = yield call(getMyRecipes, id); result = [dumy_data[0], dumy_data[1]]; + } else if (type === 2) { + // result = yield call(deleteCocktail, id); + result = true; } yield put(dataEnd(type, result)); } catch (error) { - yield put(dataError(false)); + yield put(dataError(type, false)); } } diff --git a/src/static/images/ErrorImage.svg b/src/static/images/ErrorImage.svg new file mode 100644 index 0000000..8cdf5b0 --- /dev/null +++ b/src/static/images/ErrorImage.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/images/SearchResultOff.svg b/src/static/images/SearchResultOff.svg new file mode 100644 index 0000000..098b766 --- /dev/null +++ b/src/static/images/SearchResultOff.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/static/images/gray_search.svg b/src/static/images/gray_search.svg new file mode 100644 index 0000000..9bd7b8d --- /dev/null +++ b/src/static/images/gray_search.svg @@ -0,0 +1,10 @@ + + + + + + + +