From 6a415ec165450840b2d251161d494ea926bd86f2 Mon Sep 17 00:00:00 2001 From: C4rnivore Date: Wed, 23 Jul 2025 17:57:58 +0500 Subject: [PATCH] Google map with custom markers --- .env | 3 +- bun.lock | 18 ++++ package.json | 2 + .../images/map/markers/points/shop-point.svg | 4 + src/components/AboutMarasiDrive.tsx | 42 +++++---- src/components/GoogleMap.tsx | 88 +++++++++++++++++++ src/components/ui/MapMarker.tsx | 21 +++++ src/data/mapMarasiDrive.ts | 5 ++ src/main.tsx | 15 ++-- src/types/IGMapPoi.ts | 4 + 10 files changed, 180 insertions(+), 22 deletions(-) create mode 100644 public/images/map/markers/points/shop-point.svg create mode 100644 src/components/GoogleMap.tsx create mode 100644 src/components/ui/MapMarker.tsx create mode 100644 src/data/mapMarasiDrive.ts create mode 100644 src/types/IGMapPoi.ts diff --git a/.env b/.env index 67c1687..43c3d48 100644 --- a/.env +++ b/.env @@ -2,4 +2,5 @@ # VITE_API_URL=http://192.168.1.144:4002 # VITE_API_URL=http://194.26.138.94:4002 # VITE_API_URL=https://irthtest.online/api -VITE_API_URL=https://irth.graff.estate/api \ No newline at end of file +VITE_API_URL=https://irth.graff.estate/api +GOOGLE_MAP_API_KEY=AIzaSyD1aCnh8qEIh9ACrZWeHddYJLyHMX4KsoE \ No newline at end of file diff --git a/bun.lock b/bun.lock index 53844cc..5f7b2c7 100644 --- a/bun.lock +++ b/bun.lock @@ -4,11 +4,13 @@ "": { "name": "irth-new", "dependencies": { + "@googlemaps/markerclusterer": "^2.6.2", "@tailwindcss/vite": "^4.1.3", "@tanstack/react-query": "^5.74.4", "@tanstack/react-query-devtools": "^5.74.7", "@tweenjs/tween.js": "^25.0.0", "@uidotdev/usehooks": "^2.4.1", + "@vis.gl/react-google-maps": "^1.5.4", "clsx": "^2.1.1", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", @@ -111,6 +113,8 @@ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.8", "", { "dependencies": { "@eslint/core": "^0.13.0", "levn": "^0.4.1" } }, "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA=="], + "@googlemaps/markerclusterer": ["@googlemaps/markerclusterer@2.6.2", "", { "dependencies": { "@types/supercluster": "^7.1.3", "fast-equals": "^5.2.2", "supercluster": "^8.0.1" } }, "sha512-U6uVhq8iWhiIckA89sgRu8OK35mjd6/3CuoZKWakKEf0QmRRWpatlsPb3kqXkoWSmbcZkopRiI4dnW6DQSd7bQ=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], @@ -237,6 +241,10 @@ "@types/estree": ["@types/estree@1.0.7", "", {}, "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="], + "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], + + "@types/google.maps": ["@types/google.maps@3.58.1", "", {}, "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ=="], + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/node": ["@types/node@22.14.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA=="], @@ -245,6 +253,8 @@ "@types/react-dom": ["@types/react-dom@19.1.1", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-jFf/woGTVTjUJsl2O7hcopJ1r0upqoq/vIOoCj0yLh3RIXxWcljlpuZ+vEBRXsymD1jhfeJrlyTy/S1UW+4y1w=="], + "@types/supercluster": ["@types/supercluster@7.1.3", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.29.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.29.0", "@typescript-eslint/type-utils": "8.29.0", "@typescript-eslint/utils": "8.29.0", "@typescript-eslint/visitor-keys": "8.29.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^2.0.1" }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ=="], @@ -265,6 +275,8 @@ "@uidotdev/usehooks": ["@uidotdev/usehooks@2.4.1", "", { "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg=="], + "@vis.gl/react-google-maps": ["@vis.gl/react-google-maps@1.5.4", "", { "dependencies": { "@types/google.maps": "^3.54.10", "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "react": ">=16.8.0 || ^19.0 || ^19.0.0-rc", "react-dom": ">=16.8.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-pD3e2wDtOfd439mamkacRgrM6I2B/lue61QCR0pGQT8MVaG9pz9/LajHbsjZW2lms8Ao8mf2PQJeiGC2FxI0Fw=="], + "@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@3.8.1", "", { "dependencies": { "@swc/core": "^1.11.11" }, "peerDependencies": { "vite": "^4 || ^5 || ^6" } }, "sha512-aEUPCckHDcFyxpwFm0AIkbtv6PpUp3xTb9wYGFjtABynXjCYKkWoxX0AOK9NT9XCrdk6mBBUOeHQS+RKdcNO1A=="], "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], @@ -343,6 +355,8 @@ "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + "fast-equals": ["fast-equals@5.2.2", "", {}, "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw=="], + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], @@ -403,6 +417,8 @@ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "kdbush": ["kdbush@4.0.2", "", {}, "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "ky": ["ky@1.8.1", "", {}, "sha512-7Bp3TpsE+L+TARSnnDpk3xg8Idi8RwSLdj6CMbNWoOARIrGrbuLGusV0dYwbZOm4bB3jHNxSw8Wk/ByDqJEnDw=="], @@ -513,6 +529,8 @@ "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "supercluster": ["supercluster@8.0.1", "", { "dependencies": { "kdbush": "^4.0.2" } }, "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "tailwindcss": ["tailwindcss@4.1.3", "", {}, "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g=="], diff --git a/package.json b/package.json index a7c7dcc..8532d32 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,13 @@ "preview": "vite preview" }, "dependencies": { + "@googlemaps/markerclusterer": "^2.6.2", "@tailwindcss/vite": "^4.1.3", "@tanstack/react-query": "^5.74.4", "@tanstack/react-query-devtools": "^5.74.7", "@tweenjs/tween.js": "^25.0.0", "@uidotdev/usehooks": "^2.4.1", + "@vis.gl/react-google-maps": "^1.5.4", "clsx": "^2.1.1", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", diff --git a/public/images/map/markers/points/shop-point.svg b/public/images/map/markers/points/shop-point.svg new file mode 100644 index 0000000..03a9cf6 --- /dev/null +++ b/public/images/map/markers/points/shop-point.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/AboutMarasiDrive.tsx b/src/components/AboutMarasiDrive.tsx index 37dc7cc..95de612 100644 --- a/src/components/AboutMarasiDrive.tsx +++ b/src/components/AboutMarasiDrive.tsx @@ -12,10 +12,11 @@ import TextBox from "./ui/TextBox"; import { useRef } from "react"; import { useScroll } from "motion/react"; import MarasiDriveMapCard from "./MarasiDriveMapCard"; - +import GoogleMap from "./GoogleMap"; import MarasiDriveNeighboursSliderTablet from "./MarasiDriveNeighboursSliderTablet"; import CustomScrollBar from "./ui/ScrollBar"; import BrochureButton from "./ui/BrochureButton"; +import { marasiDriveMapData } from "../data/mapMarasiDrive"; function AboutMarasiDrive() { const target = useRef(null); @@ -98,19 +99,32 @@ function AboutMarasiDrive() { destination for artful inspiration and cleverly activated spaces.`}

