feat(Preferences): Choose preferences -- Fetch user from pref

This commit is contained in:
Laurian-Dufrechou
2023-04-09 14:27:49 +02:00
parent b2325fee0f
commit d10c7fcc71
7 changed files with 239 additions and 51 deletions
+8 -1
View File
@@ -24,6 +24,13 @@ model User {
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
// Les préférences de l'utilisateur
distance Int @default(100)
ageMax Int @default(99)
ageMin Int @default(18)
prefGender Gender @default(UNKNOWN)
// Liste des chats de l'utilisateur // Liste des chats de l'utilisateur
ChatID String[] @db.ObjectId ChatID String[] @db.ObjectId
Chat Chat[] @relation(fields: [ChatID], references: [id]) Chat Chat[] @relation(fields: [ChatID], references: [id])
@@ -128,4 +135,4 @@ enum NotificationType {
enum Role { enum Role {
USER USER
ADMIN ADMIN
} }
+4 -1
View File
@@ -27,8 +27,11 @@ const Carousel = ({ images, borderRadius: bRadius }: Props) => {
borderRadius={bRadius} borderRadius={bRadius}
overflow={"hidden"} overflow={"hidden"}
justify={"space-between"} justify={"space-between"}
bgColor={"purple.50"}
bgImage={images[currentIndex]} bgImage={images[currentIndex]}
bgSize={"cover"} bgSize={"contain"}
bgRepeat={"no-repeat"}
bgPosition={"center"}
width={"100%"} width={"100%"}
height={500} height={500}
> >
@@ -28,12 +28,9 @@ export default function CardUser(props) {
setUserDislikes, setUserDislikes,
} = props; } = props;
console.log(userLikes);
console.log(userDislikes);
const toast = useToast({ const toast = useToast({
position: "top", position: "top",
duration: 3000, duration: 2000,
isClosable: true, isClosable: true,
}); });
const [listUsers, setListUsers] = useState(users); const [listUsers, setListUsers] = useState(users);
@@ -66,7 +63,6 @@ export default function CardUser(props) {
title: "Erreur", title: "Erreur",
description: "Une erreur est survenue", description: "Une erreur est survenue",
status: "error", status: "error",
duration: 2000,
}); });
}, },
onSuccess: (data) => { onSuccess: (data) => {
@@ -74,7 +70,6 @@ export default function CardUser(props) {
title: "J'aime", title: "J'aime",
description: "Votre action a bien été prise en compte", description: "Votre action a bien été prise en compte",
status: "success", status: "success",
duration: 2000,
}); });
}, },
}); });
@@ -154,7 +149,7 @@ export default function CardUser(props) {
return ( return (
<Card w={"100%"} h={"100%"} borderRadius={"1rem"} overflow={"hidden"}> <Card w={"100%"} h={"100%"} borderRadius={"1rem"} overflow={"hidden"}>
<CardHeader> <CardHeader>
<Carousel borderRadius={"1rem"} images={listUsers[0].images} /> <Carousel borderRadius={"1rem"} images={listUsers?.[0].images} />
</CardHeader> </CardHeader>
<CardBody> <CardBody>
@@ -39,7 +39,12 @@ export default function LeftPanel(props) {
{user.images.length === 0 ? ( {user.images.length === 0 ? (
<Image src={"/blank_profile_picture.webp"} borderRadius={"1rem"} /> <Image src={"/blank_profile_picture.webp"} borderRadius={"1rem"} />
) : ( ) : (
<Image src={user.images[0]} borderRadius={"1rem"} /> <Image
src={user.images[0]}
borderRadius={"1rem"}
objectFit={"contain"}
width={"100%"}
/>
)} )}
<Box mt={"2rem"}> <Box mt={"2rem"}>
<Flex align={"center"} justifyContent="space-between" mb={"1rem"}> <Flex align={"center"} justifyContent="space-between" mb={"1rem"}>
+29 -6
View File
@@ -1,9 +1,26 @@
import { error } from "console";
const { PrismaClient } = require("@prisma/client"); const { PrismaClient } = require("@prisma/client");
const birthDateFromAge = (age) => {
const ageMillis = age * 365 * 24 * 60 * 60 * 1000;
return new Date(new Date().getTime() - ageMillis);
};
const get = async (req, res) => { const get = async (req, res) => {
const { preference, excludedId, userLikes, userDislikes } = req.query; const {
preferences: preferencesList,
excludedId,
userLikes,
userDislikes,
} = req.query;
const preferences = preferencesList.split(",");
const prefGender = preferences[0];
const dateAgeMin = birthDateFromAge(preferences[1]);
const dateAgeMax = birthDateFromAge(preferences[2]);
// pas utilisé pour le moment
const distance = preferences[3];
let userLikesList = userLikes.split(","); let userLikesList = userLikes.split(",");
let userDislikesList = userDislikes.split(","); let userDislikesList = userDislikes.split(",");
@@ -21,16 +38,22 @@ const get = async (req, res) => {
.findMany({ .findMany({
where: { where: {
AND: [ AND: [
{ gender: { equals: preference } }, { gender: { equals: prefGender } },
{
birthdate: {
lte: dateAgeMin.toISOString(),
gte: dateAgeMax.toISOString(),
},
},
{ images: { isEmpty: false } }, { images: { isEmpty: false } },
{ id: { notIn: excludedIdArray } }, { id: { notIn: excludedIdArray } },
], ],
}, },
}) })
.catch((e) => { .catch((e) => {
return e; return [];
}); });
if (!users) { if (users.length === 0 || users === undefined || users === null) {
return res.status(500).send({ error: "Aucun profil trouvé" }); return res.status(500).send({ error: "Aucun profil trouvé" });
} }
return res.status(200).send({ users }); return res.status(200).send({ users });
+15 -1
View File
@@ -19,6 +19,8 @@ export default function Dashboard() {
const [userLikes, setUserLikes] = useState(); const [userLikes, setUserLikes] = useState();
const [userDislikes, setUserDislikes] = useState(); const [userDislikes, setUserDislikes] = useState();
const [preferences, setPreferences] = useState(null);
const { data: session, status } = useSession(); const { data: session, status } = useSession();
const { const {
@@ -35,6 +37,13 @@ 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();
@@ -45,6 +54,10 @@ export default function Dashboard() {
}, },
}); });
/*
Erreur quand je retourn de userProfile à dashboard
*/
const { const {
data: listUsers, data: listUsers,
isError: isErrorListUsers, isError: isErrorListUsers,
@@ -55,7 +68,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}&userLikes=${loggedUser.UserLikesID}&userDislikes=${loggedUser.UserDislikesID}` `/api/user/userDashboard?preferences=${preferences}&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) => {
@@ -99,6 +112,7 @@ export default function Dashboard() {
{isLoadingListUsers ? ( {isLoadingListUsers ? (
<LoadingPage /> <LoadingPage />
) : isErrorListUsers || ) : isErrorListUsers ||
listUsers === undefined ||
listUsers.users === undefined || listUsers.users === undefined ||
listUsers.users.length === 0 ? ( listUsers.users.length === 0 ? (
<SearchFailCard /> <SearchFailCard />
+175 -34
View File
@@ -20,7 +20,16 @@ import {
HStack, HStack,
Radio, Radio,
RadioGroup, RadioGroup,
RangeSlider,
RangeSliderFilledTrack,
RangeSliderThumb,
RangeSliderTrack,
Slider,
SliderFilledTrack,
SliderThumb,
SliderTrack,
Text, Text,
Tooltip,
useToast, useToast,
VStack, VStack,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
@@ -30,6 +39,8 @@ import ModalChoosePassion from "@/components/layout/user_profile/ModalChoosePass
import ProfileTagList from "@/components/layout/user_profile/ProfileTagList"; import ProfileTagList from "@/components/layout/user_profile/ProfileTagList";
import LoadingPage from "@/components/LoadingPage"; import LoadingPage from "@/components/LoadingPage";
import { FaGreaterThan, FaLessThan, FaWalking } from "react-icons/fa";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm, Controller } from "react-hook-form"; import { useForm, Controller } from "react-hook-form";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
@@ -41,6 +52,11 @@ export default function UserProfile() {
const [currentlyLoading, setCurrentlyLoading] = useState(false); const [currentlyLoading, setCurrentlyLoading] = useState(false);
const [passions, setPassions] = useState(null); const [passions, setPassions] = useState(null);
const [showTooltipAge, setShowTooltipAge] = useState(true);
const [sliderAgeValue, setSliderAgeValue] = useState([]);
const [showTooltipDistance, setShowTooltipDistance] = useState(true);
const [sliderDistanceValue, setSliderDistanceValue] = useState([]);
const { const {
handleSubmit, handleSubmit,
control, control,
@@ -71,6 +87,9 @@ export default function UserProfile() {
queryFn: async () => { queryFn: async () => {
const { user } = session as unknown as Session; const { user } = session as unknown as Session;
setSliderAgeValue([user.ageMin, user.ageMax]);
setSliderDistanceValue(user.distance);
return fetch(`/api/users/${user.id}`) return fetch(`/api/users/${user.id}`)
.then((res) => res.json()) .then((res) => res.json())
.catch((err) => { .catch((err) => {
@@ -108,12 +127,19 @@ export default function UserProfile() {
}; };
const saveData = (values: any) => { const saveData = (values: any) => {
const trueValues = Object.keys(values).reduce((acc, key) => { let trueValues = {};
if (values[key] !== "" && values[key] !== undefined) { console.log(values);
acc[key] = values[key];
for (const [key, value] of Object.entries(values)) {
if (value !== "" && value !== undefined) {
if (key === "age") {
trueValues["ageMin"] = value[0];
trueValues["ageMax"] = value[1];
} else {
trueValues[key] = value;
}
} }
return acc; }
}, {});
const options = { const options = {
method: "PATCH", method: "PATCH",
@@ -392,35 +418,148 @@ export default function UserProfile() {
)} )}
/> />
</Box> </Box>
</Box>
<Divider colorScheme={"purple"} />
<Box my={"1rem"}>
<Center>
<Text as={"b"} fontSize={"1.5rem"} my={"1rem"}>
Préférences
</Text>
</Center>
<Box my={"1rem"}>
<FormLabel as={"legend"} htmlFor={"prefGender"}>
Genre :
</FormLabel>
<Controller
name={"prefGender"}
control={control}
render={({ field }) => (
<RadioGroup
{...field}
colorScheme={"purple"}
id={"prefGender"}
as="b"
defaultValue={
userData.prefGender === null
? Gender.UNKNOWN
: userData.gender
}
>
<HStack spacing={"0.5rem"}>
<Radio value={Gender.MALE}>
{getTextGender(Gender.MALE)}
</Radio>
<Radio value={Gender.FEMALE}>
{getTextGender(Gender.FEMALE)}
</Radio>
<Radio value={Gender.OTHER}>
{getTextGender(Gender.OTHER)}
</Radio>
<Radio value={Gender.UNKNOWN}>
{getTextGender(Gender.UNKNOWN)}
</Radio>
</HStack>
</RadioGroup>
)}
/>
</Box>
<Box>
<FormLabel as={"legend"} htmlFor={"prefGender"}>
Age :
</FormLabel>
<Controller
name={"age"}
control={control}
render={({ field: { onChange } }) => (
<RangeSlider
aria-label={["min", "max"]}
colorScheme={"purple"}
min={18}
max={99}
id={"age"}
color={"pink.500"}
defaultValue={[userData.ageMin, userData.ageMax]}
onChange={(v) => {
setSliderAgeValue(v);
onChange(v);
}}
onMouseEnter={() => setShowTooltipAge(true)}
onMouseLeave={() => setShowTooltipAge(false)}
>
<RangeSliderTrack>
<RangeSliderFilledTrack bgColor={"purple.500"} />
</RangeSliderTrack>
<Tooltip
hasArrow
bg="purple.500"
color="white"
placement="top"
isOpen={showTooltipAge}
label={`${sliderAgeValue[0]}`}
>
<RangeSliderThumb boxSize={6} index={0}>
<Box color={"purple.500"} as={FaLessThan} />
</RangeSliderThumb>
</Tooltip>
<Tooltip
hasArrow
bg="purple.500"
color="white"
placement="top"
isOpen={showTooltipAge}
label={`${sliderAgeValue[1]}`}
>
<RangeSliderThumb boxSize={6} index={1}>
<Box color={"purple.500"} as={FaGreaterThan} />
</RangeSliderThumb>
</Tooltip>
</RangeSlider>
)}
/>
</Box>
{/* <Box> {/* <Box>
<FormLabel as={"legend"} htmlFor={"preference"}> <FormLabel as={"legend"} htmlFor={"distance"}>
Préference : Distance :
</FormLabel> </FormLabel>
<RadioGroup <Controller
id={"preference"} name={"distance"}
as="b" control={control}
value={ render={({ field: { onChange } }) => (
userData.preference === null <Slider
? Gender.UNKNOWN aria-label={"distance"}
: userData.preference colorScheme={"purple"}
} min={20}
> max={250}
<HStack spacing={"0.5rem"}> id={"distance"}
<Radio value={Gender.MALE}> color={"pink.500"}
{getTextGender(Gender.MALE)} defaultValue={userData.distance}
</Radio> onChange={(v) => {
<Radio value={Gender.FEMALE}> setSliderDistanceValue(v);
{getTextGender(Gender.FEMALE)} onChange(v);
</Radio> }}
<Radio value={Gender.OTHER}> onMouseEnter={() => setShowTooltipDistance(true)}
{getTextGender(Gender.OTHER)} onMouseLeave={() => setShowTooltipDistance(false)}
</Radio> >
<Radio value={Gender.UNKNOWN}> <SliderTrack>
{getTextGender(Gender.UNKNOWN)} <SliderFilledTrack bgColor={"purple.500"} />
</Radio> </SliderTrack>
</HStack> <Tooltip
</RadioGroup> hasArrow
</Flex> */} bg="purple.500"
color="white"
placement="top"
isOpen={showTooltipDistance}
label={`${sliderDistanceValue} km`}
>
<SliderThumb boxSize={6}>
<Box color={"purple.500"} as={FaWalking} />
</SliderThumb>
</Tooltip>
</Slider>
)}
/>
</Box> */}
</Box> </Box>
<Divider colorScheme={"purple"} /> <Divider colorScheme={"purple"} />
<Center gap={"1rem"} my={"1rem"}> <Center gap={"1rem"} my={"1rem"}>
@@ -434,7 +573,9 @@ export default function UserProfile() {
<Button <Button
colorScheme={"purple"} colorScheme={"purple"}
variant="outline" variant="outline"
onClick={() => router.push("/dashboard")} onClick={() => {
router.push("/dashboard");
}}
> >
Retour Retour
</Button> </Button>