From 38db70476872f0e6b8d93aab16dc5a4543f5e56c Mon Sep 17 00:00:00 2001
From: JeremyJamesL <jeremyluscombe@gmail.com>
Date: Mon, 9 Dec 2024 21:41:49 +0000
Subject: text search

---
 src/refactor.js | 237 +++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 140 insertions(+), 97 deletions(-)

(limited to 'src/refactor.js')

diff --git a/src/refactor.js b/src/refactor.js
index 9374402..d4e50a7 100644
--- a/src/refactor.js
+++ b/src/refactor.js
@@ -1,19 +1,20 @@
-import { algoliasearch } from "algoliasearch";
-const ALGOLIA_KEY = "9fb3db0222f7b5aef0e2b30791ee6201";
-const INDEX_NAME = "pubfinder";
-const client = algoliasearch("YSWWVAX5RB", ALGOLIA_KEY);
+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 londonBounds = {
-    north: 51.532,
-    south: 51.478,
-    east: -0.072,
-    west: -0.16,
+  const initialRectBounds = {
+    north: 51.525241,
+    south: 51.488855,
+    east: -0.09138,
+    west: -0.122212,
   };
+
   const maxMapSpace = {
     north: 51.74,
     south: 51.27,
@@ -32,13 +33,13 @@ const dataController = (function () {
   const centralPosition = { lat: 51.508616, lng: -0.125319 };
 
   return {
-    londonBounds,
+    initialRectBounds,
     centralPosition,
     maxMapSpace,
     initialPolygonBounds,
-    getSearchResults: async function (shape, bounds) {
+    getSearchResults: async function (query = '', shape = '', bounds = []) {
       let geoParam;
-      if (shape === "rectangle") {
+      if (shape === 'rectangle') {
         geoParam = {
           insideBoundingBox: [bounds],
         };
@@ -51,13 +52,17 @@ const dataController = (function () {
       const res = await client.searchSingleIndex({
         indexName: INDEX_NAME,
         searchParams: {
+          query,
           ...algolia_params,
           ...geoParam,
-          attributesToRetrieve: ["_geoloc", "name"],
+          attributesToRetrieve: ['_geoloc', 'name'],
         },
       });
       return res;
     },
+    getCurrentQuery: function () {
+      return document.querySelector('#searchbar').value;
+    },
   };
 })();
 
@@ -66,28 +71,26 @@ const interfaceController = (function () {
   let shape;
   let map;
   const DOMStrings = {
-    selectRect: ".select--rectangle",
-    selectPoly: ".select--polygon",
+    selectRect: '.select--rectangle',
+    selectPoly: '.select--polygon',
+    ip: '.select--ip',
+    hits: '#hits',
+    searchBar: '#searchbar',
   };
 
-  const generateMap = async function (
-    bounds,
-    position,
-    maxSpace,
-    initialPolygonBounds,
-    currentShape
-  ) {
-    const { Map, Polygon, Rectangle } = await google.maps.importLibrary("maps");
-    map = new Map(document.getElementById("map"), {
-      zoom: 4,
+  const generateMap = async function (bounds, position, maxSpace, initialPolygonBounds, currentShape) {
+    const { Map, Polygon, Rectangle } = await google.maps.importLibrary('maps');
+    map = new Map(document.getElementById('map'), {
+      zoom: 9,
       center: position,
-      mapId: "pub_map",
+      mapId: 'pub_map',
       restriction: {
         latLngBounds: maxSpace,
         strictBounds: true,
       },
     });
-    if (currentShape === "rectangle") {
+
+    if (currentShape === 'rectangle') {
       shape = new Rectangle({
         bounds: bounds,
         editable: true,
@@ -96,10 +99,10 @@ const interfaceController = (function () {
     } else {
       shape = new Polygon({
         paths: initialPolygonBounds,
-        strokeColor: "#FF0000",
+        strokeColor: '#FF0000',
         strokeOpacity: 0.8,
         strokeWeight: 2,
-        fillColor: "#FF0000",
+        fillColor: '#FF0000',
         fillOpacity: 0.35,
         editable: true,
         draggable: true,
@@ -113,10 +116,8 @@ const interfaceController = (function () {
     handleShapeSelect: function (e) {},
     initMap: generateMap,
     embedSearchResults: async function (hits) {
-      const { AdvancedMarkerElement } = await google.maps.importLibrary(
-        "marker"
-      );
-      const { InfoWindow } = await google.maps.importLibrary("maps");
+      const { AdvancedMarkerElement } = await google.maps.importLibrary('marker');
+      const { InfoWindow } = await google.maps.importLibrary('maps');
 
       hits.forEach((hit) => {
         const marker = new AdvancedMarkerElement({
@@ -131,7 +132,7 @@ const interfaceController = (function () {
           content: hit.name,
         });
 
-        marker.addListener("click", function () {
+        marker.addListener('click', function () {
           window.open({
             anchor: marker,
             map,
@@ -141,6 +142,18 @@ const interfaceController = (function () {
         markers.push(marker);
       });
     },
+    updateHitsList: function (hits) {
+      const slicedArr = hits.slice(0, 20);
+      $(DOMStrings.hits).innerHTML = '';
+      let html = `<ul class="flex flex-col gap-2">`;
+
+      for (const pub of slicedArr) {
+        html += `<li>${pub.name}</li>`;
+      }
+      html += `</ul>`;
+
+      $(DOMStrings.hits).insertAdjacentHTML('beforeend', html);
+    },
     handleBoundChange: function () {
       const { south, west, north, east } = shape.getBounds()?.toJSON();
       return [north, east, south, west];
@@ -148,6 +161,24 @@ const interfaceController = (function () {
     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);
@@ -161,109 +192,121 @@ const interfaceController = (function () {
 
 const controller = (function (dataCTRL, uiCTRL) {
   const DOM = uiCTRL.getDOMStrings();
-  const londonBounds = dataCTRL.londonBounds;
+  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(
-      londonBounds,
-      centralPoint,
-      mapBounds,
-      initialPolygonBounds,
-      "rectangle"
-    );
-
-    const searchResults = await dataCTRL.getSearchResults("rectangle", [
-      londonBounds.north,
-      londonBounds.east,
-      londonBounds.south,
-      londonBounds.west,
+    await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'rectangle');
+
+    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) {
-      shape.addListener("dragend", async () => {
+      let debounceTimer;
+
+      shape.addListener('bounds_changed', () => {
         uiCTRL.removeMarkers();
-        const newAlgoliaBounds = uiCTRL.handleBoundChange();
+        clearTimeout(debounceTimer);
 
-        const searchResults = await dataCTRL.getSearchResults(
-          "rectangle",
-          newAlgoliaBounds
-        );
-        await uiCTRL.embedSearchResults(searchResults.hits);
+        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();
-      let points = [];
 
       const handlePathDrag = async function () {
         uiCTRL.removeMarkers();
-        points = [];
-        paths.forEach((path) => {
-          path.forEach((latLng) => {
-            const lat = latLng.lat();
-            const lng = latLng.lng();
-            points.push(lat, lng);
-          });
-        });
-        const searchResults = await dataCTRL.getSearchResults(
-          "polygon",
-          points
-        );
-        await uiCTRL.embedSearchResults(searchResults.hits);
+        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);
+        path.addListener('set_at', handlePathDrag);
+        path.addListener('insert_at', handlePathDrag);
       });
     }
   };
 
   const setupShapeSelectListeners = async function () {
-    $(DOM.selectRect).addEventListener("click", async () => {
-      await uiCTRL.initMap(
-        londonBounds,
-        centralPoint,
-        mapBounds,
-        initialPolygonBounds,
-        "rectangle"
-      );
-      const searchResults = await dataCTRL.getSearchResults("rectangle", [
-        londonBounds.north,
-        londonBounds.east,
-        londonBounds.south,
-        londonBounds.west,
+    $(DOM.selectRect).addEventListener('click', async () => {
+      await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'rectangle');
+      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(
-        londonBounds,
-        centralPoint,
-        mapBounds,
-        initialPolygonBounds,
-        "polygon"
-      );
-      const translatedPolyBounds = initialPolygonBounds.flatMap(
-        ({ lat, lng }) => [lat, lng]
-      );
+
+    $(DOM.selectPoly).addEventListener('click', async () => {
+      await uiCTRL.initMap(rectBounds, centralPoint, mapBounds, initialPolygonBounds, 'polygon');
+      const translatedPolyBounds = initialPolygonBounds.flatMap(({ lat, lng }) => [lat, lng]);
       const searchResults = await dataCTRL.getSearchResults(
-        "polygon",
+        dataCTRL.getCurrentQuery(),
+        'polygon',
         translatedPolyBounds
       );
       await uiCTRL.embedSearchResults(searchResults.hits);
+      uiCTRL.updateHitsList(searchResults.hits);
       await setupMapListeners();
     });
+
+    $(DOM.ip).addEventListener('click', async () => {
+      const res = await client.searchSingleIndex({
+        indexName: INDEX_NAME,
+        searchParams: {
+          aroundLatLngViaIP: true,
+          aroundRadius: 1000,
+        },
+      });
+      console.log(res);
+    }),
+      $(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 {
-- 
cgit v1.2.3