├── .gitignore ├── README.md ├── client ├── assets │ ├── logo.png │ └── background.gif ├── reducers │ ├── index.js │ └── mainReducer.js ├── constants │ └── actionTypes.js ├── store.js ├── App.jsx ├── index.js ├── components │ ├── MainContainer.jsx │ ├── Navbar.jsx │ ├── ResultCard.jsx │ ├── ResultsContainer.jsx │ └── Sidebar.jsx ├── index.html ├── actions │ └── actions.js └── style.scss ├── .babelrc ├── server ├── router.js ├── server.js └── controller.js ├── webpack.config.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Frollic 2 | 3 | An app for finding accessible venues 4 | -------------------------------------------------------------------------------- /client/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frollic-app/frollic/HEAD/client/assets/logo.png -------------------------------------------------------------------------------- /client/assets/background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frollic-app/frollic/HEAD/client/assets/background.gif -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"], 3 | "plugins": ["@babel/plugin-proposal-class-properties"] 4 | } 5 | -------------------------------------------------------------------------------- /client/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import mainReducer from './mainReducer'; 4 | 5 | const reducers = combineReducers({ 6 | search: mainReducer, 7 | }); 8 | 9 | export default reducers; -------------------------------------------------------------------------------- /client/constants/actionTypes.js: -------------------------------------------------------------------------------- 1 | export const GET_RESULTS = 'GET_RESULTS'; 2 | export const ADD_FAV = 'ADD_FAV'; 3 | export const TOGGLE_FAVS_PAGE = 'TOGGLE_FAVS_PAGE'; 4 | export const ADD_COMMENT = 'ADD_COMMENT'; 5 | export const TOGGLE_COMMENTS = 'TOGGLE_COMMENTS'; -------------------------------------------------------------------------------- /client/store.js: -------------------------------------------------------------------------------- 1 | import { applyMiddleware, createStore } from 'redux'; 2 | import thunk from 'redux-thunk'; 3 | import reducers from './reducers/index'; 4 | 5 | const store = createStore( 6 | reducers, 7 | applyMiddleware(thunk) 8 | ); 9 | 10 | export default store; -------------------------------------------------------------------------------- /client/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navbar from './components/Navbar.jsx'; 3 | import MainContainer from './components/MainContainer.jsx'; 4 | 5 | const App = () => ( 6 |
7 | 8 | 9 |
10 | ); 11 | 12 | export default App; -------------------------------------------------------------------------------- /server/router.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const controller = require('./controller.js'); 3 | const router = express.Router(); 4 | 5 | 6 | //code here 7 | router.post('/search', controller.getResults, (req, res) => { 8 | console.log('in the router'); 9 | res.status(200).json(res.locals); 10 | }); 11 | 12 | module.exports = router; -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import App from './App.jsx'; 5 | import store from './store'; 6 | import style from './style.scss'; 7 | 8 | render( 9 | 10 | 11 | , 12 | document.getElementById('root') 13 | ); 14 | -------------------------------------------------------------------------------- /client/components/MainContainer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Sidebar from './Sidebar.jsx'; 3 | import ResultsContainer from './ResultsContainer.jsx'; 4 | 5 | const MainContainer = () => { 6 | return ( 7 |
8 | 9 | 10 |
11 | ) 12 | } 13 | export default MainContainer; -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Frollic 10 | 11 | 12 | 13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /client/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import * as actions from '../actions/actions'; 4 | 5 | const mapDispatchToProps = (dispatch) => ({ 6 | toggleFavsPage: () => { 7 | dispatch(actions.toggleFavsPage()); 8 | } 9 | }); 10 | 11 | const Navbar = (props) => { 12 | return ( 13 | 21 | ) 22 | } 23 | export default connect(null, mapDispatchToProps)(Navbar); -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const express = require('express'); 3 | const router = require('./router'); 4 | const app = express(); 5 | const port = process.env.PORT || 3000; 6 | 7 | app.use(express.json()); 8 | 9 | app.use('/api', router); 10 | 11 | app.use('/assets', express.static(path.join(__dirname, '../client/assets'))); 12 | 13 | app.use((req, res) => { 14 | console.log('Error: page not found') 15 | res.status(400).send('Error: page not found'); 16 | }); 17 | 18 | app.use((err, req, res, next) => { 19 | if (!err) err = { 20 | log: 'Express error handler caught unknown middleware', 21 | message: { err: 'An unknown error occurred'}, 22 | }; 23 | console.log(err); 24 | return res.status(500).json(err); 25 | }); 26 | 27 | 28 | module.exports = app.listen(port, () => console.log(`Listening on port ${port}`)); -------------------------------------------------------------------------------- /client/actions/actions.js: -------------------------------------------------------------------------------- 1 | import * as types from '../constants/actionTypes'; 2 | import axios from 'axios'; 3 | 4 | export const getResults = (location, radius, categories) => (dispatch) => { 5 | 6 | axios({ 7 | method: 'POST', 8 | url: `/api/search`, 9 | headers: { 'Content-Type': 'application/JSON' }, 10 | data: { 11 | location: location, 12 | radius: radius, 13 | categories: categories, 14 | } 15 | }) 16 | .then((response) => { 17 | dispatch({ 18 | type: types.GET_RESULTS, 19 | payload: response.data, 20 | }); 21 | }); 22 | }; 23 | 24 | export const addFav = (favorite) => ({ 25 | type: types.ADD_FAV, 26 | payload: favorite, 27 | }); 28 | 29 | export const toggleFavsPage = () => ({ 30 | type: types.TOGGLE_FAVS_PAGE, 31 | }); 32 | 33 | export const addComment = (number, comment) => ({ 34 | type: types.ADD_COMMENT, 35 | payload: { number, comment } 36 | }); 37 | 38 | export const toggleComments = () => ({ 39 | type: types.TOGGLE_COMMENTS, 40 | }); -------------------------------------------------------------------------------- /client/components/ResultCard.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {CopyToClipboard} from 'react-copy-to-clipboard'; 3 | 4 | const ResultCard = (props) => { 5 | 6 | return ( 7 |
8 |
9 | 10 |
11 |

{props.distance}

12 |

{props.name}

13 |

{props.price}Rating: {props.rating}

14 |

{props.address}

15 |

{props.phone}

16 | 17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 | ); 28 | } 29 | 30 | export default ResultCard; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin') 4 | const process = require('process'); 5 | 6 | module.exports = { 7 | // entry:[path.join(__dirname, 'client', 'index.js'), path.join(__dirname, 'client', 'style.scss')], 8 | mode: process.env.NODE_ENV, 9 | entry: {src: './client/index.js'}, 10 | output: { 11 | filename: 'bundle.js', 12 | path: path.resolve(__dirname, 'dist'), 13 | // publicPath: '/', 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.jsx?/, 19 | exclude: /node_modules/, 20 | use: { 21 | loader: 'babel-loader', 22 | options: { 23 | presets: ['@babel/preset-env', '@babel/preset-react'], 24 | }, 25 | } 26 | }, 27 | { 28 | test: /.(css|scss)$/, 29 | use: ['style-loader', 'css-loader', 'sass-loader'], 30 | }, 31 | { 32 | test: /\.(png|jp(e*)g|svg|gif)$/, 33 | type: 'asset/resource', 34 | } 35 | ] 36 | }, 37 | plugins: [ 38 | new HtmlWebpackPlugin({ 39 | title: 'Development', 40 | template: './client/index.html', 41 | }) 42 | ], 43 | devServer: { 44 | static: { 45 | publicPath: '/dist', 46 | directory: path.resolve(__dirname, 'dist'), 47 | }, 48 | proxy: { '/api': 'http://localhost:3000', '/assets' : 'http://localhost:3000' } 49 | } 50 | } -------------------------------------------------------------------------------- /client/reducers/mainReducer.js: -------------------------------------------------------------------------------- 1 | import * as types from '../constants/actionTypes'; 2 | 3 | const initialState = { 4 | searchResults: [], 5 | favorites: [], 6 | savedResults: [], 7 | favsPageOn: false, 8 | firstRender: true, 9 | comments: [], 10 | }; 11 | 12 | const mainReducer = (state = initialState, action) => { 13 | 14 | switch (action.type) { 15 | case types.GET_RESULTS: 16 | 17 | return { 18 | ...state, 19 | firstRender: false, 20 | searchResults: action.payload, 21 | } 22 | case types.ADD_FAV: 23 | const newFavs = state.favorites.slice(); 24 | 25 | if (!state.favorites.includes(action.payload)) newFavs.push(action.payload); 26 | 27 | return { 28 | ...state, 29 | favorites: newFavs, 30 | } 31 | case types.TOGGLE_FAVS_PAGE: 32 | if (!state.favsPageOn) { 33 | 34 | return { 35 | ...state, 36 | savedResults: state.searchResults, 37 | searchResults: state.favorites, 38 | favsPageOn: true, 39 | } 40 | } 41 | return { 42 | ...state, 43 | searchResults: state.savedResults, 44 | saveResults: [], 45 | favsPageOn: false, 46 | } 47 | case types.ADD_COMMENT: 48 | const newComments = state.comments.slice(); 49 | newComments.push(action.payload); 50 | 51 | return { 52 | ...state, 53 | comments: state.newComments, 54 | } 55 | case types.TOGGLE_COMMENTS: 56 | return { 57 | ...state, 58 | } 59 | default: 60 | return state; 61 | } 62 | }; 63 | 64 | export default mainReducer; 65 | -------------------------------------------------------------------------------- /server/controller.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | 3 | const controller = {}; 4 | 5 | controller.getResults = (req, res, next) => { 6 | console.log(req); 7 | 8 | const radius = Math.round((req.body.radius || 5) * 1609.34); 9 | const location = (req.body.location || 10109); 10 | const categories = (req.body.categories || []); 11 | console.log(categories); 12 | axios({ 13 | method: 'GET', 14 | url: 'https://api.yelp.com/v3/businesses/search', 15 | // data: {}, 16 | params: { 17 | 'attributes' : 'wheelchair_accessible', 18 | 'radius': radius, 19 | 'location': location, 20 | 'categories': categories, 21 | }, 22 | headers: { 23 | // 'Content-Type': 'application/json', 24 | // 'Connection' : 'keep-alive', 25 | 'Authorization' : 'Bearer ***REMOVED***', 26 | }, 27 | }) 28 | .then((response) => { 29 | res.locals = response.data.businesses.map((business) => ({ 30 | name : business.name, 31 | image : business.image_url, 32 | url : business.url, 33 | address : `${business.location.address1}, ${business.location.city}, ${business.location.state} ${business.location.zip_code}`, 34 | phone : `(${business.phone.slice(2, 5)}) ${business.phone.slice(5, 8)}-${business.phone.slice(8)}`, 35 | rating : business.rating, 36 | price : business.price, 37 | distance :`${Math.round(business.distance * .00062137 * 100) / 100} mi` 38 | })); 39 | }) 40 | .then(() => { next(); }) 41 | .catch((err) => next({ 42 | log: `Error in getResults controller: ${err}`, 43 | message: { err: 'See log for error details'}, 44 | })); 45 | } 46 | 47 | 48 | module.exports = controller; -------------------------------------------------------------------------------- /client/components/ResultsContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { connect } from 'react-redux'; 3 | import ResultCard from './ResultCard.jsx' 4 | import * as actions from '../actions/actions'; 5 | 6 | const mapStateToProps = (state) => ({ 7 | searchResults: state.search.searchResults, 8 | firstRender: state.search.firstRender, 9 | }); 10 | 11 | const mapDispatchToProps = (dispatch) => ({ 12 | addFav: (favorite) => { 13 | dispatch(actions.addFav(favorite)); 14 | }, 15 | addComment: (comment) => { 16 | dispatch(actions.addComment(comment)); 17 | } 18 | }); 19 | 20 | const ResultsContainer = (props) => { 21 | 22 | if (!props.searchResults.length && !props.firstRender) { 23 | return ( 24 |
25 |

