diff --git a/package-lock.json b/package-lock.json index b55ec57..04dbe61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1366,6 +1366,18 @@ "react-transition-group": "^4.4.0" } }, + "@material-ui/lab": { + "version": "4.0.0-alpha.56", + "resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz", + "integrity": "sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.10.2", + "clsx": "^1.0.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0" + } + }, "@material-ui/styles": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.10.0.tgz", @@ -2571,6 +2583,37 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==" }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -11266,6 +11309,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-redux": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", + "integrity": "sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==", + "requires": { + "@babel/runtime": "^7.5.5", + "hoist-non-react-statics": "^3.3.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.9.0" + } + }, "react-scripts": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz", @@ -11399,6 +11454,20 @@ "strip-indent": "^3.0.0" } }, + "redux": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", + "integrity": "sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w==", + "requires": { + "loose-envify": "^1.4.0", + "symbol-observable": "^1.2.0" + } + }, + "redux-thunk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz", + "integrity": "sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw==" + }, "regenerate": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", @@ -12905,6 +12974,11 @@ "util.promisify": "~1.0.0" } }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 5e14226..0c9435a 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,18 @@ "private": true, "dependencies": { "@material-ui/core": "^4.11.0", + "@material-ui/lab": "^4.0.0-alpha.56", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "axios": "^0.19.2", "node-sass": "^4.14.1", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-scripts": "3.4.1" + "react-redux": "^7.2.0", + "react-scripts": "3.4.1", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0" }, "scripts": { "start": "react-scripts start", diff --git a/src/App.js b/src/App.js index 321e12f..70672e3 100644 --- a/src/App.js +++ b/src/App.js @@ -4,20 +4,31 @@ import "./App.scss"; import TopBar from "./components/TopBar"; import Footer from "./components/Footer"; import SearchPanel from "./components/SearchPanel"; +import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles"; + +const theme = createMuiTheme({ + palette: { + primary: { + main: "#0e8496", + }, + }, +}); function App() { return ( -
- -
- Menui logo - -

- Sprawdź co serwuje Twoja ulubiona restauracja. -

+ +
+ +
+ Menui logo + +

+ Sprawdź co serwuje Twoja ulubiona restauracja. +

+
+
-
-
+ ); } diff --git a/src/App.scss b/src/App.scss index f42847e..1fb5149 100644 --- a/src/App.scss +++ b/src/App.scss @@ -1,6 +1,7 @@ @import "./Design.scss"; @import "./styles/TopBar.scss"; @import "./styles/SearchPanel.scss"; +@import "./styles/Footer.scss"; .App { padding: 0; diff --git a/src/Services.js b/src/Services.js index e69de29..d378720 100644 --- a/src/Services.js +++ b/src/Services.js @@ -0,0 +1 @@ +import axios from "axios"; diff --git a/src/actions/index.js b/src/actions/index.js new file mode 100644 index 0000000..3c50ac4 --- /dev/null +++ b/src/actions/index.js @@ -0,0 +1,37 @@ +import axios from "axios"; + +const autocomplete = (input) => { + return { + type: "AUTOCOMPLETE_ADD", + payload: input, + }; +}; + +export const clearAutocomplete = () => { + return { + type: "AUTOCOMPLETE_CLEAR", + }; +}; + +export const fetchAutocomplete = (input) => { + return function (dispatch) { + axios + .get("http://localhost:4000/search/autocomplete?string=" + input) + .then((response) => { + const cities = Array.from(response.data.cities); + const restaurants = Array.from(response.data.restaurants); + const options = cities.concat(restaurants); + + dispatch(autocomplete(options)); + }) + .catch((err) => { + console.log(err); + }); + }; +}; + +export const setAppMode = (mode) => { + return { + type: mode, + }; +}; diff --git a/src/components/ButtonPrimary.js b/src/components/ButtonPrimary.js index 57dc23a..bb1504e 100644 --- a/src/components/ButtonPrimary.js +++ b/src/components/ButtonPrimary.js @@ -4,12 +4,13 @@ import Button from "@material-ui/core/Button"; const StyledButton = withStyles({ root: { - background: "none", - color: "white", + background: "white", + color: "#0e8496", margin: "16px 16px 16px 0px", padding: "8px 12px 8px 12px", - borderColor: "white", - border: "solid 1px", + "&:hover": { + color: "white", + }, }, label: { textTransform: "none", diff --git a/src/components/SearchPanel.js b/src/components/SearchPanel.js index abd92d1..d912c04 100644 --- a/src/components/SearchPanel.js +++ b/src/components/SearchPanel.js @@ -1,21 +1,33 @@ import React from "react"; import ButtonSecondary from "./ButtonSecondary"; -import CustomTextInput from "./CustomTextInput"; +import TextField from "@material-ui/core/TextField"; +import Autocomplete from "@material-ui/lab/Autocomplete"; +import { useSelector, useDispatch } from "react-redux"; +import { fetchAutocomplete } from "../actions"; -export default class SearchPanel extends React.Component { - render() { - return ( -
- -
- -
+export default function SearchPanel() { + let options = useSelector((store) => store.autocomplete); + const dispatch = useDispatch(); + + return ( +
+ ( + dispatch(fetchAutocomplete(event.target.value))} + /> + )} + /> + +
+
- ); - } +
+ ); } diff --git a/src/components/TopBar.js b/src/components/TopBar.js index 628c382..e5b7f4e 100644 --- a/src/components/TopBar.js +++ b/src/components/TopBar.js @@ -1,14 +1,14 @@ import React from "react"; -import ButtonSecondary from "./ButtonSecondary"; -import logo from "../public/logo_mint.svg"; +import ButtonPrimary from "./ButtonPrimary"; +import logo from "../public/logo_white.svg"; export default function TopBar() { return (
Menui logo
- - + +
); diff --git a/src/index.js b/src/index.js index 3125ee4..70eb46e 100644 --- a/src/index.js +++ b/src/index.js @@ -1,13 +1,19 @@ import React from "react"; import ReactDOM from "react-dom"; +import { Provider } from "react-redux"; import "./index.scss"; import App from "./App"; import * as serviceWorker from "./serviceWorker"; +import rootReducer from "./reducers"; +import thunk from "redux-thunk"; +import { createStore, applyMiddleware } from "redux"; + +const store = createStore(rootReducer, applyMiddleware(thunk)); ReactDOM.render( - + - , + , document.getElementById("root") ); diff --git a/src/reducers/appMode.js b/src/reducers/appMode.js new file mode 100644 index 0000000..a8e04dc --- /dev/null +++ b/src/reducers/appMode.js @@ -0,0 +1,22 @@ +const appModeReducer = (state = "init", action) => { + switch (action.type) { + case "APP_INIT": + return (state = "init"); + case "APP_SEARCH_RESULTS": + return (state = "search results"); + case "APP_LOGIN": + return (state = "login"); + case "APP_RESTAURANT": + return (state = "restaurant"); + case "APP_DISH": + return (state = "dish"); + case "APP_ADD_RESTAURANT": + return (state = "add restaurant"); + case "APP_ADD_DISH": + return (state = "add dish"); + default: + return state; + } +}; + +export default appModeReducer; diff --git a/src/reducers/autoComplete.js b/src/reducers/autoComplete.js new file mode 100644 index 0000000..87edb4e --- /dev/null +++ b/src/reducers/autoComplete.js @@ -0,0 +1,12 @@ +const autoCompleteReducer = (state = [], action) => { + switch (action.type) { + case "AUTOCOMPLETE_ADD": + return action.payload; + case "AUTOCOMPLETE_CLEAR": + return (state = []); + default: + return state; + } +}; + +export default autoCompleteReducer; diff --git a/src/reducers/index.js b/src/reducers/index.js new file mode 100644 index 0000000..ad1a00c --- /dev/null +++ b/src/reducers/index.js @@ -0,0 +1,12 @@ +import { combineReducers } from "redux"; +import autoCompleteReducer from "./autoComplete"; +import searchResults from "./searchResults"; +import appMode from "./appMode"; + +const rootReducer = combineReducers({ + autocomplete: autoCompleteReducer, + appMode: appMode, + searchResults: searchResults, +}); + +export default rootReducer; diff --git a/src/reducers/searchResults.js b/src/reducers/searchResults.js new file mode 100644 index 0000000..84fdc06 --- /dev/null +++ b/src/reducers/searchResults.js @@ -0,0 +1,12 @@ +const searchResults = (state = {}, action) => { + switch (action.type) { + case "SEARCH_RESULTS": + return action.payload; + case "SEARCH_CLEAR": + return (state = {}); + default: + return state; + } +}; + +export default searchResults; diff --git a/src/styles/Footer.scss b/src/styles/Footer.scss new file mode 100644 index 0000000..7d1729d --- /dev/null +++ b/src/styles/Footer.scss @@ -0,0 +1,9 @@ +@import "../Design.scss"; + +.footer { + background-color: $main-color; + + p { + color: white; + } +} diff --git a/src/styles/TopBar.scss b/src/styles/TopBar.scss index 904783b..0c05ba9 100644 --- a/src/styles/TopBar.scss +++ b/src/styles/TopBar.scss @@ -1,8 +1,10 @@ +@import "../Design.scss"; + .topBar { width: 100%; display: flex; justify-content: space-between; - background-color: #ebebeb; + background-color: $main-color; } .topBarLogo {