diff --git a/src/app/carbets/_components/catalog-map-inner.tsx b/src/app/carbets/_components/catalog-map-inner.tsx new file mode 100644 index 0000000..1abac02 --- /dev/null +++ b/src/app/carbets/_components/catalog-map-inner.tsx @@ -0,0 +1,113 @@ +"use client"; + +import { useMemo } from "react"; +import Link from "next/link"; +import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet"; +import L, { LatLngBoundsExpression } from "leaflet"; + +import "leaflet/dist/leaflet.css"; + +import type { CatalogMapPoint } from "./catalog-map"; + +const ICON = L.divIcon({ + className: "karbe-catalog-marker", + html: ` +
+ + + + +
+ `, + iconSize: [28, 36], + iconAnchor: [14, 36], + popupAnchor: [0, -32], +}); + +export function CatalogMapInner({ points }: { points: CatalogMapPoint[] }) { + const bounds = useMemo(() => { + if (points.length === 0) { + // Centre par défaut sur la Guyane (Cayenne). + return [ + [3.5, -54.5], + [5.5, -52.0], + ]; + } + const lats = points.map((p) => p.latitude); + const lngs = points.map((p) => p.longitude); + const minLat = Math.min(...lats); + const maxLat = Math.max(...lats); + const minLng = Math.min(...lngs); + const maxLng = Math.max(...lngs); + // Padding 0.1° + return [ + [minLat - 0.1, minLng - 0.1], + [maxLat + 0.1, maxLng + 0.1], + ]; + }, [points]); + + return ( +
+ + + {points.map((p) => ( + + +
+ {p.coverUrl ? ( + // eslint-disable-next-line @next/next/no-img-element + {p.title} + ) : null} + {p.title} +
+ + Fleuve {p.river} + +
+ + {Number(p.nightlyPrice).toFixed(0)} € + + / nuit +
+ + Voir la fiche → + +
+
+
+ ))} +
+
+ ); +} diff --git a/src/app/carbets/_components/catalog-map.tsx b/src/app/carbets/_components/catalog-map.tsx new file mode 100644 index 0000000..5f65463 --- /dev/null +++ b/src/app/carbets/_components/catalog-map.tsx @@ -0,0 +1,29 @@ +"use client"; + +import dynamic from "next/dynamic"; + +const CatalogMapInner = dynamic( + () => import("./catalog-map-inner").then((m) => m.CatalogMapInner), + { + ssr: false, + loading: () => ( +
+ ), + }, +); + +export type CatalogMapPoint = { + id: string; + slug: string; + title: string; + river: string; + nightlyPrice: string; + latitude: number; + longitude: number; + coverUrl: string | null; +}; + +export function CatalogMap({ points }: { points: CatalogMapPoint[] }) { + if (points.length === 0) return null; + return ; +} diff --git a/src/app/carbets/page.tsx b/src/app/carbets/page.tsx index a49ed1b..b700fed 100644 --- a/src/app/carbets/page.tsx +++ b/src/app/carbets/page.tsx @@ -8,6 +8,7 @@ import { } from "@/lib/carbet-search"; import { CarbetCard } from "./_components/carbet-card"; +import { CatalogMap } from "./_components/catalog-map"; import { SearchFilters } from "./_components/search-filters"; export const metadata: Metadata = { @@ -72,6 +73,20 @@ export default async function CarbetsSearchPage({ {results.length} carbet{results.length > 1 ? "s" : ""} trouvé {results.length > 1 ? "s" : ""}.

+
+ ({ + id: c.id, + slug: c.slug, + title: c.title, + river: c.river, + nightlyPrice: c.nightlyPrice, + latitude: c.latitude, + longitude: c.longitude, + coverUrl: c.coverUrl, + }))} + /> +
    {results.map((carbet) => (
  • diff --git a/src/lib/carbet-search.ts b/src/lib/carbet-search.ts index bed9fd5..b2cb041 100644 --- a/src/lib/carbet-search.ts +++ b/src/lib/carbet-search.ts @@ -110,6 +110,9 @@ export type CarbetSearchResult = { mediaCount: number; reviewCount: number; averageRating: number | null; + nightlyPrice: string; + latitude: number; + longitude: number; }; // Build the Prisma where-clause for a public carbet search. A carbet is only @@ -179,6 +182,9 @@ export async function searchCarbets( maxStayNights: true, minCapacity: true, description: true, + nightlyPrice: true, + latitude: true, + longitude: true, media: { orderBy: { sortOrder: "asc" }, take: 1, @@ -213,6 +219,9 @@ export async function searchCarbets( mediaCount: carbet._count.media, reviewCount: stats.count, averageRating: stats.averageRating, + nightlyPrice: carbet.nightlyPrice.toString(), + latitude: Number(carbet.latitude), + longitude: Number(carbet.longitude), }; }); }