mirror of
https://github.com/LucasVbr/meeting-app.git
synced 2026-05-13 17:21:53 +00:00
fix: add types and cleanup code
This commit is contained in:
@@ -8,12 +8,12 @@ import {
|
||||
Input,
|
||||
Container,
|
||||
FormErrorMessage,
|
||||
} from "@chakra-ui/react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
import { signIn, SignInResponse } from "next-auth/react";
|
||||
import { RegisterData } from "@/models/form/RegisterData";
|
||||
import { useForm } from "react-hook-form";
|
||||
} from '@chakra-ui/react';
|
||||
import {useRouter} from 'next/router';
|
||||
import {useState} from 'react';
|
||||
import {signIn, SignInResponse} from 'next-auth/react';
|
||||
import {RegisterData} from '@/models/form/RegisterData';
|
||||
import {SubmitHandler, useForm} from 'react-hook-form';
|
||||
|
||||
export default function RegisterForm() {
|
||||
const router = useRouter();
|
||||
@@ -22,25 +22,23 @@ export default function RegisterForm() {
|
||||
handleSubmit,
|
||||
register,
|
||||
watch,
|
||||
formState: { errors, isSubmitting },
|
||||
formState: {errors, isSubmitting},
|
||||
} = useForm();
|
||||
|
||||
const buttonWidth = { base: "100%", md: "unset" };
|
||||
|
||||
const validateDate = (value: string) => {
|
||||
const selected = new Date(value).getFullYear();
|
||||
const now = new Date().getFullYear();
|
||||
return now - selected >= 18 || "Vous devez avoir 18 ans ou plus";
|
||||
return now - selected >= 18 || 'Vous devez avoir 18 ans ou plus';
|
||||
};
|
||||
|
||||
const registerUser = (values: RegisterData) => {
|
||||
let { email, firstName, lastName, birthdate, password, confirmPassword } =
|
||||
values;
|
||||
const submitHandler: SubmitHandler<any> = (values: RegisterData) => {
|
||||
let {email, firstName, lastName, birthdate, password, confirmPassword} =
|
||||
values;
|
||||
const date = new Date(birthdate);
|
||||
|
||||
const options = {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
firstName,
|
||||
@@ -50,143 +48,142 @@ export default function RegisterForm() {
|
||||
}),
|
||||
};
|
||||
|
||||
fetch("/api/users", options)
|
||||
.then(() => {
|
||||
signIn("credentials", { email, password, redirect: false }).then(
|
||||
fetch('/api/users', options).then(() => {
|
||||
signIn('credentials', {email, password, redirect: false}).then(
|
||||
(res: unknown) => {
|
||||
const { ok: connexionSuccess } = res as SignInResponse;
|
||||
const {ok: connexionSuccess} = res as SignInResponse;
|
||||
|
||||
// TODO If success -> goto interactive form else login
|
||||
router.push(connexionSuccess ? "/dashboard" : "/");
|
||||
}
|
||||
);
|
||||
})
|
||||
.catch(() => {});
|
||||
router.push(connexionSuccess ? '/dashboard' : '/');
|
||||
},
|
||||
);
|
||||
}).catch((err) => console.error(err));
|
||||
};
|
||||
|
||||
return (
|
||||
<Box flexBasis={"100%"}>
|
||||
<Container>
|
||||
<form id="register_form" onSubmit={handleSubmit(registerUser)}>
|
||||
<Heading textAlign={"center"} size={"2xl"}>
|
||||
Inscription
|
||||
</Heading>
|
||||
<Box flexBasis={'100%'}>
|
||||
<Container>
|
||||
<form id="register_form" onSubmit={handleSubmit(submitHandler)}>
|
||||
<Heading textAlign={'center'} size={'2xl'}>
|
||||
Inscription
|
||||
</Heading>
|
||||
|
||||
<Flex mt={"100px"} mb={"1rem"} gap={5}>
|
||||
{/*Prénom*/}
|
||||
<FormControl id="firstName" isInvalid={errors.firstName}>
|
||||
<FormLabel>Prénom</FormLabel>
|
||||
<Flex mt={'100px'} mb={'1rem'} gap={5}>
|
||||
{/*Prénom*/}
|
||||
<FormControl id="firstName" isInvalid={errors.firstName as boolean|undefined}>
|
||||
<FormLabel>Prénom</FormLabel>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Prénom"
|
||||
{...register('firstName', {
|
||||
required: {value: true, message: 'Prénom requis'},
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.firstName?.message as string}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/*Nom*/}
|
||||
<FormControl id="lastName" isInvalid={errors.lastName as boolean|undefined}>
|
||||
<FormLabel>Nom</FormLabel>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Nom"
|
||||
{...register('lastName', {
|
||||
required: {value: true, message: 'Nom requis'},
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.lastName?.message as string}</FormErrorMessage>
|
||||
</FormControl>
|
||||
</Flex>
|
||||
|
||||
{/*Email*/}
|
||||
<FormControl mb={'1rem'} id={'email'} isInvalid={errors.email as boolean|undefined}>
|
||||
<FormLabel>Adresse email</FormLabel>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Prénom"
|
||||
{...register("firstName", {
|
||||
required: { value: true, message: "Prénom requis" },
|
||||
})}
|
||||
type="text"
|
||||
{...register('email', {
|
||||
required: {value: true, message: 'Adresse email requise'},
|
||||
pattern: {
|
||||
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
||||
message: 'Adresse email invalide',
|
||||
},
|
||||
})}
|
||||
placeholder="adresse@email.com"
|
||||
/>
|
||||
<FormErrorMessage>{errors.firstName?.message}</FormErrorMessage>
|
||||
<FormErrorMessage>{errors.email?.message as string}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/*Nom*/}
|
||||
<FormControl id="lastName" isInvalid={errors.lastName}>
|
||||
<FormLabel>Nom</FormLabel>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Nom"
|
||||
{...register("lastName", {
|
||||
required: { value: true, message: "Nom requis" },
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.lastName?.message}</FormErrorMessage>
|
||||
</FormControl>
|
||||
</Flex>
|
||||
|
||||
{/*Email*/}
|
||||
<FormControl mb={"1rem"} id={"email"} isInvalid={errors.email}>
|
||||
<FormLabel>Adresse email</FormLabel>
|
||||
<Input
|
||||
type="text"
|
||||
{...register("email", {
|
||||
required: { value: true, message: "Adresse email requise" },
|
||||
pattern: {
|
||||
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
||||
message: "Adresse email invalide",
|
||||
},
|
||||
})}
|
||||
placeholder="adresse@email.com"
|
||||
/>
|
||||
<FormErrorMessage>{errors.email?.message}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/*Date de naissance*/}
|
||||
<FormControl
|
||||
mb={"1rem"}
|
||||
id={"birthdate"}
|
||||
isInvalid={errors.birthdate}
|
||||
>
|
||||
<FormLabel>Date de naissance</FormLabel>
|
||||
<Input
|
||||
type="date"
|
||||
{...register("birthdate", {
|
||||
required: { value: true, message: "Date de naissance requise" },
|
||||
validate: validateDate,
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.birthdate?.message}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/*Mot de passe*/}
|
||||
<FormControl mb={"1rem"} id="password" isInvalid={errors.password}>
|
||||
<FormLabel>Mot de passe</FormLabel>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Mot de passe"
|
||||
{...register("password", {
|
||||
required: { value: true, message: "Mot de passe requis" },
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.password?.message}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/*Mot de passe (2)*/}
|
||||
<FormControl
|
||||
mb={"1rem"}
|
||||
id="confirmPassword"
|
||||
isInvalid={errors.confirmPassword}
|
||||
>
|
||||
<FormLabel>Confirmation du mot de passe</FormLabel>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Mot de passe"
|
||||
{...register("confirmPassword", {
|
||||
required: { value: true, message: "Confirmation requise" },
|
||||
validate: (value: string) => {
|
||||
return (
|
||||
watch("password") === value ||
|
||||
"Les mots de passe ne correspondent pas"
|
||||
);
|
||||
},
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>
|
||||
{errors.confirmPassword?.message}
|
||||
</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
<Flex mt={"50px"} w={"100%"} justify={"space-between"} gap={5}>
|
||||
<Button onClick={() => router.push("/")} w={buttonWidth}>
|
||||
Retour
|
||||
</Button>
|
||||
<Button
|
||||
isLoading={isSubmitting}
|
||||
w={buttonWidth}
|
||||
colorScheme="purple"
|
||||
type="submit"
|
||||
{/*Date de naissance*/}
|
||||
<FormControl
|
||||
mb={'1rem'}
|
||||
id={'birthdate'}
|
||||
isInvalid={errors.birthdate as boolean|undefined}
|
||||
>
|
||||
Je m'inscris
|
||||
</Button>
|
||||
</Flex>
|
||||
</form>
|
||||
</Container>
|
||||
</Box>
|
||||
<FormLabel>Date de naissance</FormLabel>
|
||||
<Input
|
||||
type="date"
|
||||
{...register('birthdate', {
|
||||
required: {
|
||||
value: true,
|
||||
message: 'Date de naissance requise',
|
||||
},
|
||||
validate: validateDate,
|
||||
})}
|
||||
/>
|
||||
{ (errors.birthdate) ? <FormErrorMessage>{errors.birthdate.message as string}</FormErrorMessage> : "" }
|
||||
</FormControl>
|
||||
|
||||
{/*Mot de passe*/}
|
||||
<FormControl mb={'1rem'} id="password" isInvalid={errors.password as boolean|undefined}>
|
||||
<FormLabel>Mot de passe</FormLabel>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Mot de passe"
|
||||
{...register('password', {
|
||||
required: {value: true, message: 'Mot de passe requis'},
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.password?.message as string}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
{/*Mot de passe (2)*/}
|
||||
<FormControl
|
||||
mb={'1rem'}
|
||||
id="confirmPassword"
|
||||
isInvalid={errors.confirmPassword as boolean|undefined}
|
||||
>
|
||||
<FormLabel>Confirmation du mot de passe</FormLabel>
|
||||
<Input
|
||||
type="password"
|
||||
placeholder="Mot de passe"
|
||||
{...register('confirmPassword', {
|
||||
required: {value: true, message: 'Confirmation requise'},
|
||||
validate: (value: string) => {
|
||||
return (
|
||||
watch('password') === value ||
|
||||
'Les mots de passe ne correspondent pas'
|
||||
);
|
||||
},
|
||||
})}
|
||||
/>
|
||||
<FormErrorMessage>{errors.confirmPassword?.message as string}</FormErrorMessage>
|
||||
</FormControl>
|
||||
|
||||
<Flex mt={'50px'} w={'100%'} justify={'space-between'} gap={5}>
|
||||
<Button onClick={() => router.push('/')} w={{base: '100%', md: 'unset'}}>
|
||||
Retour
|
||||
</Button>
|
||||
<Button
|
||||
isLoading={isSubmitting}
|
||||
w={{base: '100%', md: 'unset'}}
|
||||
colorScheme="purple"
|
||||
type="submit"
|
||||
>
|
||||
Je m'inscris
|
||||
</Button>
|
||||
</Flex>
|
||||
</form>
|
||||
</Container>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import NextAuth from 'next-auth';
|
||||
import CredentialsProvider from 'next-auth/providers/credentials';
|
||||
import {NextApiRequest, NextApiResponse} from 'next';
|
||||
|
||||
import {LoginData} from '@/models/form/LoginData';
|
||||
import {isSamePassword} from '@/lib/PasswordTools';
|
||||
import {User} from '@prisma/client';
|
||||
|
||||
import type {User} from '@prisma/client';
|
||||
import prismaClient from '@/lib/prismaClient';
|
||||
|
||||
export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -11,27 +13,19 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
CredentialsProvider({
|
||||
name: 'Credentials',
|
||||
credentials: {
|
||||
email: {
|
||||
label: 'Email',
|
||||
type: 'text',
|
||||
placeholder: 'adresse@email.com'
|
||||
},
|
||||
password: {
|
||||
label: 'Password',
|
||||
type: 'password',
|
||||
placeholder: 'mot de passe',
|
||||
},
|
||||
email: {label: 'Email', type: 'text'},
|
||||
password: {label: 'Password', type: 'password'},
|
||||
},
|
||||
async authorize(credentials: unknown) {
|
||||
const {email, password} = credentials as LoginData;
|
||||
if (!email || !password) return null;
|
||||
|
||||
// Appel à la base de donnée
|
||||
const user = await getUserByEmail(email);
|
||||
const user: User | null = await getUserByEmail(email);
|
||||
if (!user) return null;
|
||||
|
||||
// Vérification de la connexion
|
||||
const passwordIsValid = await isSamePassword(password, user.password);
|
||||
const passwordIsValid: boolean = await isSamePassword(password, user.password);
|
||||
if (passwordIsValid) return user;
|
||||
else return null;
|
||||
},
|
||||
@@ -46,7 +40,7 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
signOut: '/auth/signout',
|
||||
error: '/auth/error',
|
||||
verifyRequest: '/auth/verify-request',
|
||||
newUser: '/auth/new-user' // New users will be directed here on first sign in (leave the property out if not of interest)
|
||||
newUser: '/auth/new-user', // New users will be directed here on first sign in (leave the property out if not of interest)
|
||||
},
|
||||
secret: process.env.NEXTAUTH_SECRET,
|
||||
callbacks: {
|
||||
@@ -62,6 +56,6 @@ export default async function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
async function getUserByEmail(email: string): Promise<null | User> {
|
||||
return prismaClient.user.findUnique({
|
||||
where: {email}
|
||||
where: {email},
|
||||
});
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import {Server} from 'socket.io';
|
||||
import prismaClient from '@/lib/prismaClient';
|
||||
import type {Chat, Message as Message} from '@prisma/client';
|
||||
|
||||
export default async function SocketHandler(req: any, res: any) {
|
||||
const {id: chatId} = req.query;
|
||||
|
||||
// It means that socket server was already initialised
|
||||
if (res.socket.server.io) {
|
||||
console.log('Already set up');
|
||||
res.end();
|
||||
@@ -14,17 +14,13 @@ export default async function SocketHandler(req: any, res: any) {
|
||||
const io = new Server(res.socket.server);
|
||||
res.socket.server.io = io;
|
||||
|
||||
// Define actions inside
|
||||
io.on('connection', async (socket) => {
|
||||
console.log(socket.id);
|
||||
io.on('connection', async (socket): Promise<void> => {
|
||||
|
||||
await prismaClient.chat.findFirst({
|
||||
where: {id: chatId},
|
||||
include: {Message: true},
|
||||
}).then(chat => {
|
||||
// @ts-ignore
|
||||
return socket.emit('allOldMessages', chat.Message);
|
||||
});
|
||||
where: {id: chatId}, include: {Message: true},
|
||||
}).then((chat: (Chat & { Message: Message[] }) | null) =>
|
||||
{if (chat) socket.emit('allOldMessages', chat.Message)}
|
||||
);
|
||||
|
||||
socket.on('createdMessage', async (msgInput) => {
|
||||
await prismaClient.message.create({
|
||||
@@ -33,10 +29,9 @@ export default async function SocketHandler(req: any, res: any) {
|
||||
User: {connect: {id: msgInput.sender}},
|
||||
Chat: {connect: {id: chatId}},
|
||||
},
|
||||
}).then((newMessage) => socket.emit('newIncomingMessage', newMessage));
|
||||
}).then((newMessage: Message) => socket.emit('newIncomingMessage', newMessage));
|
||||
});
|
||||
});
|
||||
|
||||
console.log('Setting up socket');
|
||||
res.end();
|
||||
}
|
||||
+9
-19
@@ -3,12 +3,12 @@ import Head from 'next/head';
|
||||
import {websiteName} from '@/lib/constants';
|
||||
import {useSession} from 'next-auth/react';
|
||||
import {useRouter} from 'next/router';
|
||||
import {useCallback, useEffect, useState} from 'react';
|
||||
import {useEffect, useState} from 'react';
|
||||
|
||||
import MessageList from '@/components/chat/MessageList';
|
||||
|
||||
import {io, Socket} from 'socket.io-client';
|
||||
import {Message} from '@prisma/client';
|
||||
import {Message, User} from '@prisma/client';
|
||||
|
||||
export default function ChatId() {
|
||||
const router = useRouter();
|
||||
@@ -26,22 +26,13 @@ export default function ChatId() {
|
||||
|
||||
const socketInitializer = async () => {
|
||||
await fetch(`/api/socket/chat/${chatId}`)
|
||||
const soc = io()
|
||||
const soc = io();
|
||||
|
||||
soc.on('connect', () => {
|
||||
console.log('connected')
|
||||
})
|
||||
|
||||
soc.on("allOldMessages", (allOldMessages: Message[]) => {
|
||||
console.log("allOldMessages", allOldMessages);
|
||||
setMessages(allOldMessages);
|
||||
})
|
||||
|
||||
soc.on("newIncomingMessage", (newIncomingMessage: Message) => {
|
||||
console.log("newIncomingMessage", newIncomingMessage);
|
||||
console.log("messages", messages);
|
||||
setMessages(messages => ([...messages, newIncomingMessage]));
|
||||
});
|
||||
soc.on('connect', () => console.log('connected'))
|
||||
soc.on("allOldMessages", (allOldMessages: Message[]) => setMessages(allOldMessages))
|
||||
soc.on("newIncomingMessage", (newIncomingMessage: Message) =>
|
||||
setMessages(messages => [...messages, newIncomingMessage])
|
||||
);
|
||||
|
||||
setSocket(soc);
|
||||
}
|
||||
@@ -50,7 +41,6 @@ export default function ChatId() {
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (text !== "" && socket) {
|
||||
// @ts-ignore
|
||||
socket.emit("createdMessage", {text, sender: session.user.id})
|
||||
setText("");
|
||||
}
|
||||
@@ -62,7 +52,7 @@ export default function ChatId() {
|
||||
<Head><title>{websiteName}</title></Head>
|
||||
|
||||
<Container>
|
||||
<MessageList user={session.user} messages={messages}/>
|
||||
<MessageList user={session.user as User} messages={messages}/>
|
||||
|
||||
<Flex gap={5} mt={5}>
|
||||
<Input type={"text"} colorScheme={'purple'} onChange={(evt) => setText(evt.target.value) } value={text} />
|
||||
|
||||
Reference in New Issue
Block a user