+ autocomplete + thunk
This commit is contained in:
31
src/App.js
31
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 (
|
||||
<div className="App">
|
||||
<TopBar />
|
||||
<div className="main-container">
|
||||
<img src={logo} className="logo" alt="Menui logo" />
|
||||
<SearchPanel />
|
||||
<p className="darkParagraph">
|
||||
Sprawdź co serwuje Twoja ulubiona restauracja.
|
||||
</p>
|
||||
<ThemeProvider theme={theme}>
|
||||
<div className="App">
|
||||
<TopBar />
|
||||
<div className="main-container">
|
||||
<img src={logo} className="logo" alt="Menui logo" />
|
||||
<SearchPanel />
|
||||
<p className="darkParagraph">
|
||||
Sprawdź co serwuje Twoja ulubiona restauracja.
|
||||
</p>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@import "./Design.scss";
|
||||
@import "./styles/TopBar.scss";
|
||||
@import "./styles/SearchPanel.scss";
|
||||
@import "./styles/Footer.scss";
|
||||
|
||||
.App {
|
||||
padding: 0;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import axios from "axios";
|
||||
|
||||
37
src/actions/index.js
Normal file
37
src/actions/index.js
Normal file
@@ -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,
|
||||
};
|
||||
};
|
||||
@@ -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",
|
||||
|
||||
@@ -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 (
|
||||
<div className="searchPanel">
|
||||
<CustomTextInput
|
||||
color="primary"
|
||||
id="search"
|
||||
label="Miasto, nazwa lokalu,..."
|
||||
type="search"
|
||||
/>
|
||||
<div className="btnContainer">
|
||||
<ButtonSecondary text="Szukaj" />
|
||||
</div>
|
||||
export default function SearchPanel() {
|
||||
let options = useSelector((store) => store.autocomplete);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<div className="searchPanel">
|
||||
<Autocomplete
|
||||
options={options}
|
||||
style={{ width: 300 }}
|
||||
noOptionsText="Brak podpowiedzi"
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
{...params}
|
||||
label="Miasto, Nazwa lokalu, ..."
|
||||
variant="outlined"
|
||||
onInput={(event) => dispatch(fetchAutocomplete(event.target.value))}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="btnContainer">
|
||||
<ButtonSecondary text="Szukaj" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<div className="topBar">
|
||||
<img src={logo} className="topBarLogo" alt="Menui logo" />
|
||||
<div>
|
||||
<ButtonSecondary text="Dodaj Lokal" />
|
||||
<ButtonSecondary text="Logowanie" />
|
||||
<ButtonPrimary text="Dodaj Lokal" />
|
||||
<ButtonPrimary text="Logowanie" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
10
src/index.js
10
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(
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
</Provider>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
|
||||
22
src/reducers/appMode.js
Normal file
22
src/reducers/appMode.js
Normal file
@@ -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;
|
||||
12
src/reducers/autoComplete.js
Normal file
12
src/reducers/autoComplete.js
Normal file
@@ -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;
|
||||
12
src/reducers/index.js
Normal file
12
src/reducers/index.js
Normal file
@@ -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;
|
||||
12
src/reducers/searchResults.js
Normal file
12
src/reducers/searchResults.js
Normal file
@@ -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;
|
||||
9
src/styles/Footer.scss
Normal file
9
src/styles/Footer.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
@import "../Design.scss";
|
||||
|
||||
.footer {
|
||||
background-color: $main-color;
|
||||
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
@import "../Design.scss";
|
||||
|
||||
.topBar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #ebebeb;
|
||||
background-color: $main-color;
|
||||
}
|
||||
|
||||
.topBarLogo {
|
||||
|
||||
Reference in New Issue
Block a user