Updated Google Maps API script to include marker library and use Advanced Markers
This commit is contained in:
parent
0e0c1c6d5c
commit
a158d5d1c5
@ -1,4 +1,3 @@
|
|||||||
import { anthropic } from "@ai-sdk/anthropic";
|
|
||||||
import { openai } from '@ai-sdk/openai'
|
import { openai } from '@ai-sdk/openai'
|
||||||
import { convertToCoreMessages, streamText, tool } from "ai";
|
import { convertToCoreMessages, streamText, tool } from "ai";
|
||||||
import { CodeInterpreter } from "@e2b/code-interpreter";
|
import { CodeInterpreter } from "@e2b/code-interpreter";
|
||||||
|
|||||||
51
app/page.tsx
51
app/page.tsx
@ -260,57 +260,60 @@ export default function Home() {
|
|||||||
const isValidCoordinate = (coord: number) => {
|
const isValidCoordinate = (coord: number) => {
|
||||||
return typeof coord === 'number' && !isNaN(coord) && isFinite(coord);
|
return typeof coord === 'number' && !isNaN(coord) && isFinite(coord);
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadGoogleMapsScript = (callback: () => void) => {
|
const loadGoogleMapsScript = (callback: () => void) => {
|
||||||
if (window.google && window.google.maps) {
|
if (window.google && window.google.maps) {
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingScript = document.getElementById('googleMapsScript');
|
const existingScript = document.getElementById('googleMapsScript');
|
||||||
if (existingScript) {
|
if (existingScript) {
|
||||||
existingScript.remove();
|
existingScript.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.initMap = callback;
|
window.initMap = callback;
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.id = 'googleMapsScript';
|
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.async = true;
|
||||||
script.defer = true;
|
script.defer = true;
|
||||||
document.head.appendChild(script);
|
document.head.appendChild(script);
|
||||||
};
|
};
|
||||||
|
|
||||||
const MapComponent = React.memo(({ center, places }: { center: { lat: number; lng: number }, places: any[] }) => {
|
const MapComponent = React.memo(({ center, places }: { center: { lat: number; lng: number }, places: any[] }) => {
|
||||||
const mapRef = useRef<HTMLDivElement>(null);
|
const mapRef = useRef<HTMLDivElement>(null);
|
||||||
const [mapError, setMapError] = useState<string | null>(null);
|
const [mapError, setMapError] = useState<string | null>(null);
|
||||||
const googleMapRef = useRef<google.maps.Map | 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 memoizedCenter = useMemo(() => center, [center]);
|
||||||
const memoizedPlaces = useMemo(() => places, [places]);
|
const memoizedPlaces = useMemo(() => places, [places]);
|
||||||
|
|
||||||
const initializeMap = useCallback(() => {
|
const initializeMap = useCallback(async () => {
|
||||||
if (mapRef.current && isValidCoordinate(memoizedCenter.lat) && isValidCoordinate(memoizedCenter.lng)) {
|
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) {
|
if (!googleMapRef.current) {
|
||||||
googleMapRef.current = new window.google.maps.Map(mapRef.current, {
|
googleMapRef.current = new Map(mapRef.current, {
|
||||||
center: memoizedCenter,
|
center: memoizedCenter,
|
||||||
zoom: 14,
|
zoom: 14,
|
||||||
|
mapId: "347ff92e0c7225cf",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
googleMapRef.current.setCenter(memoizedCenter);
|
googleMapRef.current.setCenter(memoizedCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear existing markers
|
// Clear existing markers
|
||||||
markersRef.current.forEach(marker => marker.setMap(null));
|
markersRef.current.forEach(marker => marker.map = null);
|
||||||
markersRef.current = [];
|
markersRef.current = [];
|
||||||
|
|
||||||
memoizedPlaces.forEach((place) => {
|
memoizedPlaces.forEach((place) => {
|
||||||
if (isValidCoordinate(place.location.lat) && isValidCoordinate(place.location.lng)) {
|
if (isValidCoordinate(place.location.lat) && isValidCoordinate(place.location.lng)) {
|
||||||
const MarkerClass = window.google.maps.marker?.AdvancedMarkerElement || window.google.maps.Marker;
|
const marker = new AdvancedMarkerElement({
|
||||||
const marker = new MarkerClass({
|
|
||||||
position: place.location,
|
|
||||||
map: googleMapRef.current,
|
map: googleMapRef.current,
|
||||||
|
position: place.location,
|
||||||
title: place.name,
|
title: place.name,
|
||||||
});
|
});
|
||||||
markersRef.current.push(marker);
|
markersRef.current.push(marker);
|
||||||
@ -320,7 +323,7 @@ export default function Home() {
|
|||||||
setMapError('Invalid coordinates provided');
|
setMapError('Invalid coordinates provided');
|
||||||
}
|
}
|
||||||
}, [memoizedCenter, memoizedPlaces]);
|
}, [memoizedCenter, memoizedPlaces]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadGoogleMapsScript(() => {
|
loadGoogleMapsScript(() => {
|
||||||
try {
|
try {
|
||||||
@ -330,17 +333,17 @@ export default function Home() {
|
|||||||
setMapError('Failed to initialize Google Maps');
|
setMapError('Failed to initialize Google Maps');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// Clean up markers when component unmounts
|
// Clean up markers when component unmounts
|
||||||
markersRef.current.forEach(marker => marker.setMap(null));
|
markersRef.current.forEach(marker => marker.map = null);
|
||||||
};
|
};
|
||||||
}, [initializeMap]);
|
}, [initializeMap]);
|
||||||
|
|
||||||
if (mapError) {
|
if (mapError) {
|
||||||
return <div className="h-64 flex items-center justify-center bg-gray-100">{mapError}</div>;
|
return <div className="h-64 flex items-center justify-center bg-gray-100">{mapError}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div ref={mapRef} className="w-full h-64" />;
|
return <div ref={mapRef} className="w-full h-64" />;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -349,7 +352,7 @@ export default function Home() {
|
|||||||
const MapSkeleton = () => (
|
const MapSkeleton = () => (
|
||||||
<Skeleton className="w-full h-64" />
|
<Skeleton className="w-full h-64" />
|
||||||
);
|
);
|
||||||
|
|
||||||
const PlaceDetails = ({ place }: { place: any }) => (
|
const PlaceDetails = ({ place }: { place: any }) => (
|
||||||
<div className="flex justify-between items-start py-2">
|
<div className="flex justify-between items-start py-2">
|
||||||
<div>
|
<div>
|
||||||
@ -398,7 +401,7 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
<Card className="w-full my-4 overflow-hidden">
|
<Card className="w-full my-4 overflow-hidden">
|
||||||
@ -411,7 +414,7 @@ export default function Home() {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="w-full my-4 overflow-hidden">
|
<Card className="w-full my-4 overflow-hidden">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/google.maps": "^3.55.12",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
|
|||||||
@ -52,7 +52,7 @@ dependencies:
|
|||||||
version: 1.4.0
|
version: 1.4.0
|
||||||
ai:
|
ai:
|
||||||
specifier: latest
|
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:
|
class-variance-authority:
|
||||||
specifier: ^0.7.0
|
specifier: ^0.7.0
|
||||||
version: 0.7.0
|
version: 0.7.0
|
||||||
@ -103,6 +103,9 @@ dependencies:
|
|||||||
version: 3.23.8
|
version: 3.23.8
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/google.maps':
|
||||||
|
specifier: ^3.55.12
|
||||||
|
version: 3.55.12
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^20
|
specifier: ^20
|
||||||
version: 20.14.13
|
version: 20.14.13
|
||||||
@ -269,8 +272,8 @@ packages:
|
|||||||
zod-to-json-schema: 3.22.5(zod@3.23.8)
|
zod-to-json-schema: 3.22.5(zod@3.23.8)
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@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):
|
||||||
resolution: {integrity: sha512-m7dMi6qRoWPuru9TyWUm5jXAPGSDb1SHZp/Q+uYjhNY1dZwgsZxJvSeakogzR37uhiRCg3Kg8fCypQJe+dikPA==}
|
resolution: {integrity: sha512-iqVPsRDXkrfIFzwrWoUKqBzMqSHxJQoompdj0LCC9v3s9c4ndn9Vx67nB5g2ee3fO3bY/O9vLebDwYyVKM4glg==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: ^3.3.4
|
vue: ^3.3.4
|
||||||
@ -1324,6 +1327,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/google.maps@3.55.12:
|
||||||
|
resolution: {integrity: sha512-Q8MsLE+YYIrE1H8wdN69YHHAF8h7ApvF5MiMXh/zeCpP9Ut745mV9M0F4X4eobZ2WJe9k8tW2ryYjLa87IO2Sg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/googlemaps@3.43.3:
|
/@types/googlemaps@3.43.3:
|
||||||
resolution: {integrity: sha512-ZWNoz/O8MPEpiajvj7QiqCY8tTLFNqNZ/a+s+zTV58wFVNAvvqV4bdGfnsjTb5Cs4V6wEsLrX8XRhmnyYJ2Tdg==}
|
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.'
|
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'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
/ai@3.3.9(react@18.3.1)(svelte@4.2.18)(vue@3.4.35)(zod@3.23.8):
|
/ai@3.3.10(react@18.3.1)(svelte@4.2.18)(vue@3.4.35)(zod@3.23.8):
|
||||||
resolution: {integrity: sha512-PS6xHzYIH+iVLG3xd/jwsqZW7+X8GrSrsJwVB4ACMbxhZN8KRs4yUcnGEDPcvRkEL3PqHHJFUo9iVysdZwOUwg==}
|
resolution: {integrity: sha512-NuUUymuQb5KWZii8xMARfhloXmzlRNJiibv7Ci5N6WsMs2DmiVUlybUEL+DOYfIdDRzqCC2mxE0agpdgCbA2kA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
openai: ^4.42.0
|
openai: ^4.42.0
|
||||||
@ -1596,7 +1603,7 @@ packages:
|
|||||||
'@ai-sdk/solid': 0.0.36(zod@3.23.8)
|
'@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/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/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
|
'@opentelemetry/api': 1.9.0
|
||||||
eventsource-parser: 1.1.2
|
eventsource-parser: 1.1.2
|
||||||
json-schema: 0.4.0
|
json-schema: 0.4.0
|
||||||
|
|||||||
@ -20,7 +20,8 @@
|
|||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./*"]
|
"@/*": ["./*"]
|
||||||
}
|
},
|
||||||
|
"types": ["google.maps"]
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user