From 084d8e2dc5a18a445f05aca4d75d7a8eb6b6b437 Mon Sep 17 00:00:00 2001 From: JeremyJamesL <jeremyluscombe@gmail.com> Date: Tue, 17 Dec 2024 19:16:09 +0000 Subject: prod --- src/index.css | 24 +--- src/main.js | 355 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/refactor.js | 353 ------------------------------------------------------- 3 files changed, 356 insertions(+), 376 deletions(-) create mode 100644 src/main.js delete mode 100644 src/refactor.js (limited to 'src') diff --git a/src/index.css b/src/index.css index 8f861f0..57ac450 100644 --- a/src/index.css +++ b/src/index.css @@ -10,7 +10,7 @@ #map { height: 100%; - height: 100dvh; + height: calc(100dvh - (64px + 288px)); width: 100%; } @@ -84,25 +84,3 @@ body { stroke-miterlimit: 10; stroke-dasharray: 4, 3; } - -/* header { - background: rgb(38, 38, 38); - background: linear-gradient( - 180deg, - rgba(38, 38, 38, 1) 0%, - rgba(38, 38, 38, 0.7665660014005602) 51%, - rgba(38, 38, 38, 0) 100% - ); -} */ - -/* body { - color: #646c78; - background-color: #222e3e; -} */ -/* -.container { - max-width: 1200px; - margin: 0 auto; - padding-left: 15px; - padding-right: 15px; -} */ diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..1466b3f --- /dev/null +++ b/src/main.js @@ -0,0 +1,355 @@ +import { algoliasearch } from 'algoliasearch'; +const ALGOLIA_KEY = '9fb3db0222f7b5aef0e2b30791ee6201'; +const INDEX_NAME = 'pubfinder'; +const client = algoliasearch('YSWWVAX5RB', ALGOLIA_KEY); +const $ = document.querySelector.bind(document); + +const dataController = (function () { + const initialRectBounds = { + north: 51.522899, + south: 51.484821, + east: -0.07766, + west: -0.138968, + }; + + const maxMapSpace = { + north: 51.74, + south: 51.27, + west: -0.51, + east: 0.23, + }; + + const initialPolygonBounds = [ + { lat: 51.522786, lng: -0.077603 }, + { lat: 51.525376, lng: -0.108023 }, + { lat: 51.520791, lng: -0.138718 }, + { lat: 51.506604, lng: -0.151214 }, + { lat: 51.485288, lng: -0.106803 }, + { lat: 51.493989, lng: -0.085187 }, + ]; + + const centralPosition = { lat: 51.508616, lng: -0.125319 }; + + return { + initialRectBounds, + centralPosition, + maxMapSpace, + initialPolygonBounds, + getSearchResults: async function (query = '', shape = '', bounds = [], hitsToGet) { + let geoParam; + if (shape === 'rectangle') { + geoParam = { + insideBoundingBox: [bounds], + }; + } else if (shape === 'polygon') { + geoParam = { + insidePolygon: [bounds], + }; + } else { + geoParam = { + aroundLatLng: bounds, + // aroundRadius: 1000, + }; + } + + const res = await client.searchSingleIndex({ + indexName: INDEX_NAME, + searchParams: { + query, + hitsPerPage: hitsToGet, + ...geoParam, + attributesToRetrieve: ['_geoloc', 'name', 'address', 'postcode'], + }, + }); + return res; + }, + getCurrentQuery: function () { + return document.querySelector('#searchbar').value; + }, + }; +})(); + +const interfaceController = (function () { + let markers = []; + let shape; + let map; + const DOMStrings = { + selectRect: '.select--rectangle', + selectPoly: '.select--polygon', + ip: '.select--ip', + ipLoader: '.ip-loader', + hits: '#hits', + searchBar: '#searchbar', + pubCount: '.pub-count', + }; + + const generateMap = async function (bounds, position, maxSpace, initialPolygonBounds, currentShape, zoom = 12) { + const { Map, Polygon, Rectangle } = await google.maps.importLibrary('maps'); + map = new Map(document.getElementById('map'), { + zoom, + center: position, + mapId: 'pub_map', + colorScheme: 'DARK', + restriction: { + latLngBounds: maxSpace, + strictBounds: true, + }, + }); + + if (currentShape === 'rectangle') { + shape = new Rectangle({ + bounds: bounds, + editable: true, + draggable: true, + strokeWeight: 2, + strokeOpacity: 0.8, + strokeColor: '#D97706', + fillColor: '#D97706', + fillOpacity: 0.35, + }); + shape.setMap(map); + } else if (currentShape === 'polygon') { + shape = new Polygon({ + paths: initialPolygonBounds, + strokeColor: '#D97706', + strokeOpacity: 0.8, + strokeWeight: 2, + fillColor: '#D97706', + fillOpacity: 0.35, + editable: true, + draggable: true, + geodesic: true, + }); + shape.setMap(map); + } + }; + + return { + handleShapeSelect: function (e) {}, + initMap: generateMap, + embedSearchResults: async function (hits) { + const { AdvancedMarkerElement } = await google.maps.importLibrary('marker'); + const { InfoWindow } = await google.maps.importLibrary('maps'); + + hits.forEach((hit) => { + const marker = new AdvancedMarkerElement({ + map: map, + position: { + lat: hit._geoloc.lat, + lng: hit._geoloc.lng, + }, + }); + + const window = new InfoWindow({ + content: hit.name, + }); + + marker.addListener('click', function () { + window.open({ + anchor: marker, + map, + }); + }); + + markers.push(marker); + }); + }, + updateHitsList: function (hits) { + $(DOMStrings.hits).innerHTML = ''; + let html = ``; + if (hits.length > 0) { + const slicedArr = hits.slice(0, 20); + html += `<ul class="flex flex-col gap-2">`; + for (const pub of slicedArr) { + html += `<li class="relative bg-[#373737] rounded-lg p-4"> + <h3 class="font-medium mb-2">${pub.name}</h3> + <h4 class="text-sm">${pub.address}, ${pub.postcode}</h4> + <a href="https://www.google.co.uk/maps/place/Ye+Old+White+Horse/" class="absolute block top-4 right-4" target="_blank"> + <svg width="20px" height="20px" viewBox="0 0 24 24" fill="none" > + <path d="M5 12V6C5 5.44772 5.44772 5 6 5H18C18.5523 5 19 5.44772 19 6V18C19 18.5523 18.5523 19 18 19H12M8.11111 12H12M12 12V15.8889M12 12L5 19" stroke="#D97706" stroke-linecap="round" stroke-linejoin="round" /> + </svg> + </a> + </li>`; + } + html += `</ul>`; + } else { + html = `<div class="text-center mt-5">There are no results to show, try refinfing your search</div>`; + } + + $(DOMStrings.hits).insertAdjacentHTML('beforeend', html); + $(DOMStrings.pubCount).innerHTML = `${hits.length > 0 ? 'Showing ' + hits.length + ' pubs' : 'No pubs'}`; + }, + handleBoundChange: function () { + const { south, west, north, east } = shape.getBounds()?.toJSON(); + return [north, east, south, west]; + }, + getActiveShape: function () { + return shape; + }, + getShapeBounds: function () { + if (shape instanceof google.maps.Polygon) { + const paths = shape.getPaths(); + let points = []; + + paths.forEach((path) => { + path.forEach((latLng) => { + const lat = latLng.lat(); + const lng = latLng.lng(); + points.push(lat, lng); + }); + }); + return points; + } else { + const { south, west, north, east } = shape.getBounds()?.toJSON(); + return [north, east, south, west]; + } + }, + removeMarkers: function () { + for (let i = 0; i < markers.length; i++) { + markers[i].setMap(null); + } + }, + getDOMStrings: function () { + return DOMStrings; + }, + }; +})(); + +const controller = (function (dataCTRL, uiCTRL) { + const DOM = uiCTRL.getDOMStrings(); + const rectBounds = dataCTRL.initialRectBounds; + const centralPoint = dataCTRL.centralPosition; + const mapBounds = dataCTRL.maxMapSpace; // Rectangle bounds + const initialPolygonBounds = dataCTRL.initialPolygonBounds; // Polygon bounds + + const initialSetup = async function () { + await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'rectangle', 12); + + const searchResults = await dataCTRL.getSearchResults( + '', + 'rectangle', + [rectBounds.north, rectBounds.east, rectBounds.south, rectBounds.west], + 1000 + ); + await uiCTRL.embedSearchResults(searchResults.hits); + uiCTRL.updateHitsList(searchResults.hits); + }; + + const setupMapListeners = async function () { + const shape = uiCTRL.getActiveShape(); + if (shape instanceof google.maps.Rectangle) { + let debounceTimer; + + shape.addListener('bounds_changed', () => { + uiCTRL.removeMarkers(); + clearTimeout(debounceTimer); + + debounceTimer = setTimeout(async () => { + const newAlgoliaBounds = uiCTRL.handleBoundChange(); + const searchResults = await dataCTRL.getSearchResults( + dataCTRL.getCurrentQuery(), + 'rectangle', + newAlgoliaBounds, + 1000 + ); + await uiCTRL.embedSearchResults(searchResults.hits); + uiCTRL.updateHitsList(searchResults.hits); + }, 200); + }); + } + + if (shape instanceof google.maps.Polygon) { + let debounceTimer; + const paths = shape.getPaths(); + + const handlePathDrag = async function () { + uiCTRL.removeMarkers(); + clearTimeout(debounceTimer); + + debounceTimer = setTimeout(async () => { + const points = uiCTRL.getShapeBounds(); + + const searchResults = await dataCTRL.getSearchResults(dataCTRL.getCurrentQuery(), 'polygon', points, 1000); + await uiCTRL.embedSearchResults(searchResults.hits); + uiCTRL.updateHitsList(searchResults.hits); + }, 300); + }; + + paths.forEach((path) => { + path.addListener('set_at', handlePathDrag); + path.addListener('insert_at', handlePathDrag); + }); + } + }; + + const setupEventListeners = async function () { + $(DOM.selectRect).addEventListener('click', async () => { + await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'rectangle', 12); + const searchResults = await dataCTRL.getSearchResults( + dataCTRL.getCurrentQuery(), + 'rectangle', + [rectBounds.north, rectBounds.east, rectBounds.south, rectBounds.west], + 1000 + ); + await uiCTRL.embedSearchResults(searchResults.hits); + uiCTRL.updateHitsList(searchResults.hits); + await setupMapListeners(); + }); + + $(DOM.selectPoly).addEventListener('click', async () => { + await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'polygon', 12); + const translatedPolyBounds = initialPolygonBounds.flatMap(({ lat, lng }) => [lat, lng]); + const searchResults = await dataCTRL.getSearchResults( + dataCTRL.getCurrentQuery(), + 'polygon', + translatedPolyBounds, + 1000 + ); + await uiCTRL.embedSearchResults(searchResults.hits); + uiCTRL.updateHitsList(searchResults.hits); + await setupMapListeners(); + }); + + // $(DOM.ip).addEventListener('click', async () => { + // $(DOM.ipLoader).classList.replace('hidden', 'inline-flex'); + // navigator.geolocation.getCurrentPosition(async (pos) => { + // const position = { lat: pos.coords.latitude, lng: pos.coords.longitude }; + // await uiCTRL.initMap('', centralPoint, position, '', 'ip', 8); + // const searchResults = await dataCTRL.getSearchResults( + // dataCTRL.getCurrentQuery(), + // 'ip', + // `${pos.coords.latitude}, ${pos.coords.longitude}`, + // 20 + // ); + // await uiCTRL.embedSearchResults(searchResults.hits); + // uiCTRL.updateHitsList(searchResults.hits); + // $(DOM.ipLoader).classList.replace('inline-flex', 'hidden'); + // }); + // }), + $(DOM.searchBar).addEventListener('input', async (e) => { + const q = dataCTRL.getCurrentQuery(); + if (q > 0 && q < 3) return; + const bounds = uiCTRL.getShapeBounds(); + const activeShape = uiCTRL.getActiveShape(); + const searchResults = await dataCTRL.getSearchResults( + q, + activeShape instanceof google.maps.Polygon ? 'polygon' : 'rectangle', + bounds, + 1000 + ); + uiCTRL.removeMarkers(); + await uiCTRL.embedSearchResults(searchResults.hits); + uiCTRL.updateHitsList(searchResults.hits); + }); + }; + + return { + init: async function () { + await initialSetup(); + await setupMapListeners(); + await setupEventListeners(); + }, + }; +})(dataController, interfaceController); + +controller.init(); diff --git a/src/refactor.js b/src/refactor.js deleted file mode 100644 index c708bed..0000000 --- a/src/refactor.js +++ /dev/null @@ -1,353 +0,0 @@ -import { algoliasearch } from 'algoliasearch'; -const ALGOLIA_KEY = '9fb3db0222f7b5aef0e2b30791ee6201'; -const INDEX_NAME = 'pubfinder'; -const client = algoliasearch('YSWWVAX5RB', ALGOLIA_KEY); -const $ = document.querySelector.bind(document); -const algolia_params = { - hitsPerPage: 1000, -}; - -const dataController = (function () { - const initialRectBounds = { - north: 51.525241, - south: 51.488855, - east: -0.09138, - west: -0.122212, - }; - - const maxMapSpace = { - north: 51.74, - south: 51.27, - west: -0.51, - east: 0.23, - }; - - const initialPolygonBounds = [ - { lat: 51.528125, lng: -0.104853 }, - { lat: 51.519405, lng: -0.089005 }, - { lat: 51.508742, lng: -0.108198 }, - { lat: 51.507389, lng: -0.132242 }, - { lat: 51.522659, lng: -0.134998 }, - ]; - - const centralPosition = { lat: 51.508616, lng: -0.125319 }; - - return { - initialRectBounds, - centralPosition, - maxMapSpace, - initialPolygonBounds, - getSearchResults: async function (query = '', shape = '', bounds = []) { - let geoParam; - if (shape === 'rectangle') { - geoParam = { - insideBoundingBox: [bounds], - }; - } else if (shape === 'polygon') { - geoParam = { - insidePolygon: [bounds], - }; - } else { - geoParam = { - aroundLatLng: bounds, - // aroundRadius: 1000, - }; - } - - const res = await client.searchSingleIndex({ - indexName: INDEX_NAME, - searchParams: { - query, - ...algolia_params, - ...geoParam, - attributesToRetrieve: ['_geoloc', 'name', 'address', 'postcode'], - }, - }); - return res; - }, - getCurrentQuery: function () { - return document.querySelector('#searchbar').value; - }, - }; -})(); - -const interfaceController = (function () { - let markers = []; - let shape; - let map; - const DOMStrings = { - selectRect: '.select--rectangle', - selectPoly: '.select--polygon', - ip: '.select--ip', - ipLoader: '.ip-loader', - hits: '#hits', - searchBar: '#searchbar', - pubCount: '.pub-count', - }; - - const generateMap = async function (bounds, position, maxSpace, initialPolygonBounds, currentShape, zoom = 12) { - const { Map, Polygon, Rectangle } = await google.maps.importLibrary('maps'); - map = new Map(document.getElementById('map'), { - zoom, - center: position, - mapId: 'pub_map', - colorScheme: 'DARK', - restriction: { - latLngBounds: maxSpace, - strictBounds: true, - }, - }); - - if (currentShape === 'rectangle') { - shape = new Rectangle({ - bounds: bounds, - editable: true, - draggable: true, - strokeWeight: 2, - strokeOpacity: 0.8, - strokeColor: '#D97706', - fillColor: '#D97706', - fillOpacity: 0.35, - }); - shape.setMap(map); - } else if (currentShape === 'polygon') { - shape = new Polygon({ - paths: initialPolygonBounds, - strokeColor: '#D97706', - strokeOpacity: 0.8, - strokeWeight: 2, - fillColor: '#D97706', - fillOpacity: 0.35, - editable: true, - draggable: true, - geodesic: true, - }); - shape.setMap(map); - } - }; - - return { - handleShapeSelect: function (e) {}, - initMap: generateMap, - embedSearchResults: async function (hits) { - const { AdvancedMarkerElement } = await google.maps.importLibrary('marker'); - const { InfoWindow } = await google.maps.importLibrary('maps'); - - hits.forEach((hit) => { - const marker = new AdvancedMarkerElement({ - map: map, - position: { - lat: hit._geoloc.lat, - lng: hit._geoloc.lng, - }, - }); - - const window = new InfoWindow({ - content: hit.name, - }); - - marker.addListener('click', function () { - window.open({ - anchor: marker, - map, - }); - }); - - markers.push(marker); - }); - }, - updateHitsList: function (hits) { - $(DOMStrings.hits).innerHTML = ''; - let html = ``; - if (hits.length > 0) { - const slicedArr = hits.slice(0, 20); - html += `<ul class="flex flex-col gap-2">`; - for (const pub of slicedArr) { - html += `<li class="relative bg-[#373737] rounded-lg p-4"> - <h3 class="font-medium mb-2">${pub.name}</h3> - <h4 class="text-sm">${pub.address}, ${pub.postcode}</h4> - <a href="https://www.google.co.uk/maps/place/Ye+Old+White+Horse/" class="absolute block top-4 right-4" target="_blank"> - <svg width="20px" height="20px" viewBox="0 0 24 24" fill="none" > - <path d="M5 12V6C5 5.44772 5.44772 5 6 5H18C18.5523 5 19 5.44772 19 6V18C19 18.5523 18.5523 19 18 19H12M8.11111 12H12M12 12V15.8889M12 12L5 19" stroke="#D97706" stroke-linecap="round" stroke-linejoin="round" /> - </svg> - </a> - </li>`; - } - html += `</ul>`; - } else { - html = `<div class="text-center mt-5">There are no results to show, try refinfing your search</div>`; - } - - $(DOMStrings.hits).insertAdjacentHTML('beforeend', html); - $(DOMStrings.pubCount).innerHTML = `${hits.length > 0 ? 'Showing ' + hits.length + ' pubs' : 'No pubs'}`; - }, - handleBoundChange: function () { - const { south, west, north, east } = shape.getBounds()?.toJSON(); - return [north, east, south, west]; - }, - getActiveShape: function () { - return shape; - }, - getShapeBounds: function () { - if (shape instanceof google.maps.Polygon) { - const paths = shape.getPaths(); - let points = []; - - paths.forEach((path) => { - path.forEach((latLng) => { - const lat = latLng.lat(); - const lng = latLng.lng(); - points.push(lat, lng); - }); - }); - return points; - } else { - const { south, west, north, east } = shape.getBounds()?.toJSON(); - return [north, east, south, west]; - } - }, - removeMarkers: function () { - for (let i = 0; i < markers.length; i++) { - markers[i].setMap(null); - } - }, - getDOMStrings: function () { - return DOMStrings; - }, - }; -})(); - -const controller = (function (dataCTRL, uiCTRL) { - const DOM = uiCTRL.getDOMStrings(); - const rectBounds = dataCTRL.initialRectBounds; - const centralPoint = dataCTRL.centralPosition; - const mapBounds = dataCTRL.maxMapSpace; // This is rectangle bounds - const initialPolygonBounds = dataCTRL.initialPolygonBounds; // Polygon bound - - const initialSetup = async function () { - await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'rectangle', 12); - - const searchResults = await dataCTRL.getSearchResults('', 'rectangle', [ - rectBounds.north, - rectBounds.east, - rectBounds.south, - rectBounds.west, - ]); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - }; - - const setupMapListeners = async function () { - const shape = uiCTRL.getActiveShape(); - if (shape instanceof google.maps.Rectangle) { - let debounceTimer; - - shape.addListener('bounds_changed', () => { - uiCTRL.removeMarkers(); - clearTimeout(debounceTimer); - - debounceTimer = setTimeout(async () => { - const newAlgoliaBounds = uiCTRL.handleBoundChange(); - const searchResults = await dataCTRL.getSearchResults( - dataCTRL.getCurrentQuery(), - 'rectangle', - newAlgoliaBounds - ); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - }, 200); - }); - } - - if (shape instanceof google.maps.Polygon) { - let debounceTimer; - const paths = shape.getPaths(); - - const handlePathDrag = async function () { - uiCTRL.removeMarkers(); - clearTimeout(debounceTimer); - - debounceTimer = setTimeout(async () => { - const points = uiCTRL.getShapeBounds(); - - const searchResults = await dataCTRL.getSearchResults(dataCTRL.getCurrentQuery(), 'polygon', points); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - }, 300); - }; - - paths.forEach((path) => { - path.addListener('set_at', handlePathDrag); - path.addListener('insert_at', handlePathDrag); - }); - } - }; - - const setupShapeSelectListeners = async function () { - $(DOM.selectRect).addEventListener('click', async () => { - await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'rectangle', 12); - const searchResults = await dataCTRL.getSearchResults(dataCTRL.getCurrentQuery(), 'rectangle', [ - rectBounds.north, - rectBounds.east, - rectBounds.south, - rectBounds.west, - ]); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - await setupMapListeners(); - }); - - $(DOM.selectPoly).addEventListener('click', async () => { - await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'polygon', 12); - const translatedPolyBounds = initialPolygonBounds.flatMap(({ lat, lng }) => [lat, lng]); - const searchResults = await dataCTRL.getSearchResults( - dataCTRL.getCurrentQuery(), - 'polygon', - translatedPolyBounds - ); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - await setupMapListeners(); - }); - - $(DOM.ip).addEventListener('click', async () => { - $(DOM.ipLoader).classList.replace('hidden', 'inline-flex'); - navigator.geolocation.getCurrentPosition(async (pos) => { - const position = { lat: pos.coords.latitude, lng: pos.coords.longitude }; - await uiCTRL.initMap('', position, rectBounds, '', 'ip', 10); - const searchResults = await dataCTRL.getSearchResults( - dataCTRL.getCurrentQuery(), - 'ip', - `${pos.coords.latitude}, ${pos.coords.longitude}` - ); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - $(DOM.ipLoader).classList.replace('inline-flex', 'hidden'); - }); - }), - $(DOM.searchBar).addEventListener('input', async (e) => { - const q = dataCTRL.getCurrentQuery(); - if (q > 0 && q < 3) return; - const bounds = uiCTRL.getShapeBounds(); - const activeShape = uiCTRL.getActiveShape(); - const searchResults = await dataCTRL.getSearchResults( - q, - activeShape instanceof google.maps.Polygon ? 'polygon' : 'rectangle', - bounds - ); - uiCTRL.removeMarkers(); - await uiCTRL.embedSearchResults(searchResults.hits); - uiCTRL.updateHitsList(searchResults.hits); - }); - }; - - return { - init: async function () { - await initialSetup(); - await setupMapListeners(); - await setupShapeSelectListeners(); - }, - }; -})(dataController, interfaceController); - -controller.init(); -- cgit v1.2.3