diff --git a/apps/api/src/app/auth/auth.service.ts b/apps/api/src/app/auth/auth.service.ts index 43f053d..84117b4 100644 --- a/apps/api/src/app/auth/auth.service.ts +++ b/apps/api/src/app/auth/auth.service.ts @@ -26,14 +26,13 @@ export class AuthService { async register( registerData: Pick ): Promise { - const password = await bcrypt.hash( - registerData.password, - this.configService.get('PASSWORD_SALT_ROUND') - ); + const password = await bcrypt.hash(registerData.password, 12); const userExists = await this.userService.getUserByEmail( - registerData.email + registerData.email, + true ); + if (userExists) { throw new ConflictException(AuthError.EMAIL_ALREADY_EXISTS); } diff --git a/apps/api/src/app/message/message.controller.ts b/apps/api/src/app/message/message.controller.ts index e5bdd65..f0f0810 100644 --- a/apps/api/src/app/message/message.controller.ts +++ b/apps/api/src/app/message/message.controller.ts @@ -2,17 +2,20 @@ import { Body, Controller, Get, Param, Post } from '@nestjs/common'; import { MessageService } from './message.service'; import { CreateMessageCommand } from './commands'; import { ApiTags } from '@nestjs/swagger'; +import { Public } from '../auth/decorators'; @ApiTags('Message') @Controller('message') export class MessageController { constructor(private readonly messageService: MessageService) {} + @Public() @Get() getMessages() { return this.messageService.getMessages(); } + @Public() @Get('receiver/:id') getMessagesByReceiverId(@Param('id') id: string) { return this.messageService.getMessagesByReceiverId(id); @@ -23,6 +26,7 @@ export class MessageController { return this.messageService.getMessageById(id); } + @Public() @Post() createMessage(@Body() data: CreateMessageCommand) { return this.messageService.createMessage(data); diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts index 5fbd8dc..4a6bab9 100644 --- a/apps/api/src/app/user/user.service.ts +++ b/apps/api/src/app/user/user.service.ts @@ -24,10 +24,13 @@ export class UserService { return user; } - async getUserByEmail(email: string): Promise { + async getUserByEmail( + email: string, + verification: boolean = false + ): Promise { const user = await this.prisma.user.findFirst({ where: { email } }); - if (!user) { + if (!user && !verification) { throw new NotFoundException(UserError.USER_NOT_FOUND); } diff --git a/apps/front/components/chat/ChatBox.tsx b/apps/front/components/chat/ChatBox.tsx index 1569312..19effa0 100644 --- a/apps/front/components/chat/ChatBox.tsx +++ b/apps/front/components/chat/ChatBox.tsx @@ -5,70 +5,140 @@ import { useRef } from 'react'; import MessageItem from './message'; import { BasicButton } from '../forms/Button'; -export default function ChatBox() { - const [messages, setMessages] = useState([ - { text: 'Bonjour, comment puis-je vous aider?', user: 'user1', timestamp: new Date() }, - { text: 'Voici un exemple de message.', user: 'user2', timestamp: new Date() }, - { text: 'Testons avec plusieurs messages.', user: 'user1', timestamp: new Date() }, - { text: 'Testons avec plusieurs messages.', user: 'user1', timestamp: new Date() }, - { text: 'Testons avec plusieurs messages.', user: 'user1', timestamp: new Date() }, - { text: 'Testons avec plusieurs messages.', user: 'user1', timestamp: new Date() }, - { text: 'Testons avec plusieurs messages.', user: 'user1', timestamp: new Date() }, - { text: 'Testons avec plusieurs messages.', user: 'user1', timestamp: new Date() }, +interface ChatProps { + chats: [{ text: string; user: string; timestamp: Date }]; + onMessageSent: (messageText: string) => void; +} + +export default function ChatBox({ chats, onMessageSent }: ChatProps) { + const dummyMessages = [ + { + text: 'Bonjour, comment puis-je vous aider?', + user: 'user1', + timestamp: new Date(), + }, + { + text: 'Voici un exemple de message.', + user: 'user2', + timestamp: new Date(), + }, + { + text: 'Testons avec plusieurs messages.', + user: 'user1', + timestamp: new Date(), + }, + { + text: 'Testons avec plusieurs messages.', + user: 'user1', + timestamp: new Date(), + }, + { + text: 'Testons avec plusieurs messages.', + user: 'user1', + timestamp: new Date(), + }, + { + text: 'Testons avec plusieurs messages.', + user: 'user1', + timestamp: new Date(), + }, + { + text: 'Testons avec plusieurs messages.', + user: 'user1', + timestamp: new Date(), + }, + { + text: 'Testons avec plusieurs messages.', + user: 'user1', + timestamp: new Date(), + }, + ]; + const [messages, setMessages] = useState([...dummyMessages, ...chats]); - ]); - const [inputValue, setInputValue] = useState(''); - const handleKeyPress = (event: React.KeyboardEvent) => { - if (event.key === 'Enter' && !event.shiftKey) { // Vérifier si la touche "Entrée" est pressée sans "Shift" - event.preventDefault(); // Prévenir le comportement par défaut (saut de ligne) - sendMessage(); - } - }; - const inputRef = useRef(null); - const sendMessage = () => { - if (inputRef.current && inputRef.current.value.trim() !== '') { - setMessages([...messages, { text: inputRef.current.value, user: 'user2', timestamp: new Date() }]); - inputRef.current.value = ""; - setInputValue(''); - } - }; + const [inputValue, setInputValue] = useState(''); + const handleKeyPress = (event: React.KeyboardEvent) => { + if (event.key === 'Enter' && !event.shiftKey) { + event.preventDefault(); + sendMessage(); + } + }; + const inputRef = useRef(null); + const sendMessage = () => { + if (inputRef.current && inputRef.current.value.trim() !== '') { + setMessages([ + ...messages, + { text: inputRef.current.value, user: 'user2', timestamp: new Date() }, + ]); + onMessageSent(inputRef.current.value); + inputRef.current.value = ''; + setInputValue(''); + } + }; - const messagesEndRef = useRef(null); - const handleInputChange = (event: ChangeEvent) => { - setInputValue(event.target.value); - }; - const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); - }; + const messagesEndRef = useRef(null); + const handleInputChange = (event: ChangeEvent) => { + setInputValue(event.target.value); + }; + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }; - useEffect(() => { - scrollToBottom(); - }, [messages]); - return ( - - - - {messages.map((message, index) => ( - - ))} -
- - - - - - - ); + useEffect(() => { + scrollToBottom(); + }, [messages]); + return ( + + + {messages.map((message, index) => ( + + ))} +
+ + + + + + + ); } diff --git a/apps/front/components/forms/Button.tsx b/apps/front/components/forms/Button.tsx index ad35ffd..9f4ece1 100644 --- a/apps/front/components/forms/Button.tsx +++ b/apps/front/components/forms/Button.tsx @@ -8,19 +8,30 @@ interface BasicButtonProps { buttonColor: 'primary' | 'secondary'; chat: 'yes' | 'no'; disabled?: boolean; + buttonWidth?: number; } export function BasicButton(props: BasicButtonProps) { - const { buttonText, buttonVariant, onClick, buttonColor, chat, disabled } = props; + const { + buttonText, + buttonVariant, + onClick, + buttonColor, + chat, + disabled, + buttonWidth, + } = props; const buttonContent = chat === 'yes' ? : buttonText; return ( - + {user.name} + + {user.email} + + + + + + ); } diff --git a/apps/front/pages/_app.tsx b/apps/front/pages/_app.tsx index 3a2122a..8d055df 100644 --- a/apps/front/pages/_app.tsx +++ b/apps/front/pages/_app.tsx @@ -10,19 +10,127 @@ import useMediaQuery from '@mui/material/useMediaQuery'; import { Box } from '@mui/material'; import ProfilePage from '../components/profile/profile'; +interface Message { + text: string; + user: string; + timestamp: Date; +} + function CustomApp({ Component, pageProps }: AppProps) { - var [auth, setAuth] = useState(false); + const [userId, setUserId] = useState(''); + const [auth, setAuth] = useState(false); + const [messages, setMessages] = useState([ + { text: '', user: 'user1', timestamp: new Date() }, + ]); const appBarHeight = theme.mixins.toolbar.minHeight; + const paddingTopValue = + typeof appBarHeight === 'number' + ? appBarHeight + 30 + : `calc(${appBarHeight} + 10px)`; + const isDesktop = useMediaQuery(theme.breakpoints.up('sm')); - const drawerWidth = 240; + const drawerWidth = 240; const [showProfile, setShowProfile] = useState(false); + const apiUrl = 'http://localhost:3000/api'; + let access_token = ''; + const parseJwt = (token: string) => { + if (!token) { + return; + } + const base64Url = token.split('.')[1]; + const base64 = base64Url.replace('-', '+').replace('_', '/'); + return JSON.parse(window.atob(base64)); + }; + + const Login = async (email: string, password: string) => { + console.log('login'); + try { + const data = { email, password }; + const signIn = await fetch(`${apiUrl}/auth/login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then((res) => res.text()); + access_token = signIn; + const tokenPayload = parseJwt(access_token); + setUserId(tokenPayload.sub); + } catch (error) { + console.error(error); + } + setAuth(true); + getMessages(); + }; + const SignUp = async (email: string, password: string, name: string) => { + console.log('SignUp'); + + try { + const data = { email, password, name }; + console.log(data); + + const signup = await fetch(`${apiUrl}/auth/register`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then((res) => res.json()); + console.log(signup); + Login(email, password); + if (signup.error) console.error(signup.message); + } catch (error) { + console.error(error); + } + + // setAuth(true); + }; + + const getMessages = async () => { + const fetchedMessages = await fetch( + `${apiUrl}/message/receiver/d685ecf9-8c83-474b-85fa-daa0ebb795cf`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + } + ).then((res) => res.json()); + const checkedMessages = fetchedMessages.map((message: any) => { + let user = 'user1'; + if (message.receiver == userId) { + user = 'user2'; + } + return { + text: message.text, + user: user, + timestamp: message.created_at, + }; + }); + console.log(checkedMessages); + + setMessages(checkedMessages); + console.log(messages); + }; + + const postMessage = async (textMessage: string) => { + const data = { + sender_id: userId, + text: textMessage, + receiver_id: 'd685ecf9-8c83-474b-85fa-daa0ebb795cf', + }; + console.log(data); + + const post = await fetch(`${apiUrl}/message`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }).then((res) => res.json()); + console.log(post); + }; - const Login = () => { - setAuth(true) - } - const SignUp = () => { - setAuth(true) - } const toggleProfile = () => { setShowProfile(!showProfile); }; @@ -32,17 +140,41 @@ function CustomApp({ Component, pageProps }: AppProps) { Web Chat -
-
- - {auth ? (showProfile ? : ) : } +
+
+ + {auth ? ( + showProfile ? ( + + ) : messages ? ( + + ) : ( +

no messages ...

+ ) + ) : ( + + )}
-
);