diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..d078a7e --- /dev/null +++ b/global.d.ts @@ -0,0 +1,3 @@ +interface Window { + google: any; +} diff --git a/package.json b/package.json index 952fda9..a36872e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "standalone-script": "node ./src/scripts/standalone-script.js" }, "dependencies": { + "@googlemaps/js-api-loader": "^1.16.6", "@payloadcms/db-postgres": "3.0.0-beta.65", "@payloadcms/email-nodemailer": "3.0.0-beta.65", "@payloadcms/next": "3.0.0-beta.65", @@ -27,6 +28,7 @@ "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-navigation-menu": "^1.2.0", "@radix-ui/react-slot": "^1.1.0", + "@react-google-maps/api": "^2.19.3", "babel-plugin-react-compiler": "^0.0.0-experimental-592953e-20240517", "class-variance-authority": "^0.7.0", "classnames": "^2.5.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e6c5813..8470406 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@googlemaps/js-api-loader': + specifier: ^1.16.6 + version: 1.16.6 '@payloadcms/db-postgres': specifier: 3.0.0-beta.65 version: 3.0.0-beta.65(payload@3.0.0-beta.65(@swc/core@1.6.3(@swc/helpers@0.5.11))(@swc/types@0.1.8)(graphql@16.9.0)(typescript@5.4.5))(react@19.0.0-rc-f994737d14-20240522)(types-react@19.0.0-beta.2) @@ -41,6 +44,9 @@ importers: '@radix-ui/react-slot': specifier: ^1.1.0 version: 1.1.0(react@19.0.0-rc-f994737d14-20240522)(types-react@19.0.0-beta.2) + '@react-google-maps/api': + specifier: ^2.19.3 + version: 2.19.3(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522) babel-plugin-react-compiler: specifier: ^0.0.0-experimental-592953e-20240517 version: 0.0.0-experimental-938cd9a-20240601 @@ -800,6 +806,15 @@ packages: '@floating-ui/utils@0.2.2': resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} + '@googlemaps/js-api-loader@1.16.2': + resolution: {integrity: sha512-psGw5u0QM6humao48Hn4lrChOM2/rA43ZCm3tKK9qQsEj1/VzqkCqnvGfEOshDbBQflydfaRovbKwZMF4AyqbA==} + + '@googlemaps/js-api-loader@1.16.6': + resolution: {integrity: sha512-V8p5W9DbPQx74jWUmyYJOerhiB4C+MHekaO0ZRmc6lrOYrvY7+syLhzOWpp55kqSPeNb+qbC2h8i69aLIX6krQ==} + + '@googlemaps/markerclusterer@2.5.3': + resolution: {integrity: sha512-x7lX0R5yYOoiNectr10wLgCBasNcXFHiADIBdmn7jQllF2B5ENQw5XtZK+hIw4xnV0Df0xhN4LN98XqA5jaiOw==} + '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -1507,6 +1522,18 @@ packages: '@types/react-dom': optional: true + '@react-google-maps/api@2.19.3': + resolution: {integrity: sha512-jiLqvuOt5lOowkLeq7d077AByTyJp+s6hZVlLhlq7SBacBD37aUNpXBz2OsazfeR6Aw4a+9RRhAEjEFvrR1f5A==} + peerDependencies: + react: ^16.8 || ^17 || ^18 + react-dom: ^16.8 || ^17 || ^18 + + '@react-google-maps/infobox@2.19.2': + resolution: {integrity: sha512-6wvBqeJsQ/eFSvoxg+9VoncQvNoVCdmxzxRpLvmjPD+nNC6mHM0vJH1xSqaKijkMrfLJT0nfkTGpovrF896jwg==} + + '@react-google-maps/marker-clusterer@2.19.2': + resolution: {integrity: sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw==} + '@rushstack/eslint-patch@1.10.3': resolution: {integrity: sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==} @@ -1819,6 +1846,9 @@ packages: '@types/glob@7.2.0': resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + '@types/google.maps@3.55.2': + resolution: {integrity: sha512-JcTwzkxskR8DN/nnX96Pie3gGN3WHiPpuxzuQ9z3516o1bB243d8w8DHUJ8BohuzoT1o3HUFta2ns/mkZC8KRw==} + '@types/is-hotkey@0.1.10': resolution: {integrity: sha512-RvC8KMw5BCac1NvRRyaHgMMEtBaZ6wh0pyPTBu7izn4Sj/AX9Y4aXU5c7rX8PnM/knsuUpC1IeoBkANtxBypsQ==} @@ -3272,6 +3302,9 @@ packages: jws@3.2.2: resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + kdbush@4.0.2: + resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -4221,6 +4254,9 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + supercluster@8.0.1: + resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} + superjson@2.2.1: resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} engines: {node: '>=16'} @@ -5486,6 +5522,19 @@ snapshots: '@floating-ui/utils@0.2.2': {} + '@googlemaps/js-api-loader@1.16.2': + dependencies: + fast-deep-equal: 3.1.3 + + '@googlemaps/js-api-loader@1.16.6': + dependencies: + fast-deep-equal: 3.1.3 + + '@googlemaps/markerclusterer@2.5.3': + dependencies: + fast-deep-equal: 3.1.3 + supercluster: 8.0.1 + '@hapi/hoek@9.3.0': {} '@hapi/topo@5.1.0': @@ -6268,6 +6317,21 @@ snapshots: '@types/react': types-react@19.0.0-beta.2 '@types/react-dom': types-react-dom@19.0.0-beta.2 + '@react-google-maps/api@2.19.3(react-dom@19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522))(react@19.0.0-rc-f994737d14-20240522)': + dependencies: + '@googlemaps/js-api-loader': 1.16.2 + '@googlemaps/markerclusterer': 2.5.3 + '@react-google-maps/infobox': 2.19.2 + '@react-google-maps/marker-clusterer': 2.19.2 + '@types/google.maps': 3.55.2 + invariant: 2.2.4 + react: 19.0.0-rc-f994737d14-20240522 + react-dom: 19.0.0-rc-f994737d14-20240522(react@19.0.0-rc-f994737d14-20240522) + + '@react-google-maps/infobox@2.19.2': {} + + '@react-google-maps/marker-clusterer@2.19.2': {} + '@rushstack/eslint-patch@1.10.3': {} '@sideway/address@4.1.5': @@ -6682,6 +6746,8 @@ snapshots: '@types/minimatch': 5.1.2 '@types/node': 20.14.7 + '@types/google.maps@3.55.2': {} + '@types/is-hotkey@0.1.10': {} '@types/istanbul-lib-coverage@2.0.6': {} @@ -7559,7 +7625,7 @@ snapshots: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.9.0(eslint@8.57.0) eslint-plugin-react: 7.34.3(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -7583,7 +7649,7 @@ snapshots: enhanced-resolve: 5.17.0 eslint: 8.57.0 eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.14.0 @@ -7605,7 +7671,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -8362,6 +8428,8 @@ snapshots: jwa: 1.4.1 safe-buffer: 5.2.1 + kdbush@4.0.2: {} + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -9394,6 +9462,10 @@ snapshots: pirates: 4.0.6 ts-interface-checker: 0.1.13 + supercluster@8.0.1: + dependencies: + kdbush: 4.0.2 + superjson@2.2.1: dependencies: copy-anything: 3.0.5 diff --git a/src/app/(app)/[works]/[slug]/page.tsx b/src/app/(app)/[works]/[slug]/page.tsx index a215a2d..e5e8b76 100644 --- a/src/app/(app)/[works]/[slug]/page.tsx +++ b/src/app/(app)/[works]/[slug]/page.tsx @@ -46,7 +46,7 @@ export default async function Work({ params }: { params: { slug: string } }) { {serializeLexical({ nodes: description!.root?.children })}
- +
diff --git a/src/app/(app)/layout.tsx b/src/app/(app)/layout.tsx index 0657b19..483069d 100644 --- a/src/app/(app)/layout.tsx +++ b/src/app/(app)/layout.tsx @@ -30,7 +30,6 @@ export default function RootLayout({ }>) { return ( -
diff --git a/src/collections/Works.ts b/src/collections/Works.ts index ae9653b..4a1e768 100644 --- a/src/collections/Works.ts +++ b/src/collections/Works.ts @@ -33,6 +33,12 @@ export const Works: CollectionConfig = { }, ], }, + { + name: "category", + type: "relationship", + relationTo: "categoryWork", + }, + { name: "mapUrl", type: "text" }, { name: "coordenadas", type: "group", @@ -52,10 +58,5 @@ export const Works: CollectionConfig = { }, ], }, - { - name: "category", - type: "relationship", - relationTo: "categoryWork", - }, ], }; diff --git a/src/components/Map/dinamycMap.tsx b/src/components/Map/dinamycMap.tsx new file mode 100644 index 0000000..3a43f9f --- /dev/null +++ b/src/components/Map/dinamycMap.tsx @@ -0,0 +1,45 @@ +'use client' + +import { MapComponent } from "./googleMap"; +import { MapProvider } from "./mapProvider"; + + + +function extractMapParametersFromUrl(url: string) { + const regex = /@(-?\d+\.\d+),(-?\d+\.\d+),(\d+)a,(\d+\.\d+)y,(\d+\.\d+)h,(\d+\.\d+)t/; + console.log("url", url) + + const matches = url.match(regex); + console.log("matches", matches) + if (matches) { + return { + lat: parseFloat(matches[1]), + lng: parseFloat(matches[2]), + zoom: parseInt(matches[3]), + pitch: parseFloat(matches[4]), + heading: parseFloat(matches[5]), + tilt: parseFloat(matches[6]), + }; + } else { + return null; + } +} + +const DynamicMap = ({ mapUrl }: { mapUrl: string }) => { + + const mapParameters = extractMapParametersFromUrl(mapUrl); + + console.log("mapParameters", mapParameters) + + if (!mapParameters) { + return

Invalid URL

; + } + + return ( + + + + ); +}; + +export default DynamicMap; diff --git a/src/components/Map/googleMap.tsx b/src/components/Map/googleMap.tsx new file mode 100644 index 0000000..0789a99 --- /dev/null +++ b/src/components/Map/googleMap.tsx @@ -0,0 +1,49 @@ +/*Since the map was loaded on client side, +we need to make this component client rendered as well*/ +'use client' + +//Map component Component from library +import { GoogleMap, useJsApiLoader } from "@react-google-maps/api"; + + +const MapComponent = ({ lat, lng, zoom, tilt }: { lat: number, lng: number, zoom: number, tilt: number }) => { + //Map's styling + const defaultMapContainerStyle = { + width: '100%', + height: '100vh', + borderRadius: '32px 0px 0px 32px', + }; + + //K2's coordinates + const defaultMapCenter = { + lat: lat, + lng: lng + } + + //Default zoom level, can be adjusted + const defaultMapZoom = zoom + + //Map options + const defaultMapOptions = { + zoomControl: false, + tilt: tilt, + }; + + + + return ( +
+ + +
+ + ) +}; + +export { MapComponent }; \ No newline at end of file diff --git a/src/components/Map/index.tsx b/src/components/Map/index.tsx index 49f4077..708556f 100644 --- a/src/components/Map/index.tsx +++ b/src/components/Map/index.tsx @@ -1,20 +1,26 @@ -const Map = (props: + +import { Work } from "@/payload-types"; +import DynamicMap from "./dinamycMap"; + +const Map = ({ work, height = '800' }: { - hasCoordinates: (arg0: any) => any; - work: { - coordenadas: { - longitude: any; - latitude: any; - }; - }; + // hasCoordinates: (arg0: any) => any; + work: Work; height?: string; }) => { - const height = props.height ?? '450' + + return ( - props.hasCoordinates(props.work?.coordenadas) &&
- -
) + work.mapUrl && + + + ) }; +// props.hasCoordinates(props.work?.coordenadas) &&
+// +//
+ + export default Map \ No newline at end of file diff --git a/src/components/Map/mapProvider.tsx b/src/components/Map/mapProvider.tsx new file mode 100644 index 0000000..6751c15 --- /dev/null +++ b/src/components/Map/mapProvider.tsx @@ -0,0 +1,26 @@ +//Since the map will be laoded and displayed on client side +'use client'; + +// Import necessary modules and functions from external libraries and our own project +import { Libraries, useJsApiLoader } from '@react-google-maps/api'; +import { ReactNode } from 'react'; + +// Define a list of libraries to load from the Google Maps API +const libraries = ['places', 'drawing', 'geometry']; + +// Define a function component called MapProvider that takes a children prop +export function MapProvider({ children }: { children: ReactNode }) { + + // Load the Google Maps JavaScript API asynchronously + const { isLoaded: scriptLoaded, loadError } = useJsApiLoader({ + googleMapsApiKey: process.env.NEXT_PUBLIC_GOOGLE_MAP_API as string, + libraries: libraries as Libraries, + }); + + if (loadError) return

Parece que hou um problema para carregar o map :(

+ + if (!scriptLoaded) return

Procurando o local no mapa ...

+ + // Return the children prop wrapped by this MapProvider component + return children; +} \ No newline at end of file diff --git a/src/payload-types.ts b/src/payload-types.ts index 51be9f2..9847996 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -174,11 +174,12 @@ export interface Work { id?: string | null; }[] | null; + category?: (number | null) | CategoryWork; + mapUrl?: string | null; coordenadas?: { longitude?: string | null; latitude?: string | null; }; - category?: (number | null) | CategoryWork; updatedAt: string; createdAt: string; }