diff --git a/containers/api/package-lock.json b/containers/api/package-lock.json
index d6ede8ee..80ea8757 100644
--- a/containers/api/package-lock.json
+++ b/containers/api/package-lock.json
@@ -41,6 +41,7 @@
"@types/express": "^4.17.13",
"@types/jest": "29.5.0",
"@types/node": "18.15.11",
+ "@types/qrcode": "^1.5.0",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
@@ -2305,6 +2306,15 @@
"integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
"dev": true
},
+ "node_modules/@types/qrcode": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.0.tgz",
+ "integrity": "sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
diff --git a/containers/api/package.json b/containers/api/package.json
index d54f1be3..fdad87d1 100644
--- a/containers/api/package.json
+++ b/containers/api/package.json
@@ -52,6 +52,7 @@
"@types/express": "^4.17.13",
"@types/jest": "29.5.0",
"@types/node": "18.15.11",
+ "@types/qrcode": "^1.5.0",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
diff --git a/containers/api/src/users/2fa.ts b/containers/api/src/users/2fa.ts
index 8e505cfd..38a0924e 100644
--- a/containers/api/src/users/2fa.ts
+++ b/containers/api/src/users/2fa.ts
@@ -5,6 +5,8 @@ import crypto from "crypto";
import * as OTPAuth from "otpauth";
import { encode } from "hi-base32";
+import * as qr from 'qrcode';
+
// [...] Register user
// [...] Login user
@@ -32,6 +34,24 @@ export const generateOTP = async (user) => {
});
let otpauth_url = totp.toString();
+ const qrCodeDataUrl = await qr.toDataURL(otpauth_url, { errorCorrectionLevel: 'H' });
+
+ const filePath = 'qrcode.png'; // Specify the file path where the QR code should be saved
+
+ qr.toFile(filePath, qrCodeDataUrl, (error) => {
+ if (error) {
+ console.error(error);
+ // Handle the error appropriately
+ return;
+ }
+ // QR code image has been generated and saved to the file
+ // Or, you can create a buffer of the image data directly
+ })
+
+
+
+
+
const res = {
otpauth_url: otpauth_url,
@@ -87,7 +107,6 @@ export const generateOTP = async (user) => {
period: 15,
secret: user.otp_base32,
});
-
let delta = totp.validate({ token });
if (delta === null) {
diff --git a/containers/react/src/components/Alert/GreenAlert.jsx b/containers/react/src/components/Alert/GreenAlert.jsx
new file mode 100644
index 00000000..cded387b
--- /dev/null
+++ b/containers/react/src/components/Alert/GreenAlert.jsx
@@ -0,0 +1,39 @@
+import Backdrop from "../Sidebar/Backdrop"
+import { motion } from 'framer-motion'
+import { AiOutlineCheckCircle } from "react-icons/ai";
+import '../../styles/Messages.css'
+
+
+const dropIn = {
+ hidden: {
+ y: "-100vh",
+ },
+ visible: {
+ y: "0",
+ },
+ exit: {
+ y: "-100vh",
+ },
+};
+
+function GreenAlert ({handleClose, text}){
+
+ return(
+
+ e.stopPropagation()}
+ className="greenAlert"
+ variant={dropIn}
+ initial="hidden"
+ animate="visible"
+ exit="exit"
+ >
+
+ {text}
+
+ {setTimeout(handleClose, 3000)}
+
+ )
+}
+
+export default GreenAlert
\ No newline at end of file
diff --git a/containers/react/src/components/Alert/RedAlert.jsx b/containers/react/src/components/Alert/RedAlert.jsx
new file mode 100644
index 00000000..3a9104b1
--- /dev/null
+++ b/containers/react/src/components/Alert/RedAlert.jsx
@@ -0,0 +1,38 @@
+import Backdrop from "../Sidebar/Backdrop"
+import { motion } from 'framer-motion'
+import { BiErrorCircle } from "react-icons/bi";
+import '../../styles/Messages.css'
+
+
+const dropIn = {
+ hidden: {
+ y: "-100vh",
+ },
+ visible: {
+ y: "0",
+ },
+ exit: {
+ y: "-100vh",
+ },
+};
+
+function RedAlert ({handleClose, text}) {
+ return(
+
+ e.stopPropagation()}
+ className="redAlert"
+ variant={dropIn}
+ initial="hidden"
+ animate="visible"
+ exit="exit"
+ >
+
+ {text}
+
+ {setTimeout(handleClose, 3000)}
+
+ )
+}
+
+export default RedAlert
\ No newline at end of file
diff --git a/containers/react/src/components/Alert/YellowAlert.jsx b/containers/react/src/components/Alert/YellowAlert.jsx
new file mode 100644
index 00000000..bbedcdca
--- /dev/null
+++ b/containers/react/src/components/Alert/YellowAlert.jsx
@@ -0,0 +1,37 @@
+import Backdrop from "../Sidebar/Backdrop"
+import { motion } from 'framer-motion'
+import { GrTrophy } from "react-icons/gr";
+import '../../styles/Messages.css'
+
+const dropIn = {
+ hidden: {
+ y: "-100vh",
+ },
+ visible: {
+ y: "0",
+ },
+ exit: {
+ y: "-100vh",
+ },
+};
+
+function YellowAlert ({handleClose, text}) {
+ return(
+
+ e.stopPropagation()}
+ className="yellowAlert"
+ variant={dropIn}
+ initial="hidden"
+ animate="visible"
+ exit="exit"
+ >
+
+ {text}
+
+ {setTimeout(handleClose, 3000)}
+
+ )
+}
+
+export default YellowAlert
\ No newline at end of file
diff --git a/containers/react/src/components/Messages/Chats.jsx b/containers/react/src/components/Messages/Chats.jsx
index ac19b416..0fbf3230 100644
--- a/containers/react/src/components/Messages/Chats.jsx
+++ b/containers/react/src/components/Messages/Chats.jsx
@@ -4,6 +4,8 @@ import '../../styles/Messages.css'
import styled from "styled-components";
import DefaultPic from '../../assets/profile.jpg'
import api from '../../script/axiosApi';
+import { motion , AnimatePresence} from "framer-motion";
+import Modal from "./Modal";
import Message from "./Message"
// import Input from "./Input";
@@ -12,6 +14,12 @@ import Message from "./Message"
import { TbSend } from 'react-icons/tb';
import { ImBlocked } from 'react-icons/im';
import { MdOutlineGroupAdd } from 'react-icons/md';
+import { GrAdd } from 'react-icons/gr';
+
+import { Rank } from "../../DataBase/DataRank";
+import GreenAlert from "../Alert/GreenAlert";
+import RedAlert from "../Alert/RedAlert";
+import YellowAlert from "../Alert/YellowAlert";
const TouchDiv = styled.div`
@@ -38,6 +46,9 @@ const UserChat = styled.div `
&:hover{
background-color: #3e3c61;
}
+ &:active {
+ filter: black;
+ }
`
// const SideSpan = styled.span`
@@ -213,6 +224,34 @@ function Chats(){
}
}
+ const [friend, setFriend] = useState("");
+ const [modalOpen, setModalOpen] = useState(false);
+ const [addFriend, setAddFriend] = useState(false);
+ const [block, setBlock] = useState(false);
+ const close = () => setModalOpen(false);
+ const open = () => setModalOpen(true);
+ const closeAddFriend = () => setAddFriend(false);
+ const closeBlock = () => setBlock(false);
+
+
+ const handleFriend = e => {
+ setFriend(e.target.value)
+ };
+
+ // const findValue = () => {
+ // // setFind(false);
+ // console.log(friend);
+ // Rank.map((tab) => {
+ // if (tab.name === friend)
+ // {
+ // console.log("ok bon");
+ // setFind(true);
+ // }
+ // })
+ // console.log(find);
+ // // if (!find)
+ // };
+
// console.log(`data user1= ${user.username}`)
// while (user === null)
@@ -228,7 +267,7 @@ function Chats(){
return (
-
+ {/*
{isLoading ? (
@@ -238,7 +277,7 @@ function Chats(){
// {user.username}
)}
-
+
*/}
@@ -252,33 +291,74 @@ function Chats(){
)}
- {conversations.map(c=> (
- setCurrentChat(c)}>
-
-
-
- {c.name}
- Desc?
-
-
+
+
+
+
+ (modalOpen ? close() : open())}
+ >
+
+ New Conversation
+
+ {modalOpen && }
+
+
+ {conversations.map((c, index ) => {
+ return (
+
setCurrentChat(c)}>
+
+
+
+ {c.name}
+ Desc?
+
+
+
+
+ )})}
- ))}
{
currentChat ? (
- <>
+ <>
- {messages.map(m=>(
-
- ))}
+
+ {messages.map(m=>(
+
+ ))}
+
{/* */}
setNewMessage(e.target.value)}
value={newMessages}
- />
+ />
@@ -295,19 +375,14 @@ function Chats(){
>
) : (
- Open a conversation)}
+
+ Open a conversation
+
+ )}
+
//
- );
-
-
-
-
-
-
-
-
-
+ );
}
export default Chats
\ No newline at end of file
diff --git a/containers/react/src/components/Messages/Message.jsx b/containers/react/src/components/Messages/Message.jsx
index e3c8a9ad..69e0b628 100644
--- a/containers/react/src/components/Messages/Message.jsx
+++ b/containers/react/src/components/Messages/Message.jsx
@@ -19,10 +19,10 @@ import DefaultPicture from '../../assets/profile.jpg'
import '../../styles/Messages.css'
const MeStyleP = styled.p`
- background-color: lightgray;
+ background-color: #5843e4;
padding 10px 20px;
border-radius 10px 0px 10px 10px;
- color: black;
+ color: white;
margin-right: 20px;
`
diff --git a/containers/react/src/components/Messages/Modal.jsx b/containers/react/src/components/Messages/Modal.jsx
new file mode 100644
index 00000000..4dea9b6e
--- /dev/null
+++ b/containers/react/src/components/Messages/Modal.jsx
@@ -0,0 +1,113 @@
+import { motion } from "framer-motion";
+import Backdrop from "../Sidebar/Backdrop";
+import { Rank } from "../../DataBase/DataRank"
+import '../../styles/Messages.css'
+import { useState } from "react";
+import { GrAdd } from "react-icons/gr";
+import { Link } from "react-router-dom";
+
+const dropIn = {
+ hidden:{y:"-100vh",
+ opacity: 0,},
+ visible:{y: "0",
+ opacity: 0,
+ transotion:{
+ duration:0.1,
+ type:"spring",
+ damping: 100,
+ stiffness: 500,
+ }},
+ exit:{y: "100vh",
+ opacity: 0,},
+
+};
+
+const Modal = ({handleClose, text}) => {
+ const [multi, setMulti] = useState(false);
+ const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]);
+ const [selectedOptionArray, setSelectedOptionArray] = useState([]);
+
+ const handleOptionChange = (selectId, selectedOption) => {
+ setSelectTag((prevTags) =>
+ prevTags.map((tag) =>
+ tag.id === selectId ? { ...tag, selectedOption } : tag
+ )
+ );
+ };
+
+ const addNewSelectedTag = () => {
+ const newSelectedId = Math.max (...selectTags.map((tag) => tag.id)) + 1;
+ setSelectTag([...selectTags, { id: newSelectedId, selectedOption: ''}]);
+ };
+
+ const saveSelectedOptions = () => {
+ const selectedOptions = selectTags.map((tag) => tag.selectedOption);
+ setSelectedOptionArray(selectedOptions);
+ }
+ let new_name;
+ return (
+
+ e.stopPropagation()}
+ className="modal"
+ variant={dropIn}
+ initial="hidden"
+ animate="visible"
+ exit="exit"
+ >
+ New Convewrstion
+
+{/* First selection */}
+
+
+
+{/* Second selection */}
+ {selectTags.map((selectTag) =>(
+
+
+
+
+ ))
+ }
+
+
Selected Option:
+
+ {selectedOptionArray.map((option, index) => (
+ - {option}
+ ))}
+
+
+
+ {multi === true ? (
+ ) : " "}
+
+
+ Submit
+
+ Cancel
+
+
+
+
+ )
+}
+
+export default Modal
\ No newline at end of file
diff --git a/containers/react/src/styles/Messages.css b/containers/react/src/styles/Messages.css
index b72d5208..37c84b40 100644
--- a/containers/react/src/styles/Messages.css
+++ b/containers/react/src/styles/Messages.css
@@ -7,6 +7,61 @@
}
+select{
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -ms-appearance: none;
+ background: black;
+ color: white;
+ box-shadow: none;
+ appearance: none;
+ outline: 0;
+ border: 0!important;
+ margin: 5px;
+ font-size: 18px;
+ border-radius: 6px;
+}
+
+.modal{
+ width: clamp(50%, 700px, 90%);
+ height: min(50%, 300px);
+
+ margin: auto;
+ padding: 2rem;
+ border-radius: 12px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.scroll{
+ overflow: scroll;
+}
+
+.newMessage{
+ color: white;
+ font-size: 18px;
+}
+
+.contact{
+ background-color: rgb(46, 46, 46);
+ align-items: left;
+ height: 29.7rem;
+ overflow: scroll;
+ /* width: 2rem; */
+ /* height: 4rem; */
+}
+
+.messages_box{
+ background-color: black;
+ /* height: 90vh; */
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ /* position:relative; */
+
+}
+
.container{
border-color: #FFFFFF ;
border-radius: 50%;
@@ -35,9 +90,11 @@
.navbar{
display: flex;
align-items: center;
- background-color: #000c66;
+ /* background-color: yellow; */
+ background-image: linear-gradient(90deg, #5843e4, #5a0760);
color: white;
padding: 3px;
+ border-radius: 10px 10px 0px 0px;
}
.pic{
@@ -65,8 +122,9 @@
}
.messages{
- background-color: #349b83;
- height: calc(100% - 118px);
+ background-color: black;
+ /* height: calc(100% - 118px); */
+ width: 40rem;
overflow: scroll;
}
@@ -115,4 +173,91 @@ input{
display: flex;
flex-direction: row-reverse;
padding: 20px;
-}
\ No newline at end of file
+ color: lightgrey;
+}
+
+.submit{
+ display: inline-block;
+ color: white;
+ background-color: #5843e4;
+ border-radius: 10px;
+ padding: 5px;
+ font-size: 1.2rem;
+ text-decoration: none;
+ font-weight:lighter;
+}
+
+.div_submit {
+ flex-direction: row;
+ align-items: center;
+ /* margin-left: 4px;
+ margin-right: 4px; */
+}
+
+.lookForFriends{
+ color: rgba(255, 255, 255, 0.5);;
+ backdrop-filter: sepia(90%);
+ background-color: rgba(0, 0, 0, 0.3);
+ border-radius: 4px;
+ width: 11rem;
+ height: 1.5rem;
+ margin-top: 1rem;
+}
+
+.greenAlert{
+ width: clamp(50%, 500px, 90%);
+ height: min(50%, 100px);
+
+ margin: auto;
+ padding: 1rem;
+ border-radius: 12px;
+ /* display: flex; */
+ flex-direction: row;
+ align-items: center;
+ background-color: rgba(0, 86, 27, 0.7);
+ font-size: 25px;
+ color: rgba(255, 255, 255, 1);
+}
+
+.redAlert{
+ width: clamp(50%, 500px, 90%);
+ height: min(50%, 100px);
+
+ margin: auto;
+ padding: 1rem;
+ border-radius: 12px;
+ flex-direction: row;
+ align-items: center;
+ background-color: rgba(133, 6, 6, 0.7);
+ font-size: 25px;
+ color: rgba(255, 255, 255, 1);
+}
+
+.redAlert{
+ width: clamp(50%, 500px, 90%);
+ height: min(50%, 100px);
+
+ margin: auto;
+ padding: 1rem;
+ border-radius: 12px;
+ flex-direction: row;
+ align-items: center;
+ background-color: rgba(133, 6, 6, 0.7);
+ font-size: 25px;
+ color: rgba(255, 255, 255, 1);
+}
+
+.yellowAlert{
+ width: clamp(50%, 500px, 90%);
+ height: min(50%, 100px);
+
+ margin: auto;
+ padding: 1rem;
+ border-radius: 12px;
+ flex-direction: row;
+ align-items: center;
+ background-color: rgba(212, 175, 55, 0.7);
+ font-size: 25px;
+ color: rgba(255, 255, 255, 1);
+}
+
diff --git a/containers/react/src/styles/chat.css b/containers/react/src/styles/chat.css
index 0fde8fdb..cf81842f 100644
--- a/containers/react/src/styles/chat.css
+++ b/containers/react/src/styles/chat.css
@@ -38,9 +38,13 @@
.chat {
width: 100%;
height: 100vh;
- display: flex;
+ display:inline-block;
align-items: center;
}
+
+.chat_2{
+ display:flex;
+}
.chat__sidebar {
height: 100%;
background-color: #f9f5eb;