diff --git a/index.html b/index.html index c47664a..f7f96da 100644 --- a/index.html +++ b/index.html @@ -7,11 +7,14 @@ href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300..700&display=swap" rel="stylesheet" /> + + Monday Replica
+ diff --git a/package-lock.json b/package-lock.json index dc1171e..0dfadfc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@mui/icons-material": "^6.3.1", "@mui/material": "^6.3.1", "@mui/x-date-pickers": "^7.23.6", + "animate.css": "^4.1.1", "dayjs": "^1.11.13", "gh-pages": "^6.3.0", "react": "^18.3.1", @@ -2145,6 +2146,12 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/animate.css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", + "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==", + "license": "MIT" + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", diff --git a/package.json b/package.json index d8b2734..60baadd 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@mui/icons-material": "^6.3.1", "@mui/material": "^6.3.1", "@mui/x-date-pickers": "^7.23.6", + "animate.css": "^4.1.1", "dayjs": "^1.11.13", "gh-pages": "^6.3.0", "react": "^18.3.1", diff --git a/public/vite.svg b/public/vite.svg index e7b8dfb..c200287 100644 --- a/public/vite.svg +++ b/public/vite.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/cmps/AppHeader.jsx b/src/cmps/AppHeader.jsx index 0075669..c547912 100644 --- a/src/cmps/AppHeader.jsx +++ b/src/cmps/AppHeader.jsx @@ -26,10 +26,10 @@ export function AppHeader({ userData = null }) { width="20" height="20" aria-hidden="true" - class="icon_da9e87501e" + className="icon_da9e87501e" data-testid="topbar-icon" > - + - - + + - - + + - - + + - - + + - - + + diff --git a/src/cmps/dynamicCmps/Members.jsx b/src/cmps/dynamicCmps/Members.jsx index 1255061..a4ce030 100644 --- a/src/cmps/dynamicCmps/Members.jsx +++ b/src/cmps/dynamicCmps/Members.jsx @@ -6,9 +6,6 @@ import { useSelector } from "react-redux"; export function Members({ cellId, group, task, members, onTaskUpdate, users }) { const openModalId = useSelector(state => state.boardModule.openModal) const modal = (openModalId === cellId) - useEffect(() => { - console.log(members) - }, []) const modalRef = useRef(null) const membersCellRef = useRef(null) diff --git a/src/cmps/dynamicCmps/TaskTitle.jsx b/src/cmps/dynamicCmps/TaskTitle.jsx index dfdcf72..dbb3221 100644 --- a/src/cmps/dynamicCmps/TaskTitle.jsx +++ b/src/cmps/dynamicCmps/TaskTitle.jsx @@ -4,6 +4,7 @@ import { ChatModal } from "./modals/ChatModal.jsx" import ChatIcon from '@mui/icons-material/MapsUgcOutlined'; import { openModal } from '../../store/actions/boards.actions.js' import { useSelector } from "react-redux"; +import { utilService } from "../../services/util.service.js"; export function TaskTitle({ cellId, users, @@ -22,28 +23,32 @@ export function TaskTitle({ cellId, const modalRef = useRef(null) const ChatButtonRef = useRef(null) - // close and open modal as needed - function modalToggle() { - modal - ? openModal(null) - : openModal(cellId) - } + useEffect(() => { + if (modalRef.current && modal) { + chatAnimation(true) + } + }, [modal]) - function handleClickOutsideModal(event) { - if (!modalRef.current.contains(event.target) - && !ChatButtonRef.current.contains(event.target)) - modalToggle() - } + function chatAnimation(isEnter){ + isEnter + ? utilService.animateCSS(modalRef.current, 'fadeInRightBig', 0.3, + { position: 'fixed', + top: '0px', + right: '0px', + opacity: 1, + zIndex: 100, + }) + : utilService.animateCSS(modalRef.current, 'fadeOutRightBig', 0.3) - useEffect(() => { - if (modal) document.addEventListener - ('mousedown', handleClickOutsideModal) - else document.removeEventListener - ('mousedown', handleClickOutsideModal) - return () => document.removeEventListener - ('mousedown', handleClickOutsideModal) + } - }, [modal]) + // close and open modal as needed + function modalToggle() { + if(modal){ + chatAnimation(false) + setTimeout(()=>openModal(null), 275) + } else openModal(cellId) + } function onAddComment(comment) { const newComment = { diff --git a/src/cmps/dynamicCmps/modals/ChatModal.jsx b/src/cmps/dynamicCmps/modals/ChatModal.jsx index e5dd896..ec57fa5 100644 --- a/src/cmps/dynamicCmps/modals/ChatModal.jsx +++ b/src/cmps/dynamicCmps/modals/ChatModal.jsx @@ -1,6 +1,7 @@ import { simplifyTimeToStr } from "../../../services/util.service.js"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { showErrorMsg } from '../../../services/event-bus.service.js' +import 'animate.css'; export function ChatModal({ loggedinUser, @@ -13,6 +14,9 @@ export function ChatModal({ modalToggle}) { + + + const [onEditMode, setOnEditMode] = useState(false) const [textToEdit, setTextToEdit] = useState(text) @@ -20,6 +24,25 @@ export function ChatModal({ const [newReplies, setNewReplies] = useState( chat.map(comment => ({ id: comment.sentAt, text: "" }))) + + const [width, setWidth] = useState(700) // Initial width of the chat modal + const [isDragging, setIsDragging] = useState(false) + + useEffect(() => { + // Attach global mousemove and mouseup listeners when dragging starts + if (isDragging) { + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + } + + // Cleanup listeners when dragging stops + return () => { + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + }, [isDragging]); + + // toggel btween spectate and edit mode function toggleEditMode() { if (onEditMode) { @@ -87,85 +110,120 @@ export function ChatModal({ )) } + const handleMouseDown = () => { + setIsDragging(true) + } + + const handleMouseMove = event => { + if (!isDragging) return + const modalRect = document.querySelector('.chat-modal').getBoundingClientRect() + const newWidth = modalRect.right - event.clientX; // Calculate width dynamically + + // Set a minimum and maximum width for the modal to prevent it from collapsing or overflowing + const MIN_WIDTH = 570 + const MAX_WIDTH = window.innerWidth - 210 // will need to be change later + + setWidth(Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH))); + } + + const handleMouseUp = () => { + setIsDragging(false) + } + return ( -
- - - - {/* Edit Task Title */} -
- { - !onEditMode - ? - {text} - : -