Sorry, no results found matching your query.
Try expanding your search radius.

26 |
27 | ) 28 | } else if (!props.searchResults.length) { 29 | return ( 30 |
31 |

fun with frollic

32 |
33 | ) 34 | } 35 | 36 | const resultCards = props.searchResults.map((resultObj, index) => { 37 | return 51 | }); 52 | 53 | return ( 54 |
55 |

Results:

56 | {resultCards} 57 |
58 | ); 59 | } 60 | 61 | export default connect(mapStateToProps, mapDispatchToProps)(ResultsContainer); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "access", 3 | "version": "1.0.0", 4 | "description": "An app to help plan accessible events", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "cross-env NODE_ENV=production nodemon server/server.js", 8 | "build": "cross-env NODE_ENV=production webpack", 9 | "dev": "concurrently \"cross-env NODE_ENV=development nodemon server/server.js\" \"cross-env NODE_ENV=development webpack serve --open\"", 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/Star-Nosed/Moles.git" 15 | }, 16 | "keywords": [ 17 | "accessibility", 18 | "social", 19 | "entertainment" 20 | ], 21 | "author": "Aram Paparian, Katrina Henderson, Wirapa May Boonyasurat, Megan Nadkarni", 22 | "license": "ISC", 23 | "bugs": { 24 | "url": "https://github.com/Star-Nosed/Moles/issues" 25 | }, 26 | "homepage": "https://github.com/Star-Nosed/Moles#readme", 27 | "dependencies": { 28 | "axios": "^0.25.0", 29 | "bootstrap": "^5.1.3", 30 | "copy-to-clipboard": "^3.3.1", 31 | "css-loader": "^6.5.1", 32 | "express": "^4.17.2", 33 | "file-loader": "^6.2.0", 34 | "html-webpack-plugin": "^5.5.0", 35 | "install": "^0.13.0", 36 | "nodemon": "^2.0.15", 37 | "npm": "^8.4.0", 38 | "react": "^17.0.2", 39 | "react-copy-to-clipboard": "^5.0.4", 40 | "react-dom": "^17.0.2", 41 | "react-redux": "^7.2.6", 42 | "react-router-dom": "^6.2.1", 43 | "redux": "^4.1.2", 44 | "redux-devtools-extension": "^2.13.9", 45 | "redux-thunk": "^2.4.1", 46 | "save": "^2.4.0", 47 | "scss-loader": "^0.0.1", 48 | "style-loader": "^3.3.1", 49 | "url-loader": "^4.1.1" 50 | }, 51 | "devDependencies": { 52 | "@babel/core": "^7.16.12", 53 | "@babel/preset-env": "^7.16.11", 54 | "@babel/preset-react": "^7.16.7", 55 | "babel-loader": "^8.2.3", 56 | "concurrently": "^7.0.0", 57 | "cross-env": "^7.0.3", 58 | "sass": "^1.49.0", 59 | "sass-loader": "^12.4.0", 60 | "webpack": "^5.67.0", 61 | "webpack-cli": "^4.9.2", 62 | "webpack-dev-server": "^4.7.3" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /client/components/Sidebar.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { connect } from 'react-redux'; 3 | import * as actions from '../actions/actions'; 4 | 5 | const mapDispatchToProps = (dispatch) => ({ 6 | getResults: (location, radius, categories) => { 7 | dispatch(actions.getResults(location, radius, categories)); 8 | } 9 | }); 10 | 11 | const Sidebar = (props) => { 12 | const handleClick = (e) => { 13 | e.preventDefault(); 14 | const location = document.querySelector('input[name="location"]').value; 15 | const radius = document.querySelector('select[name="radius"]').value; 16 | const checkboxes = document.querySelectorAll('input[type=checkbox]:checked'); 17 | let categories = ''; 18 | checkboxes.forEach((el) => categories += ',' + el.name); 19 | categories = categories.slice(1); 20 | props.getResults(location, radius, categories); 21 | } 22 | // onSubmit={() => {return false}} 23 | return ( 24 | 93 | ) 94 | }; 95 | 96 | export default connect(null, mapDispatchToProps)(Sidebar); -------------------------------------------------------------------------------- /client/style.scss: -------------------------------------------------------------------------------- 1 | $teal: #22B3A6; 2 | $gold: #f0c25f; 3 | $white: #FFFCF5; 4 | $gray: #D0D7DD; 5 | $black: #2A343A; 6 | $shadow: rgb(42, 52, 58, .10); 7 | 8 | html, body { 9 | width: 100%; 10 | height: 100%; 11 | margin: 0; 12 | overflow-x: hidden; 13 | max-height:100vh; 14 | color: $black; 15 | font-family: 'Roboto', sans-serif; 16 | background-color: $white; 17 | } 18 | 19 | h1 { 20 | color: $white; 21 | background-color: $black; 22 | font-size: 48px; 23 | text-align: center; 24 | padding: 75px 50px; 25 | } 26 | 27 | h2 { 28 | color: $white; 29 | background-color: $black; 30 | text-align: center; 31 | padding: 75px 50px; 32 | line-height: 35px; 33 | } 34 | 35 | .result-word { 36 | align-items: left; 37 | } 38 | 39 | p { 40 | color: $black; 41 | margin: 5px 0; 42 | } 43 | 44 | #nav { 45 | width: 100%; 46 | height: 75px; 47 | color: $white; 48 | background-color: $teal; 49 | display: flex; 50 | align-items: center; 51 | justify-content: space-between; 52 | position: fixed; 53 | box-shadow: -2px 3px 3px 2px $shadow; 54 | z-index: 2; 55 | } 56 | 57 | #logo { 58 | margin-top: 4px; 59 | margin-left: 40.2px; 60 | width: auto; 61 | height: 52.5px; 62 | } 63 | 64 | #profile-icon { 65 | margin-top: 4px; 66 | margin-right: 32px; 67 | width: 45px; 68 | height: 45px; 69 | border-radius: 50%; 70 | color: $white; 71 | background-color: $white; 72 | border: 1px solid $white; 73 | z-index: auto; 74 | box-shadow: -.5px 1.5px 2px 2px $shadow; 75 | } 76 | 77 | button { 78 | z-index: auto; 79 | } 80 | 81 | button:hover { 82 | cursor: pointer; 83 | } 84 | 85 | a { 86 | z-index: auto; 87 | } 88 | 89 | a:hover { 90 | cursor: pointer; 91 | } 92 | 93 | #main-container { 94 | height: 100%; 95 | } 96 | 97 | aside { 98 | position: fixed; 99 | margin-top: 75px; 100 | padding: 40px; 101 | height: 100%; 102 | background-color:#FFFCF5; 103 | display: flex; 104 | align-items: flex-start; 105 | } 106 | 107 | .side-header { 108 | font-weight: 500; 109 | font-size: 1rem; 110 | margin-bottom: 10px; 111 | } 112 | 113 | input[type=text], select[name=radius] { 114 | width: 90%; 115 | padding: 12px 10px; 116 | margin: 10px 0 20px; 117 | border: 1px solid $black; 118 | color: $black; 119 | border-radius: 5px; 120 | color: $black; 121 | font-size: 14px; 122 | } 123 | 124 | select[name=radius] { 125 | width: 97%; 126 | padding: 11px 10px; 127 | font-size: 14px; 128 | } 129 | 130 | input[type=checkbox]{ 131 | width: 30px; 132 | height: 30px; 133 | vertical-align: middle; 134 | margin-right: 10px; 135 | } 136 | 137 | .checkbox { 138 | display: flex; 139 | align-items: center; 140 | margin: 5px 0; 141 | 142 | .checkbox label { 143 | padding-left: 5px; 144 | font-size: 14px; 145 | } 146 | } 147 | 148 | .checkboxes { 149 | display: grid; 150 | grid-template-columns: 1fr 1fr; 151 | } 152 | 153 | #search { 154 | background-color: $gold; 155 | color: $black; 156 | font-weight: bold; 157 | font-size: 16px; 158 | border: 1px solid $gold; 159 | border-radius: 5px; 160 | width: 100%; 161 | height: 45px; 162 | z-index: 1; 163 | box-shadow: 0px 2px 2px $shadow; 164 | margin: 30px 0 0; 165 | } 166 | 167 | #results-container { 168 | margin-left: 385px; 169 | display: flex; 170 | flex-direction: column; 171 | flex-basis: 300px; 172 | width: auto; 173 | padding: 93px 40px 40px 40px; 174 | } 175 | 176 | #splash { 177 | margin-left: 385px; 178 | display: flex; 179 | flex-direction: column; 180 | align-content: center; 181 | justify-content: center; 182 | align-items: center; 183 | background: url("./assets/background.gif") $gold repeat center; 184 | height: 100vh; 185 | padding: 40px; 186 | } 187 | 188 | article { 189 | display: flex; 190 | justify-content: start; 191 | margin-bottom: 20px; 192 | width: 100%; 193 | } 194 | 195 | .business { 196 | display: flex; 197 | flex-direction: row; 198 | align-self: stretch; 199 | justify-content: flex-end; 200 | width: 100%; 201 | min-width: 500px; 202 | border: 1px solid $shadow; 203 | box-shadow: 0 2px 5px 2px $shadow; 204 | } 205 | 206 | .businessImg { 207 | width: 200px; 208 | height: 200px; 209 | object-fit: cover; 210 | flex-shrink: 0; 211 | } 212 | 213 | .businessDetails { 214 | display: flex; 215 | flex-direction: column; 216 | justify-content: center; 217 | width: 100%; 218 | padding: 12px 20px 12px 22px; 219 | } 220 | 221 | .buttonContainer { 222 | display: flex; 223 | flex-direction: column; 224 | margin-left: 10px; 225 | vertical-align: middle; 226 | } 227 | 228 | .addFav { 229 | background-color: $teal; 230 | color:$white; 231 | border-radius: 5px; 232 | border: 1px solid $teal; 233 | width: 125px; 234 | padding: 10px; 235 | margin: 0 0 10px; 236 | box-shadow: 0px 2px 2px $shadow; 237 | } 238 | 239 | .comment { 240 | background-color: $gold; 241 | border: 1px solid $gold; 242 | color: $black; 243 | border-radius: 5px; 244 | width: 125px; 245 | padding: 10px; 246 | box-shadow: 0px 2px 2px $shadow; 247 | } 248 | 249 | .share { 250 | background-color: $gold; 251 | border: 1px solid $gold; 252 | color: $black; 253 | border-radius: 5px; 254 | width: 125px; 255 | padding: 10px; 256 | margin: 10px 0 0; 257 | box-shadow: 0px 2px 2px $shadow; 258 | } 259 | 260 | .name { 261 | color: $teal; 262 | font-size: 20px; 263 | font-weight: bold; 264 | text-decoration: none; 265 | } 266 | 267 | .name:hover { 268 | color: $gold; 269 | text-decoration: underline; 270 | } 271 | 272 | .distance { 273 | padding-top: 8px; 274 | margin: 0; 275 | color: $black; 276 | font-size: 14px; 277 | } 278 | 279 | .rating { 280 | color: $black; 281 | margin-left: 5px; 282 | font-weight: 700; 283 | font-size: 14px; 284 | } 285 | 286 | .price { 287 | color: $black; 288 | margin-left: 0; 289 | padding-right: 2px; 290 | font-weight: 700; 291 | font-size: 14px; 292 | } 293 | 294 | .Address { 295 | margin: 5px 0 0 0; 296 | } 297 | 298 | .phone { 299 | margin-top: 4px; 300 | } 301 | 302 | .add-comment { 303 | padding: 12px 0 0 1px; 304 | margin: 0; 305 | color: $teal; 306 | align-self: flex-start; 307 | background: none; 308 | border: none; 309 | } 310 | 311 | .add-comment:hover { 312 | color: $gold; 313 | } 314 | 315 | @media screen and (max-width: 1060px) and (min-width: 500px) { 316 | #main-container { 317 | display: flex; 318 | flex-direction: column; 319 | justify-content: start; 320 | width: 100%; 321 | height: 100vh; 322 | } 323 | 324 | #results-container { 325 | margin-left: 0; 326 | display: flex; 327 | flex-direction: column; 328 | width: auto; 329 | padding: 40px 40px 40px 40px; 330 | } 331 | 332 | #splash { 333 | margin-left: 0; 334 | display: flex; 335 | flex-direction: column; 336 | align-content: center; 337 | justify-content: center; 338 | align-items: center; 339 | padding: 40px; 340 | } 341 | 342 | aside { 343 | position: relative; 344 | padding: 40px 0; 345 | width: 100%; 346 | justify-content: center; 347 | } 348 | 349 | aside > * { 350 | padding: 0 40px; 351 | } 352 | 353 | form { 354 | display: grid; 355 | grid-template-columns: 1fr 1fr; 356 | grid-template-areas: 357 | "left right" 358 | "bottom right"; 359 | gap: 20px; 360 | } 361 | 362 | .filters { 363 | grid-area: right; 364 | } 365 | 366 | .checkboxes { 367 | margin-top: 20px; 368 | } 369 | 370 | .location-and-radius { 371 | grid-area: left; 372 | } 373 | 374 | #search { 375 | grid-area: bottom; 376 | width: 97%; 377 | padding: 0; 378 | margin-top: -5px; 379 | } 380 | 381 | .side-header { 382 | margin-top: 0; 383 | } 384 | 385 | } 386 | 387 | @media screen and (max-width: 500px) { 388 | #main-container { 389 | display: flex; 390 | flex-direction: column; 391 | justify-content: start; 392 | } 393 | 394 | #results-container { 395 | margin-left: 0; 396 | display: flex; 397 | flex-direction: column; 398 | width: auto; 399 | padding: 40px; 400 | } 401 | 402 | #splash { 403 | margin-left: 0; 404 | display: flex; 405 | flex-direction: column; 406 | align-content: center; 407 | justify-content: center; 408 | align-items: center; 409 | padding: 40px; 410 | } 411 | 412 | aside { 413 | position: relative; 414 | padding: 40px; 415 | width: auto; 416 | height: 100%; 417 | justify-content: center; 418 | } 419 | 420 | aside > * { 421 | padding: 0 20px; 422 | } 423 | 424 | form { 425 | display: block; 426 | } 427 | 428 | #search { 429 | margin-top: 30px; 430 | } 431 | 432 | article { 433 | display: flex; 434 | flex-direction: column; 435 | justify-content: start; 436 | margin-bottom: 20px; 437 | width: 100%; 438 | } 439 | 440 | .business { 441 | display: flex; 442 | flex-direction: column; 443 | width: 100%; 444 | min-width: 300px; 445 | box-shadow: -2px 5px 5px 2px $shadow; 446 | } 447 | 448 | .businessImg { 449 | width: auto; 450 | object-fit: cover; 451 | } 452 | 453 | .businessDetails { 454 | // display: flex; 455 | // flex-direction: column; 456 | // justify-content: center; 457 | // border: 1px solid $shadow; 458 | // width: auto; 459 | // height: auto; 460 | // padding: 20px; 461 | // box-shadow: 0px 2px 2px $shadow; 462 | } 463 | 464 | .buttonContainer { 465 | display: flex; 466 | flex-direction: row; 467 | margin-left: 0; 468 | align-items: center; 469 | justify-content: center; 470 | min-width: 300px; 471 | } 472 | 473 | .addFav { 474 | background-color: $teal; 475 | color:$white; 476 | border-radius: 5px; 477 | border: 1px solid $teal; 478 | width: 125px; 479 | padding: 10px; 480 | margin: 10px 5px; 481 | box-shadow: 0px 2px 2px $shadow; 482 | } 483 | 484 | .comment { 485 | background-color: $gold; 486 | border: 1px solid $gold; 487 | color: $black; 488 | border-radius: 5px; 489 | width: 125px; 490 | padding: 10px; 491 | margin: 10px 5px; 492 | box-shadow: 0px 2px 2px $shadow; 493 | } 494 | 495 | .share { 496 | background-color: $gold; 497 | border: 1px solid $gold; 498 | color: $black; 499 | border-radius: 5px; 500 | width: 125px; 501 | padding: 10px; 502 | margin: 10px 5px; 503 | box-shadow: 0px 2px 2px $shadow; 504 | } 505 | } --------------------------------------------------------------------------------