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 (
-
+ {/*
profile {isLoading ? ( @@ -238,7 +277,7 @@ function Chats(){ //

{user.username}

)}
-
+
*/} @@ -252,33 +291,74 @@ function Chats(){ )}
+ - + (addFriend ? setAddFriend(false) : setAddFriend(true))}> + + {/* {console.log("find = ",find) && setFind(true)} */} + + null} + > + {addFriend && } + + {/* {console.log("find2 = ", find) && find && } */} + (block ? setBlock(false) : setBlock(true))} + > + null} + > + {block && } + +
- {conversations.map(c=> ( -
setCurrentChat(c)}> - - User -
- {c.name} - Desc? -
-
+
+
+ + + (modalOpen ? close() : open())} + > + + New Conversation + + {modalOpen && } + + + {conversations.map((c, index ) => { + return ( +
setCurrentChat(c)}> + + User +
+ {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;