Updated Google Maps API script to include marker library and use Advanced Markers

This commit is contained in:
zaidmukaddam 2024-08-19 18:20:36 +05:30
parent 0e0c1c6d5c
commit a158d5d1c5
5 changed files with 43 additions and 32 deletions

View File

@ -1,4 +1,3 @@
import { anthropic } from "@ai-sdk/anthropic";
import { openai } from '@ai-sdk/openai'
import { convertToCoreMessages, streamText, tool } from "ai";
import { CodeInterpreter } from "@e2b/code-interpreter";

View File

@ -260,57 +260,60 @@ export default function Home() {
const isValidCoordinate = (coord: number) => {
return typeof coord === 'number' && !isNaN(coord) && isFinite(coord);
};
const loadGoogleMapsScript = (callback: () => void) => {
if (window.google && window.google.maps) {
callback();
return;
}
const existingScript = document.getElementById('googleMapsScript');
if (existingScript) {
existingScript.remove();
}
window.initMap = callback;
const script = document.createElement('script');
script.id = 'googleMapsScript';
script.src = `https://maps.googleapis.com/maps/api/js?key=${process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY}&libraries=places&callback=initMap`;
script.src = `https://maps.googleapis.com/maps/api/js?key=${process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY}&libraries=places,marker&callback=initMap`;
script.async = true;
script.defer = true;
document.head.appendChild(script);
};
const MapComponent = React.memo(({ center, places }: { center: { lat: number; lng: number }, places: any[] }) => {
const mapRef = useRef<HTMLDivElement>(null);
const [mapError, setMapError] = useState<string | null>(null);
const googleMapRef = useRef<google.maps.Map | null>(null);
const markersRef = useRef<google.maps.Marker[]>([]);
const markersRef = useRef<google.maps.marker.AdvancedMarkerElement[]>([]);
const memoizedCenter = useMemo(() => center, [center]);
const memoizedPlaces = useMemo(() => places, [places]);
const initializeMap = useCallback(() => {
const initializeMap = useCallback(async () => {
if (mapRef.current && isValidCoordinate(memoizedCenter.lat) && isValidCoordinate(memoizedCenter.lng)) {
const { Map } = await google.maps.importLibrary("maps") as google.maps.MapsLibrary;
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker") as google.maps.MarkerLibrary;
if (!googleMapRef.current) {
googleMapRef.current = new window.google.maps.Map(mapRef.current, {
googleMapRef.current = new Map(mapRef.current, {
center: memoizedCenter,
zoom: 14,
mapId: "347ff92e0c7225cf",
});
} else {
googleMapRef.current.setCenter(memoizedCenter);
}
// Clear existing markers
markersRef.current.forEach(marker => marker.setMap(null));
markersRef.current.forEach(marker => marker.map = null);
markersRef.current = [];
memoizedPlaces.forEach((place) => {
if (isValidCoordinate(place.location.lat) && isValidCoordinate(place.location.lng)) {
const MarkerClass = window.google.maps.marker?.AdvancedMarkerElement || window.google.maps.Marker;
const marker = new MarkerClass({
position: place.location,
const marker = new AdvancedMarkerElement({
map: googleMapRef.current,
position: place.location,
title: place.name,
});
markersRef.current.push(marker);
@ -320,7 +323,7 @@ export default function Home() {
setMapError('Invalid coordinates provided');
}
}, [memoizedCenter, memoizedPlaces]);
useEffect(() => {
loadGoogleMapsScript(() => {
try {
@ -330,17 +333,17 @@ export default function Home() {
setMapError('Failed to initialize Google Maps');
}
});
return () => {
// Clean up markers when component unmounts
markersRef.current.forEach(marker => marker.setMap(null));
markersRef.current.forEach(marker => marker.map = null);
};
}, [initializeMap]);
if (mapError) {
return <div className="h-64 flex items-center justify-center bg-gray-100">{mapError}</div>;
}
return <div ref={mapRef} className="w-full h-64" />;
});
@ -349,7 +352,7 @@ export default function Home() {
const MapSkeleton = () => (
<Skeleton className="w-full h-64" />
);
const PlaceDetails = ({ place }: { place: any }) => (
<div className="flex justify-between items-start py-2">
<div>
@ -398,7 +401,7 @@ export default function Home() {
</div>
);
}
if (isLoading) {
return (
<Card className="w-full my-4 overflow-hidden">
@ -411,7 +414,7 @@ export default function Home() {
</Card>
);
}
return (
<Card className="w-full my-4 overflow-hidden">
<CardHeader>

View File

@ -43,6 +43,7 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@types/google.maps": "^3.55.12",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",

View File

@ -52,7 +52,7 @@ dependencies:
version: 1.4.0
ai:
specifier: latest
version: 3.3.9(react@18.3.1)(svelte@4.2.18)(vue@3.4.35)(zod@3.23.8)
version: 3.3.10(react@18.3.1)(svelte@4.2.18)(vue@3.4.35)(zod@3.23.8)
class-variance-authority:
specifier: ^0.7.0
version: 0.7.0
@ -103,6 +103,9 @@ dependencies:
version: 3.23.8
devDependencies:
'@types/google.maps':
specifier: ^3.55.12
version: 3.55.12
'@types/node':
specifier: ^20
version: 20.14.13
@ -269,8 +272,8 @@ packages:
zod-to-json-schema: 3.22.5(zod@3.23.8)
dev: false
/@ai-sdk/vue@0.0.37(vue@3.4.35)(zod@3.23.8):
resolution: {integrity: sha512-m7dMi6qRoWPuru9TyWUm5jXAPGSDb1SHZp/Q+uYjhNY1dZwgsZxJvSeakogzR37uhiRCg3Kg8fCypQJe+dikPA==}
/@ai-sdk/vue@0.0.38(vue@3.4.35)(zod@3.23.8):
resolution: {integrity: sha512-iqVPsRDXkrfIFzwrWoUKqBzMqSHxJQoompdj0LCC9v3s9c4ndn9Vx67nB5g2ee3fO3bY/O9vLebDwYyVKM4glg==}
engines: {node: '>=18'}
peerDependencies:
vue: ^3.3.4
@ -1324,6 +1327,10 @@ packages:
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
dev: false
/@types/google.maps@3.55.12:
resolution: {integrity: sha512-Q8MsLE+YYIrE1H8wdN69YHHAF8h7ApvF5MiMXh/zeCpP9Ut745mV9M0F4X4eobZ2WJe9k8tW2ryYjLa87IO2Sg==}
dev: true
/@types/googlemaps@3.43.3:
resolution: {integrity: sha512-ZWNoz/O8MPEpiajvj7QiqCY8tTLFNqNZ/a+s+zTV58wFVNAvvqV4bdGfnsjTb5Cs4V6wEsLrX8XRhmnyYJ2Tdg==}
deprecated: 'Types for the Google Maps browser API have moved to @types/google.maps. Note: these types are not for the googlemaps npm package, which is a Node API.'
@ -1569,8 +1576,8 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
/ai@3.3.9(react@18.3.1)(svelte@4.2.18)(vue@3.4.35)(zod@3.23.8):
resolution: {integrity: sha512-PS6xHzYIH+iVLG3xd/jwsqZW7+X8GrSrsJwVB4ACMbxhZN8KRs4yUcnGEDPcvRkEL3PqHHJFUo9iVysdZwOUwg==}
/ai@3.3.10(react@18.3.1)(svelte@4.2.18)(vue@3.4.35)(zod@3.23.8):
resolution: {integrity: sha512-NuUUymuQb5KWZii8xMARfhloXmzlRNJiibv7Ci5N6WsMs2DmiVUlybUEL+DOYfIdDRzqCC2mxE0agpdgCbA2kA==}
engines: {node: '>=18'}
peerDependencies:
openai: ^4.42.0
@ -1596,7 +1603,7 @@ packages:
'@ai-sdk/solid': 0.0.36(zod@3.23.8)
'@ai-sdk/svelte': 0.0.38(svelte@4.2.18)(zod@3.23.8)
'@ai-sdk/ui-utils': 0.0.33(zod@3.23.8)
'@ai-sdk/vue': 0.0.37(vue@3.4.35)(zod@3.23.8)
'@ai-sdk/vue': 0.0.38(vue@3.4.35)(zod@3.23.8)
'@opentelemetry/api': 1.9.0
eventsource-parser: 1.1.2
json-schema: 0.4.0

View File

@ -20,7 +20,8 @@
],
"paths": {
"@/*": ["./*"]
}
},
"types": ["google.maps"]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]