Skip to content

Commit

Permalink
Implemented the initial version of the map needed to specify the loca…
Browse files Browse the repository at this point in the history
…tion of an event
  • Loading branch information
berkaydoner committed Dec 7, 2021
1 parent eda5bcb commit 8209458
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 11 deletions.
5 changes: 5 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"@babel/preset-env": "^7.16.0",
"@babel/runtime": "^7.16.0",
"babel-loader": "^8.2.3",
"css-loader": "^6.5.1",
"html-webpack-plugin": "^5.5.0",
"style-loader": "^3.3.1",
"webpack": "^5.62.1",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
Expand All @@ -27,16 +29,19 @@
"@date-io/date-fns": "^1.3.13",
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@material-ui/core": "^4.12.3",
"@material-ui/icons": "^4.11.2",
"@mui/icons-material": "^5.1.0",
"@mui/lab": "^5.0.0-alpha.54",
"@mui/material": "^5.0.6",
"@mui/styles": "^5.1.0",
"date-fns": "^2.25.0",
"joi": "^17.4.2",
"leaflet": "^1.7.1",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-leaflet": "^3.1.0",
"react-router-dom": "^6.0.1",
"url-loader": "^4.1.1"
}
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/Controllers/GeocodingController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export async function getLocationMatches(query){
return await fetch("https://nominatim.openstreetmap.org/search?q="+query+"&limit=5&format=json")
.then(response=>response.json())
.then(r=>r.map(d=>({lat:d.lat,lng:d.lon,name:d.display_name})))

}
43 changes: 34 additions & 9 deletions frontend/src/Views/Create Event/CreateEventPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import * as React from "react";
import Button from "@mui/material/Button";
import {Grid, Paper, TextField, Typography, Box, SvgIcon, Container, Divider} from "@mui/material";
import {
Grid,
Paper,
TextField,
Typography,
Box,
SvgIcon,
Container,
Divider,
Dialog,
DialogContent, DialogTitle
} from "@mui/material";
import {makeStyles, createStyles} from '@mui/styles'
import {Link} from 'react-router-dom'
import Joi from 'joi'
Expand All @@ -11,6 +22,8 @@ import DatePicker from '@mui/lab/DatePicker'
import {Autocomplete} from "@mui/lab";
import {useEffect, useState} from "react";
import {getSportsList} from "../../Controllers/SportsController";
import {getLocationMatches} from "../../Controllers/GeocodingController";
import MapWithMarker from "./MapWithMarker";

const initialState = {
title: {
Expand All @@ -23,11 +36,6 @@ const initialState = {
changed: false,
error: undefined
},
location: {
value: "",
changed: false,
error: undefined
},
minAge: {
value: 18,
changed: false,
Expand Down Expand Up @@ -67,6 +75,14 @@ export default function CreateEventPage(props){
const skillOptions = [{label: "Beginner"},{label: "Preintermediate"},{label: "Intermediate"},
{label: "Advanced"},{label: "Expert"}]
const [inputs, setInputs] = useState(initialState)
const [locationOpen, setLocationOpen] = React.useState(false);
const handleClickOpen = () => {
setLocationOpen(true);
};

const handleClose = () => {
setLocationOpen(false);
};
const getValue = inputs => ({
title: inputs.title.value,
description: inputs.description.value,
Expand Down Expand Up @@ -106,9 +122,11 @@ export default function CreateEventPage(props){
const handleEndChange = (newValue) => {
setTimeEnd(newValue);
}

function createEvent(){

}

return(
<Container component="main" maxWidth="md">
<Paper elevation={8} style={paperStyle}>
Expand Down Expand Up @@ -141,9 +159,16 @@ export default function CreateEventPage(props){

</Grid>
<Grid item xs={12} sm={6}>
<TextField id="location" fullWidth required label="Event Location" size="small" variant="outlined" style={textFieldStyle}
value={inputs.location.value||""} onChange={handleChange} InputProps={inputStyle}></TextField>
</Grid>
<Button variant="outlined" onClick={handleClickOpen}>
Select location
</Button>
<Dialog open={locationOpen} onClose={handleClose} fullWidth maxWidth="md">
<DialogTitle>Select location from map</DialogTitle>
<DialogContent>
<MapWithMarker/>
</DialogContent>
</Dialog>
</Grid>
</Grid>
<Grid container spacing={1}>
<Grid item xs={12} sm={4}>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/Views/Create Event/Index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import CreateEventPage from "./CreateEventPage";
import 'leaflet/dist/leaflet.css'

const CreateEvent = () => {
return (
Expand Down
95 changes: 95 additions & 0 deletions frontend/src/Views/Create Event/MapWithMarker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import 'leaflet/dist/leaflet.css';
import {MapContainer, TileLayer, Marker, Popup, useMap} from 'react-leaflet';
import * as React from "react";
import {useMemo, useRef, useState} from "react";
import "leaflet/dist/images/marker-shadow.png";
import "leaflet/dist/images/marker-icon-2x.png";
import L from 'leaflet';
import icon from 'leaflet/dist/images/marker-icon.png';
import iconShadow from 'leaflet/dist/images/marker-shadow.png';
import {Autocomplete} from "@mui/lab";
import {TextField} from "@mui/material";
import {getLocationMatches} from "../../Controllers/GeocodingController";

export default function MapWithMarker() {
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow
});
L.Marker.prototype.options.icon = DefaultIcon;
const centerValue = {
lat:41.0082,
lng:28.9784
}
const [location, setLocation] = useState(null);
const [locationText, setLocationText] = useState("");
const [locations, setLocations] = React.useState([{}]);
const [position, setPosition] = useState(centerValue);
const markerRef = useRef(null);
const eventHandlers = useMemo(
() => ({
dragend() {
const marker = markerRef.current
if (marker != null) {
setPosition(marker.getLatLng())
}
},
}),
[],
)

function SetViewOnClick({ coords }) {
const map = useMap();
map.setView(coords, map.getZoom());
console.log(position)
return null;
}
const handleLocationSearch = (event,inputQuery) => {
setLocationText(inputQuery)
if(inputQuery&&inputQuery.length>=3){
getLocationMatches(inputQuery).then(results=> {
setLocations(results)
}
)
}
else{
setLocations([])
}
}
const selectLocation = (input) => {
let coords = {lat:input.lat, lng:input.lng}
setPosition(coords)
}
return (
<div>
<Autocomplete
value={location}
inputValue={locationText}
options={locations}
getOptionLabel={d=>d.name ||""}
filterOptions={(x)=>x}
onChange={(event, value) =>value ? selectLocation(value) : selectLocation(event.target.value)}
onInputChange={handleLocationSearch}
renderInput={params => {
return (
<TextField {...params} id="location" fullWidth label="Event Location" placeholder="Search for city, district, street..." size="small" variant="outlined"
style={{marginTop: 10, marginBottom: 10}} value={locationText|""}></TextField>
)}} />
<div id="map">
<MapContainer style={{width: "100%", height: "70vh"}} center={centerValue} zoom={13}
scrollWheelZoom={false} attributionControl={false}>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker
position={position}
draggable={"true"}
ref={markerRef}
eventHandlers={eventHandlers}>
<SetViewOnClick coords={position}/>
</Marker>
</MapContainer>
</div>
</div>);
}
7 changes: 5 additions & 2 deletions frontend/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ module.exports = {
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
options: { presets: ['@babel/env','@babel/preset-react'] },
options: { presets: ['@babel/env','@babel/preset-react'] }
},

{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},

{
test: /\.css$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }],
},
],
},
resolve: {
Expand Down

0 comments on commit 8209458

Please sign in to comment.