mirror of
https://github.com/LucasVbr/meeting-app.git
synced 2026-05-13 17:21:53 +00:00
feat(Map with bars): added the map with bars provided by opendatasoft
TODO: -modal to invite match to bar -use overpass ? (openStreetMap API)
This commit is contained in:
Generated
+65
@@ -9,6 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.5.1",
|
"@chakra-ui/react": "^2.5.1",
|
||||||
|
"@christopherpickering/react-leaflet-markercluster": "^1.1.0",
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.10.6",
|
||||||
"@emotion/styled": "^11.10.6",
|
"@emotion/styled": "^11.10.6",
|
||||||
"@premieroctet/next-crud": "^2.2.0",
|
"@premieroctet/next-crud": "^2.2.0",
|
||||||
@@ -24,12 +25,15 @@
|
|||||||
"formidable": "^2.1.1",
|
"formidable": "^2.1.1",
|
||||||
"framer-motion": "^10.8.5",
|
"framer-motion": "^10.8.5",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
|
"leaflet": "^1.9.3",
|
||||||
|
"leaflet.markercluster": "^1.5.3",
|
||||||
"next": "13.2.3",
|
"next": "13.2.3",
|
||||||
"next-auth": "^4.20.1",
|
"next-auth": "^4.20.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-hook-form": "^7.43.5",
|
"react-hook-form": "^7.43.5",
|
||||||
"react-icons": "^4.8.0",
|
"react-icons": "^4.8.0",
|
||||||
|
"react-leaflet": "^4.2.1",
|
||||||
"react-query": "^3.39.3",
|
"react-query": "^3.39.3",
|
||||||
"socket.io": "^4.6.1",
|
"socket.io": "^4.6.1",
|
||||||
"socket.io-client": "^4.6.1"
|
"socket.io-client": "^4.6.1"
|
||||||
@@ -1316,6 +1320,23 @@
|
|||||||
"react": ">=18"
|
"react": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@christopherpickering/react-leaflet-markercluster": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@christopherpickering/react-leaflet-markercluster/-/react-leaflet-markercluster-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-69Q3c/Szq7vXNSq6wy+wi6Wj4yHHVxzAuJMiFMgTcoyuZO4EQj8a6qzOc/XdcuQbNX+gfFe2Me/C61bc6sjO4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@react-leaflet/core": "^2.1.0",
|
||||||
|
"leaflet": "^1.9.3",
|
||||||
|
"leaflet.markercluster": "^1.5.3",
|
||||||
|
"postcss-flexbugs-fixes": "^5.0.2",
|
||||||
|
"react-leaflet": "^4.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"leaflet": "^1.9.3",
|
||||||
|
"leaflet.markercluster": "^1.5.3",
|
||||||
|
"react-leaflet": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@cspotcode/source-map-support": {
|
"node_modules/@cspotcode/source-map-support": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||||
@@ -2145,6 +2166,16 @@
|
|||||||
"integrity": "sha512-jh9ajkGl3Lw9uTKEwlNBSh79a1v6C1JducqxakgkQyLev6kG1xxkuc2rDGrIDxUdpCOuuPRjuSCHhjnv7qLLgQ==",
|
"integrity": "sha512-jh9ajkGl3Lw9uTKEwlNBSh79a1v6C1JducqxakgkQyLev6kG1xxkuc2rDGrIDxUdpCOuuPRjuSCHhjnv7qLLgQ==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-leaflet/core": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"leaflet": "^1.9.0",
|
||||||
|
"react": "^18.0.0",
|
||||||
|
"react-dom": "^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@reduxjs/toolkit": {
|
"node_modules/@reduxjs/toolkit": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
|
||||||
@@ -5646,6 +5677,19 @@
|
|||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ=="
|
||||||
|
},
|
||||||
|
"node_modules/leaflet.markercluster": {
|
||||||
|
"version": "1.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz",
|
||||||
|
"integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"leaflet": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/levn": {
|
"node_modules/levn": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||||
@@ -6735,6 +6779,14 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/postcss-flexbugs-fixes": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"postcss": "^8.1.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/preact": {
|
"node_modules/preact": {
|
||||||
"version": "10.13.2",
|
"version": "10.13.2",
|
||||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.13.2.tgz",
|
"resolved": "https://registry.npmjs.org/preact/-/preact-10.13.2.tgz",
|
||||||
@@ -6966,6 +7018,19 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/react-leaflet": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@react-leaflet/core": "^2.1.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"leaflet": "^1.9.0",
|
||||||
|
"react": "^18.0.0",
|
||||||
|
"react-dom": "^18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-query": {
|
"node_modules/react-query": {
|
||||||
"version": "3.39.3",
|
"version": "3.39.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.5.1",
|
"@chakra-ui/react": "^2.5.1",
|
||||||
|
"@christopherpickering/react-leaflet-markercluster": "^1.1.0",
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.10.6",
|
||||||
"@emotion/styled": "^11.10.6",
|
"@emotion/styled": "^11.10.6",
|
||||||
"@premieroctet/next-crud": "^2.2.0",
|
"@premieroctet/next-crud": "^2.2.0",
|
||||||
@@ -25,12 +26,15 @@
|
|||||||
"formidable": "^2.1.1",
|
"formidable": "^2.1.1",
|
||||||
"framer-motion": "^10.8.5",
|
"framer-motion": "^10.8.5",
|
||||||
"fs": "^0.0.1-security",
|
"fs": "^0.0.1-security",
|
||||||
|
"leaflet": "^1.9.3",
|
||||||
|
"leaflet.markercluster": "^1.5.3",
|
||||||
"next": "13.2.3",
|
"next": "13.2.3",
|
||||||
"next-auth": "^4.20.1",
|
"next-auth": "^4.20.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-hook-form": "^7.43.5",
|
"react-hook-form": "^7.43.5",
|
||||||
"react-icons": "^4.8.0",
|
"react-icons": "^4.8.0",
|
||||||
|
"react-leaflet": "^4.2.1",
|
||||||
"react-query": "^3.39.3",
|
"react-query": "^3.39.3",
|
||||||
"socket.io": "^4.6.1",
|
"socket.io": "^4.6.1",
|
||||||
"socket.io-client": "^4.6.1"
|
"socket.io-client": "^4.6.1"
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 45 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@@ -0,0 +1,25 @@
|
|||||||
|
import { MdError } from "react-icons/md";
|
||||||
|
import { Button, Text, VStack } from "@chakra-ui/react";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
export default function LoadingPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<VStack
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
|
height="100vh"
|
||||||
|
width="100vw"
|
||||||
|
bg="gray.100"
|
||||||
|
>
|
||||||
|
<MdError color="purple.500" size="50%" />
|
||||||
|
<Text color="purple.500" fontSize="2xl" fontWeight="bold">
|
||||||
|
Une erreur est survenue
|
||||||
|
</Text>
|
||||||
|
<Button colorScheme={"purple"} onClick={() => router.push("/")}>
|
||||||
|
Page d'accueuil
|
||||||
|
</Button>
|
||||||
|
</VStack>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -9,7 +9,6 @@ import {
|
|||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { signOut, useSession } from "next-auth/react";
|
import { signOut, useSession } from "next-auth/react";
|
||||||
import Nextlink from "next/link";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
variant: "static" | "fixed";
|
variant: "static" | "fixed";
|
||||||
@@ -73,6 +72,9 @@ export default function Navbar({ variant = "fixed" }: Props) {
|
|||||||
<Link href={"/userProfile"} color={"purple.500"}>
|
<Link href={"/userProfile"} color={"purple.500"}>
|
||||||
Profile
|
Profile
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link href={"/map"} color={"purple.500"}>
|
||||||
|
Carte
|
||||||
|
</Link>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { useRouter } from "next/router";
|
|||||||
import { AiFillMessage } from "react-icons/ai";
|
import { AiFillMessage } from "react-icons/ai";
|
||||||
import { BsFillPersonFill } from "react-icons/bs";
|
import { BsFillPersonFill } from "react-icons/bs";
|
||||||
import { BiLogOut } from "react-icons/bi";
|
import { BiLogOut } from "react-icons/bi";
|
||||||
|
import { FaMapMarkedAlt } from "react-icons/fa";
|
||||||
|
|
||||||
import LeftPanelButton from "@/components/layout/dashboard/left_panel/LeftPanelButton";
|
import LeftPanelButton from "@/components/layout/dashboard/left_panel/LeftPanelButton";
|
||||||
import { signOut } from "next-auth/react";
|
import { signOut } from "next-auth/react";
|
||||||
@@ -69,6 +70,12 @@ export default function LeftPanel(props) {
|
|||||||
spacing={3.5}
|
spacing={3.5}
|
||||||
alignContent={"bottom"}
|
alignContent={"bottom"}
|
||||||
>
|
>
|
||||||
|
<LeftPanelButton
|
||||||
|
leftIcon={<FaMapMarkedAlt />}
|
||||||
|
onClickHandler={() => router.push("/map")}
|
||||||
|
>
|
||||||
|
Carte
|
||||||
|
</LeftPanelButton>
|
||||||
<LeftPanelButton
|
<LeftPanelButton
|
||||||
leftIcon={<AiFillMessage />}
|
leftIcon={<AiFillMessage />}
|
||||||
onClickHandler={() => router.push("/dashboard")}
|
onClickHandler={() => router.push("/dashboard")}
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
|
||||||
|
import { Flex, Text, useToast } from "@chakra-ui/react";
|
||||||
|
import MarkerClusterGroup from "@christopherpickering/react-leaflet-markercluster";
|
||||||
|
|
||||||
|
import "@christopherpickering/react-leaflet-markercluster/dist/styles.min.css";
|
||||||
|
|
||||||
|
import MarkerBar from "./MarkerBar";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
|
||||||
|
export default function MapComponent(props) {
|
||||||
|
const { location, listBars } = props;
|
||||||
|
|
||||||
|
const toast = useToast({ position: "top" });
|
||||||
|
|
||||||
|
const idToastError = "error_location";
|
||||||
|
|
||||||
|
const userIcon = new L.Icon({
|
||||||
|
iconUrl: "logo.svg",
|
||||||
|
iconSize: [35, 35],
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{location[0] === null || location[1] === null ? (
|
||||||
|
<>
|
||||||
|
{!toast.isActive(idToastError)
|
||||||
|
? toast({
|
||||||
|
title: "Erreur",
|
||||||
|
id: idToastError,
|
||||||
|
description: "Veuillez autoriser la localisation",
|
||||||
|
status: "error",
|
||||||
|
isClosable: false,
|
||||||
|
duration: 100000,
|
||||||
|
})
|
||||||
|
: null}
|
||||||
|
<Text color="purple.500" fontSize="2xl" fontWeight="bold">
|
||||||
|
Veuillez autoriser la localisation
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Flex>
|
||||||
|
<MapContainer
|
||||||
|
center={location}
|
||||||
|
zoom={13}
|
||||||
|
minZoom={8}
|
||||||
|
style={{
|
||||||
|
width: "100vw",
|
||||||
|
height: "100vw",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TileLayer
|
||||||
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
|
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
|
/>
|
||||||
|
{/* Pour le user */}
|
||||||
|
<Marker icon={userIcon} position={location}></Marker>
|
||||||
|
|
||||||
|
<MarkerClusterGroup chunkedLoading showCoverageOnHover={false}>
|
||||||
|
{listBars.map((bar, index) => {
|
||||||
|
return <MarkerBar key={index} bar={bar} />;
|
||||||
|
})}
|
||||||
|
</MarkerClusterGroup>
|
||||||
|
</MapContainer>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { Marker, Popup } from "react-leaflet";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
import { Box, Button, Card, CardBody, Text } from "@chakra-ui/react";
|
||||||
|
|
||||||
|
export default function MarkerBar(props) {
|
||||||
|
const { bar } = props;
|
||||||
|
|
||||||
|
//changer l'icon
|
||||||
|
const barIcon = new L.Icon({
|
||||||
|
iconUrl: "drink_cocktail.png",
|
||||||
|
iconSize: [35, 35],
|
||||||
|
popupAnchor: [0, -5],
|
||||||
|
backgroundColor: "purple",
|
||||||
|
});
|
||||||
|
|
||||||
|
const location = [bar.geo_point_2d.lat, bar.geo_point_2d.lon];
|
||||||
|
|
||||||
|
//mettre un tooltip...
|
||||||
|
return (
|
||||||
|
<Marker icon={barIcon} position={location}>
|
||||||
|
<Popup>
|
||||||
|
<Box alignItems={"center"}>
|
||||||
|
<Text fontSize={"1rem"} fontWeight={"bold"} align={"center"}>
|
||||||
|
{bar.name || '"Nom du bar"'}
|
||||||
|
</Text>
|
||||||
|
<Button colorScheme={"purple"} variant={"outline"}>
|
||||||
|
Inviter un match
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Popup>
|
||||||
|
</Marker>
|
||||||
|
);
|
||||||
|
}
|
||||||
+11
-14
@@ -1,7 +1,7 @@
|
|||||||
import { Grid, GridItem, Text, Box, useToast } from "@chakra-ui/react";
|
import { Grid, GridItem, Text, Box, useToast } from "@chakra-ui/react";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import type { Session } from "@/models/auth/Session";
|
import type { Session } from "@/models/auth/Session";
|
||||||
import CardUser from "../components/layout/dashboard/card_user/CardUser";
|
import CardUser from "../components/layout/dashboard/card_user/CardUser";
|
||||||
@@ -16,10 +16,8 @@ import LoadingPage from "@/components/LoadingPage";
|
|||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const toast = useToast({ position: "top", isClosable: true });
|
const toast = useToast({ position: "top", isClosable: true });
|
||||||
const [userLikes, setUserLikes] = useState();
|
const [userLikes, setUserLikes] = useState([] as string[]);
|
||||||
const [userDislikes, setUserDislikes] = useState();
|
const [userDislikes, setUserDislikes] = useState([] as string[]);
|
||||||
|
|
||||||
const [preferences, setPreferences] = useState(null);
|
|
||||||
|
|
||||||
const { data: session, status } = useSession();
|
const { data: session, status } = useSession();
|
||||||
|
|
||||||
@@ -37,13 +35,6 @@ export default function Dashboard() {
|
|||||||
setUserDislikes([...user.UserDislikesID]);
|
setUserDislikes([...user.UserDislikesID]);
|
||||||
setUserLikes([...user.UserLikesID]);
|
setUserLikes([...user.UserLikesID]);
|
||||||
|
|
||||||
setPreferences([
|
|
||||||
user.prefGender,
|
|
||||||
user.ageMin,
|
|
||||||
user.ageMax,
|
|
||||||
user.distance,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return fetch(`/api/users/${user.id}`)
|
return fetch(`/api/users/${user.id}`)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
return res.json();
|
return res.json();
|
||||||
@@ -68,7 +59,14 @@ export default function Dashboard() {
|
|||||||
enabled: status === "authenticated" && !isLoading,
|
enabled: status === "authenticated" && !isLoading,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
return fetch(
|
return fetch(
|
||||||
`/api/user/userDashboard?preferences=${preferences}&excludedId=${loggedUser.id}&userLikes=${loggedUser.UserLikesID}&userDislikes=${loggedUser.UserDislikesID}`
|
`/api/user/userDashboard?preferences=${[
|
||||||
|
loggedUser.prefGender,
|
||||||
|
loggedUser.ageMin,
|
||||||
|
loggedUser.ageMax,
|
||||||
|
loggedUser.distance,
|
||||||
|
]}&excludedId=${loggedUser.id}&userLikes=${
|
||||||
|
loggedUser.UserLikesID
|
||||||
|
}&userDislikes=${loggedUser.UserDislikesID}`
|
||||||
) //exclure les profils déjà like ou dislike
|
) //exclure les profils déjà like ou dislike
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -89,7 +87,6 @@ export default function Dashboard() {
|
|||||||
position: "top",
|
position: "top",
|
||||||
});
|
});
|
||||||
if (status === "unauthenticated") router.push("/");
|
if (status === "unauthenticated") router.push("/");
|
||||||
return <span>Error: {error.message}</span>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
import { useToast } from "@chakra-ui/react";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
import LoadingPage from "@/components/LoadingPage";
|
||||||
|
import ErrorPage from "@/components/ErrorPage";
|
||||||
|
import Navbar from "@/components/Navbar";
|
||||||
|
|
||||||
|
export default function Map() {
|
||||||
|
const [location, setLocation] = useState([
|
||||||
|
null as unknown as number,
|
||||||
|
null as unknown as number,
|
||||||
|
]);
|
||||||
|
const toast = useToast({ position: "bottom" });
|
||||||
|
const idSaveToast = "saved_location";
|
||||||
|
const { data: session, status } = useSession();
|
||||||
|
|
||||||
|
//faire un useQuery pour récupérer les bars et restaurants et en meme temps regarder si l'user a une location
|
||||||
|
//Si oui, faire une mutation avec navigator.geolocation.getCurrentPosition pour mettre à jour la location de l'user dans la bdd
|
||||||
|
|
||||||
|
// cet url : https://data.opendatasoft.com/api/v2/catalog/datasets/osm-fr-bars%40babel/records?limit=100&offset=0&lang=fr&timezone=UTC
|
||||||
|
|
||||||
|
// ou : https://data.opendatasoft.com/api/v2/catalog/datasets/osm-fr-bars%40babel/exports/json?limit=-1&offset=0&lang=fr&timezone=UTC MAIS RENVOI UN file
|
||||||
|
|
||||||
|
const {
|
||||||
|
isLoading,
|
||||||
|
isError,
|
||||||
|
data: loggedUser,
|
||||||
|
error,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["LoggedUser"],
|
||||||
|
enabled: status === "authenticated",
|
||||||
|
queryFn: async () => {
|
||||||
|
const { user } = session as unknown as Session;
|
||||||
|
|
||||||
|
return fetch(`/api/users/${user.id}`)
|
||||||
|
.then((res) => {
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: listBars,
|
||||||
|
isError: isErrorListBars,
|
||||||
|
isLoading: isLoadingListBars,
|
||||||
|
error: errorListBars,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ["listBars"],
|
||||||
|
enabled: !isLoading && location[0] !== null,
|
||||||
|
queryFn: async () => {
|
||||||
|
let urlBars = new URL(
|
||||||
|
"https://data.opendatasoft.com/api/v2/catalog/datasets/osm-fr-bars%40babel/exports/json?"
|
||||||
|
);
|
||||||
|
|
||||||
|
const coordinates = location[1].toString() + " " + location[0].toString();
|
||||||
|
|
||||||
|
urlBars.searchParams.append(
|
||||||
|
"where",
|
||||||
|
`distance(geo_point_2d,geom'POINT(${coordinates})',75km)`
|
||||||
|
);
|
||||||
|
urlBars.searchParams.append("limit", "-1");
|
||||||
|
urlBars.searchParams.append("offset", "0");
|
||||||
|
urlBars.searchParams.append("timezone", `UTC`);
|
||||||
|
|
||||||
|
return fetch(urlBars.toString())
|
||||||
|
.then((res) => res.json())
|
||||||
|
.catch((err) => {
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const userSetLocation = useMutation({
|
||||||
|
mutationKey: "userSetLocation",
|
||||||
|
enabled: !isLoading && !loggedUser,
|
||||||
|
mutationFn: async (position: string) => {
|
||||||
|
const pos = {
|
||||||
|
location: position,
|
||||||
|
};
|
||||||
|
|
||||||
|
return fetch(`/api/users/${loggedUser.id}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(pos),
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
// if (!toast.isActive(idSaveToast)) {
|
||||||
|
// toast({
|
||||||
|
// id: idSaveToast,
|
||||||
|
// title: "Position enregistrée",
|
||||||
|
// description: "Votre position a bien été enregistrée",
|
||||||
|
// status: "success",
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
res.json();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
navigator.geolocation.getCurrentPosition((position) => {
|
||||||
|
setLocation([position.coords.latitude, position.coords.longitude]);
|
||||||
|
userSetLocation.mutate(
|
||||||
|
`${position.coords.latitude},${position.coords.longitude}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const MapWithNoSSR = dynamic(
|
||||||
|
() => import("../components/layout/map/MapComponent"),
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isLoading || isLoadingListBars ? (
|
||||||
|
<LoadingPage />
|
||||||
|
) : isError || isErrorListBars ? (
|
||||||
|
<ErrorPage />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Navbar />
|
||||||
|
<MapWithNoSSR
|
||||||
|
location={location}
|
||||||
|
loggedUser={loggedUser}
|
||||||
|
listBars={listBars}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -53,9 +53,9 @@ export default function UserProfile() {
|
|||||||
const [passions, setPassions] = useState(null);
|
const [passions, setPassions] = useState(null);
|
||||||
|
|
||||||
const [showTooltipAge, setShowTooltipAge] = useState(true);
|
const [showTooltipAge, setShowTooltipAge] = useState(true);
|
||||||
const [sliderAgeValue, setSliderAgeValue] = useState([]);
|
const [sliderAgeValue, setSliderAgeValue] = useState([] as number[]);
|
||||||
const [showTooltipDistance, setShowTooltipDistance] = useState(true);
|
// const [showTooltipDistance, setShowTooltipDistance] = useState(true);
|
||||||
const [sliderDistanceValue, setSliderDistanceValue] = useState([]);
|
// const [sliderDistanceValue, setSliderDistanceValue] = useState([]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -88,7 +88,7 @@ export default function UserProfile() {
|
|||||||
const { user } = session as unknown as Session;
|
const { user } = session as unknown as Session;
|
||||||
|
|
||||||
setSliderAgeValue([user.ageMin, user.ageMax]);
|
setSliderAgeValue([user.ageMin, user.ageMax]);
|
||||||
setSliderDistanceValue(user.distance);
|
// setSliderDistanceValue(user.distance);
|
||||||
|
|
||||||
return fetch(`/api/users/${user.id}`)
|
return fetch(`/api/users/${user.id}`)
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
@@ -110,10 +110,9 @@ export default function UserProfile() {
|
|||||||
position: "top",
|
position: "top",
|
||||||
});
|
});
|
||||||
if (status === "unauthenticated") router.push("/");
|
if (status === "unauthenticated") router.push("/");
|
||||||
return <span>Error: {error.message}</span>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTextGender = (gender) => {
|
const getTextGender = (gender: string) => {
|
||||||
switch (gender) {
|
switch (gender) {
|
||||||
case Gender.MALE:
|
case Gender.MALE:
|
||||||
return "Homme";
|
return "Homme";
|
||||||
|
|||||||
Reference in New Issue
Block a user