feat(like / dislike): Added possibility to like and dislike

This commit is contained in:
Laurian-Dufrechou
2023-04-08 15:20:38 +02:00
parent 5cfe91e6ca
commit b2325fee0f
5 changed files with 175 additions and 43 deletions
+3
View File
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules\\typescript\\lib"
}
+8
View File
@@ -43,6 +43,14 @@ model User {
OtherUserLikesID String[] @db.ObjectId OtherUserLikesID String[] @db.ObjectId
OtherUserLikes User[] @relation("Likes", fields: [OtherUserLikesID], references: [id]) OtherUserLikes User[] @relation("Likes", fields: [OtherUserLikesID], references: [id])
// Les personnes que l'utilisateur a dislike
UserDislikesID String[] @db.ObjectId
UserDislikes User[] @relation("Dislikes", fields: [UserDislikesID], references: [id])
// Les personnes qui aiment l'utilisateur
OtherUserDislikesID String[] @db.ObjectId
OtherUserDislikes User[] @relation("Dislikes", fields: [OtherUserDislikesID], references: [id])
MatchID String[] @db.ObjectId MatchID String[] @db.ObjectId
Match Match[] @relation(fields: [MatchID], references: [id]) Match Match[] @relation(fields: [MatchID], references: [id])
@@ -7,19 +7,118 @@ import {
Heading, Heading,
Box, Box,
CardHeader, CardHeader,
useToast,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import Carousel from "../../../Carousel"; import Carousel from "../../../Carousel";
import { BiHeart } from "react-icons/bi"; import { BiHeart } from "react-icons/bi";
import { RxCross1 } from "react-icons/rx"; import { RxCross1 } from "react-icons/rx";
import { useQuery } from "@tanstack/react-query"; import { useMutation, useQuery } from "@tanstack/react-query";
import PassionTagList from "@/components/layout/dashboard/card_user/PassionTagList"; import PassionTagList from "@/components/layout/dashboard/card_user/PassionTagList";
import { useState } from "react"; import { useState } from "react";
import SearchFailCard from "./SearchFailCard";
import LoadingPage from "@/components/LoadingPage";
export default function CardUser(props) { export default function CardUser(props) {
const { user, loggedUser, userLiked, setLiked, userDisliked, setDisliked } = const {
props; users,
loggedUser,
userLikes,
setUserLikes,
userDislikes,
setUserDislikes,
} = props;
const [hidden, setHidden] = useState(false); console.log(userLikes);
console.log(userDislikes);
const toast = useToast({
position: "top",
duration: 3000,
isClosable: true,
});
const [listUsers, setListUsers] = useState(users);
const likeMutation = useMutation({
mutationKey: "like",
mutationFn: async (id) => {
return fetch(`/api/users/${loggedUser.id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ UserLikesID: [...userLikes, id] }),
})
.then((res) => {
setUserLikes([...userLikes, user.id]);
toast({
title: "J'aime",
description: "Votre action a bien été prise en compte",
status: "success",
});
res.json();
})
.catch((err) => {
return err;
});
},
onError: (err) => {
toast({
title: "Erreur",
description: "Une erreur est survenue",
status: "error",
duration: 2000,
});
},
onSuccess: (data) => {
toast({
title: "J'aime",
description: "Votre action a bien été prise en compte",
status: "success",
duration: 2000,
});
},
});
const dislikeMutation = useMutation({
mutationKey: "dislike",
mutationFn: async (id) => {
return fetch(`/api/users/${loggedUser.id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ UserDislikesID: [...userDislikes, id] }),
})
.then((res) => {
setUserDislikes([...userDislikes, user.id]);
toast({
title: "J'aime pas",
description: "Votre action a bien été prise en compte",
status: "success",
});
res.json();
})
.catch((err) => {
return err;
});
},
onError: (err) => {
toast({
title: "Erreur",
description: "Une erreur est survenue",
status: "error",
duration: 2000,
});
},
onSuccess: (data) => {
toast({
title: "J'aime pas",
description: "Votre action a bien été prise en compte",
status: "success",
duration: 2000,
});
},
});
const { const {
isLoading: passionLoading, isLoading: passionLoading,
@@ -44,24 +143,25 @@ export default function CardUser(props) {
return Math.abs(ageDate.getUTCFullYear() - 1970); return Math.abs(ageDate.getUTCFullYear() - 1970);
}; };
if (listUsers.length === 0) {
return <SearchFailCard />;
}
if (likeMutation.isLoading || dislikeMutation.isLoading) {
return <LoadingPage />;
}
return ( return (
<Card <Card w={"100%"} h={"100%"} borderRadius={"1rem"} overflow={"hidden"}>
// position={"absolute"}
w={"100%"}
h={"100%"}
borderRadius={"1rem"}
overflow={"hidden"}
hidden={hidden}
>
<CardHeader> <CardHeader>
<Carousel borderRadius={"1rem"} images={user.images} /> <Carousel borderRadius={"1rem"} images={listUsers[0].images} />
</CardHeader> </CardHeader>
<CardBody> <CardBody>
<Flex justify={"space-between"} mb={"20px"}> <Flex justify={"space-between"} mb={"20px"}>
<Heading fontSize={"1.5rem"} fontWeight={"bold"} flexBasis={"70%"}> <Heading fontSize={"1.5rem"} fontWeight={"bold"} flexBasis={"70%"}>
{user.firstName} {user.lastName}, {formateDateToAge(user.birthdate)}{" "} {listUsers[0].firstName} {listUsers[0].lastName},{" "}
ans {formateDateToAge(listUsers[0].birthdate)} ans
</Heading> </Heading>
<Flex gap={1}> <Flex gap={1}>
@@ -69,8 +169,8 @@ export default function CardUser(props) {
borderRadius={"1rem"} borderRadius={"1rem"}
colorScheme={"purple"} colorScheme={"purple"}
onClick={() => { onClick={() => {
// setLiked([...userLiked, user.id]); likeMutation.mutate(listUsers[0].id);
setHidden(true); setListUsers(listUsers.slice(1));
}} }}
> >
<BiHeart /> <BiHeart />
@@ -79,7 +179,10 @@ export default function CardUser(props) {
borderRadius={"1rem"} borderRadius={"1rem"}
colorScheme={"purple"} colorScheme={"purple"}
variant={"outline"} variant={"outline"}
// onClick={setDisiked([...userDisliked, user.id])} onClick={() => {
dislikeMutation.mutate(listUsers[0].id);
setListUsers(listUsers.slice(1));
}}
> >
<RxCross1 /> <RxCross1 />
</IconButton> </IconButton>
@@ -90,7 +193,7 @@ export default function CardUser(props) {
<Heading size={"sm"} fontWeight={"bold"} mb="0.5rem"> <Heading size={"sm"} fontWeight={"bold"} mb="0.5rem">
A propos : A propos :
</Heading> </Heading>
<Text as="i">&quot;{user.bio}&quot;</Text> <Text as="i">&quot;{listUsers[0].bio}&quot;</Text>
</Box> </Box>
<Box> <Box>
@@ -103,7 +206,7 @@ export default function CardUser(props) {
<Text>Erreur lors du chargement des passions</Text> <Text>Erreur lors du chargement des passions</Text>
) : ( ) : (
<PassionTagList <PassionTagList
passions={user.PassionID} passions={listUsers[0].PassionID}
userPassions={loggedUser.PassionID} userPassions={loggedUser.PassionID}
listPassions={listPassions} listPassions={listPassions}
/> />
+18 -4
View File
@@ -1,7 +1,20 @@
import { error } from "console";
const { PrismaClient } = require("@prisma/client"); const { PrismaClient } = require("@prisma/client");
const get = async (req, res) => { const get = async (req, res) => {
const { preference, excludedId } = req.query; const { preference, excludedId, userLikes, userDislikes } = req.query;
let userLikesList = userLikes.split(",");
let userDislikesList = userDislikes.split(",");
if (userLikesList[0] === "") {
userLikesList = [];
}
if (userDislikesList[0] === "") {
userDislikesList = [];
}
const excludedIdArray = [excludedId, ...userLikesList, ...userDislikesList];
const prisma = new PrismaClient(); const prisma = new PrismaClient();
// a terme mettre l'age, la distance // a terme mettre l'age, la distance
const users = await prisma.user const users = await prisma.user
@@ -9,15 +22,16 @@ const get = async (req, res) => {
where: { where: {
AND: [ AND: [
{ gender: { equals: preference } }, { gender: { equals: preference } },
{ images: { isEmpty: false }, NOT: { id: { equals: excludedId } } }, { images: { isEmpty: false } },
{ id: { notIn: excludedIdArray } },
], ],
}, },
}) })
.catch((e) => { .catch((e) => {
return null; return e;
}); });
if (!users) { if (!users) {
return res.status(500).send({ message: "Internal server error" }); return res.status(500).send({ error: "Aucun profil trouvé" });
} }
return res.status(200).send({ users }); return res.status(200).send({ users });
}; };
+18 -14
View File
@@ -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 { useState } from "react"; import { useEffect, 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,8 +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 [liked, setLiked] = useState(null); const [userLikes, setUserLikes] = useState();
const [disliked, setDisliked] = useState(null); const [userDislikes, setUserDislikes] = useState();
const { data: session, status } = useSession(); const { data: session, status } = useSession();
@@ -32,8 +32,13 @@ export default function Dashboard() {
queryFn: async () => { queryFn: async () => {
const { user } = session as unknown as Session; const { user } = session as unknown as Session;
setUserDislikes([...user.UserDislikesID]);
setUserLikes([...user.UserLikesID]);
return fetch(`/api/users/${user.id}`) return fetch(`/api/users/${user.id}`)
.then((res) => res.json()) .then((res) => {
return res.json();
})
.catch((err) => { .catch((err) => {
return err; return err;
}); });
@@ -50,7 +55,7 @@ export default function Dashboard() {
enabled: status === "authenticated" && !isLoading, enabled: status === "authenticated" && !isLoading,
queryFn: async () => { queryFn: async () => {
return fetch( return fetch(
`/api/user/userDashboard?preference=${loggedUser.gender}&excludedId=${loggedUser.id}` `/api/user/userDashboard?preference=${loggedUser.gender}&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) => {
@@ -93,21 +98,20 @@ export default function Dashboard() {
<Box py={3}> <Box py={3}>
{isLoadingListUsers ? ( {isLoadingListUsers ? (
<LoadingPage /> <LoadingPage />
) : listUsers.users.length === 0 && listUsers.users === null ? ( ) : isErrorListUsers ||
listUsers.users === undefined ||
listUsers.users.length === 0 ? (
<SearchFailCard /> <SearchFailCard />
) : ( ) : (
listUsers.users.map((user: any) => (
// dans cardUser, mettre une liste de user, utiliser le user[0] et quand like ou dislike, supprimer le user[0] de la liste // dans cardUser, mettre une liste de user, utiliser le user[0] et quand like ou dislike, supprimer le user[0] de la liste
<CardUser <CardUser
key={user.id} users={listUsers.users}
user={user}
loggedUser={loggedUser} loggedUser={loggedUser}
userLiked={liked} userLikes={userLikes}
setLiked={setLiked} setUserLikes={setUserLikes}
userDisliked={disliked} userDislikes={userDislikes}
setDisliked={setDisliked} setUserDislikes={setUserDislikes}
/> />
))
)} )}
</Box> </Box>
</GridItem> </GridItem>