diff --git a/.env.development b/.env.development index 327d04f..8c1afbc 100644 --- a/.env.development +++ b/.env.development @@ -1,4 +1,5 @@ NEXT_PUBLIC_GOOGLE_CLIENT_ID=xxxx NEXT_PUBLIC_GOOGLE_USER_SCRIPT_URL=xxxx NEXT_PUBLIC_GOOGLE_PLACES_SCRIPT_URL=xxxx +NEXT_PUBLIC_GOOGLE_PLACE_DETAILS_SCRIPT_URL=xxxx NEXT_PUBLIC_GOOGLE_FAVORITE_PLACES_SCRIPT_URL=xxxx \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5fdbc54..ab7123d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,6 +29,7 @@ jobs: NEXT_PUBLIC_GOOGLE_USER_SCRIPT_URL: ${{ secrets.GOOGLE_USER_SCRIPT_URL }} NEXT_PUBLIC_GOOGLE_PLACES_SCRIPT_URL: ${{ secrets.GOOGLE_PLACES_SCRIPT_URL }} NEXT_PUBLIC_GOOGLE_FAVORITE_PLACES_SCRIPT_URL: ${{ secrets.GOOGLE_FAVORITE_PLACES_SCRIPT_URL }} + NEXT_PUBLIC_GOOGLE_PLACE_DETAILS_SCRIPT_URL: ${{ secrets.GOOGLE_PLACE_DETAILS_SCRIPT_URL }} run: yarn build - name: Deploy to GitHub Pages diff --git a/app/detalhes/page.tsx b/app/detalhes/page.tsx index 51c2b21..6b13900 100644 --- a/app/detalhes/page.tsx +++ b/app/detalhes/page.tsx @@ -1,16 +1,67 @@ "use client"; +import Carousel from "@/components/Carousel"; +import { usePlacesContext } from "@/contexts/PlacesContext"; +import { Place, PlaceDetails } from "@/domains/Places/types"; import { useSearchParams } from "next/navigation"; +import { useEffect, useState } from "react"; +import { FaMapPin } from "react-icons/fa"; -const PlaceDetails: React.FC = () => { +const PlaceDetailsComponent: React.FC = () => { + const [selectedPlace, setSelectedPlace] = useState(); + const { places, placeDetails, loading, fetchPlaceDetails } = + usePlacesContext(); const searchParams = useSearchParams(); const placeId = searchParams.get("placeId"); + useEffect(() => { + if (places.length > 0) + setSelectedPlace(places.find((p) => p.id === Number(placeId))); + }, [placeId, places]); + + useEffect(() => { + const getDetails = async () => { + fetchPlaceDetails(placeId || ""); + }; + + getDetails(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [placeId]); + return (
-

{placeId}

-

Teste

+
+ {loading ? ( + // Skeleton loader enquanto os dados são carregados +
+
+
+ ) : ( + // Carousel real depois que os dados foram carregados + + )} +
+ + {/* Nome do local */} +

{selectedPlace?.name}

+ +
+ + {placeDetails?.location} +
+ + {/* Descrição do local */} +

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque sit + amet sapien eu ligula blandit consequat. Integer eget dolor in lacus + posuere volutpat. +

+ + {/* Mapa com a localização */} + {selectedPlace?.description && ( +
+ )}
); }; -export default PlaceDetails; +export default PlaceDetailsComponent; diff --git a/components/Carousel/index.tsx b/components/Carousel/index.tsx new file mode 100644 index 0000000..0192a8b --- /dev/null +++ b/components/Carousel/index.tsx @@ -0,0 +1,72 @@ +"use client"; +import { useState } from "react"; +import { FaChevronLeft, FaChevronRight } from "react-icons/fa"; + +const Carousel = ({ images }: { images: string[] }) => { + const [currentIndex, setCurrentIndex] = useState(0); + + const goToNext = () => { + setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length); + }; + + const goToPrevious = () => { + setCurrentIndex( + (prevIndex) => (prevIndex - 1 + images.length) % images.length + ); + }; + + return ( +
+ {/* Imagens */} +
+
+ {images.map((image, index) => ( +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {`Imagem +
+ ))} +
+
+ + + + +
+ {images.map((_, index) => ( +
setCurrentIndex(index)} + className={`w-3 h-3 rounded-full bg-white cursor-pointer ${ + currentIndex === index ? "bg-opacity-100" : "bg-opacity-50" + }`} + /> + ))} +
+
+ ); +}; + +export default Carousel; diff --git a/contexts/PlacesContext.tsx b/contexts/PlacesContext.tsx index 3a00964..b473d03 100644 --- a/contexts/PlacesContext.tsx +++ b/contexts/PlacesContext.tsx @@ -1,21 +1,29 @@ "use client"; -import { Place } from "@/domains/Places/types"; +import { Place, PlaceDetails } from "@/domains/Places/types"; +import axios from "axios"; import React, { createContext, useContext, useEffect, useState } from "react"; interface PlacesContextType { places: Place[]; loading: boolean; error: string | null; + placeDetails: PlaceDetails | undefined; + fetchPlaceDetails: (placeId: string) => void; } const PlacesContext = createContext(undefined); const SCRIPT_URL = process.env.NEXT_PUBLIC_GOOGLE_PLACES_SCRIPT_URL!; +const PLACE_DETAILS_SCRIPT_URL = + process.env.NEXT_PUBLIC_GOOGLE_PLACE_DETAILS_SCRIPT_URL!; export const PlacesProvider: React.FC<{ children: React.ReactNode }> = ({ children, }) => { const [places, setPlaces] = useState([]); + const [placeDetails, setPlaceDetails] = useState( + undefined + ); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -40,8 +48,24 @@ export const PlacesProvider: React.FC<{ children: React.ReactNode }> = ({ fetchPlaces(); }, []); + const fetchPlaceDetails = async (placeId: string) => { + try { + setLoading(true); + const response = await axios.get( + `${PLACE_DETAILS_SCRIPT_URL}?placeId=${placeId}` + ); + setPlaceDetails(response.data[0]); + } catch (err: unknown) { + console.error("Error fetching place details"); + } finally { + setLoading(false); + } + }; + return ( - + {children} ); diff --git a/domains/Places/types.ts b/domains/Places/types.ts index 8d0bbe2..28619da 100644 --- a/domains/Places/types.ts +++ b/domains/Places/types.ts @@ -7,3 +7,12 @@ export type Place = { image: string; type: PlaceType[]; }; + +interface CarouselImage { + carouselImages: string[]; +} + +export interface PlaceDetails extends CarouselImage { + placeId: string; + location: string; +}