-
+
{marasiDriveFeatures.map(({ image, name }) => ( -
+
{name} - {name} + + {name} +
))}
- +
@@ -165,7 +179,7 @@ function AboutMarasiDrive() {

- +
@@ -224,18 +238,14 @@ function AboutMarasiDrive() { {marasiDriveMapCards.map((card) => ( ))} -
- +
+
- +
-
+
-
Download our brochures
+
+ Download our brochures +
+ + + ); +} + +function MapMarkers() { + const marasiDriveMarker = ( +
+ + +
+ ); + + const DubaiMarinaMarker = ( +
+ + +
+ ); + + const shopMarker = ( +
+ +
+ ); + + const templateMarkers: IGMapPoi[] = [ + { + location: { lat: 25.181504160790247, lng: 55.27565159760525 }, + customMarker: marasiDriveMarker, + }, + { + location: { lat: 25.069466431595334, lng: 55.128736429300375 }, + customMarker: DubaiMarinaMarker, + }, + { + location: { lat: 25.193476007744233, lng: 55.274782084720286 }, + customMarker: shopMarker, + }, + { + location: { lat: 25.193476007744233, lng: 55.244782084720286 }, + customMarker: shopMarker, + }, + ]; + + return ( + <> + {templateMarkers.map((poi: IGMapPoi, index: number) => ( + + {poi.customMarker} + + ))} + + ); +} diff --git a/src/components/ui/MapMarker.tsx b/src/components/ui/MapMarker.tsx new file mode 100644 index 0000000..1fdc5f4 --- /dev/null +++ b/src/components/ui/MapMarker.tsx @@ -0,0 +1,21 @@ +import { AdvancedMarker, Pin } from "@vis.gl/react-google-maps"; + +interface IGMapMarker { + key: string; + location: google.maps.LatLngLiteral; + children: React.ReactNode; +} + +export default function MapMarker({ key, location, children }: IGMapMarker) { + return ( + + + {children} + + + ); +} diff --git a/src/data/mapMarasiDrive.ts b/src/data/mapMarasiDrive.ts new file mode 100644 index 0000000..56fc364 --- /dev/null +++ b/src/data/mapMarasiDrive.ts @@ -0,0 +1,5 @@ +export const marasiDriveMapData = { + mapCenter: { lat: 25.183476007744233, lng: 55.274782084720286 } +} + + diff --git a/src/main.tsx b/src/main.tsx index 6c5a9d5..9e330ee 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,6 +1,6 @@ // Initialize Eruda for mobile debugging in development if (import.meta.env.DEV) { - import('eruda').then(eruda => eruda.default.init()); + import("eruda").then((eruda) => eruda.default.init()); } import "./index.css"; @@ -24,6 +24,7 @@ import TestPage from "./pages/TestPage.tsx"; import UnitPage from "./pages/UnitPage.tsx"; import PopupContainer from "./components/PopupContainer.tsx"; import VirtualTourPage from "./pages/VirtualTourPage.tsx"; +import { APIProvider } from "@vis.gl/react-google-maps"; const route = createBrowserRouter([ { @@ -88,10 +89,12 @@ const route = createBrowserRouter([ createRoot(document.getElementById("root")!).render( <> - - - - - + + + + + + + ); diff --git a/src/types/IGMapPoi.ts b/src/types/IGMapPoi.ts new file mode 100644 index 0000000..4c0f681 --- /dev/null +++ b/src/types/IGMapPoi.ts @@ -0,0 +1,4 @@ +export default interface IGMapPoi { + location: google.maps.LatLngLiteral; + customMarker?: React.ReactNode; +} \ No newline at end of file