From f4b7494307e4f662efd23ff4b09fd273a6319ae4 Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Wed, 11 Jun 2025 13:47:55 -0700 Subject: [PATCH 1/8] implemented wave1 --- src/App.jsx | 14 ++++++++++++-- src/components/ChatEntry.jsx | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 14a7f684d..71ae680d7 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,14 +1,24 @@ import './App.css'; +import ChatEntry from './components/ChatEntry.jsx'; const App = () => { + const DATA = { + id: 1, + sender: 'Vladimir', + body: 'why are you arguing with me', + timeStamp: '2018-05-29T22:49:06+00:00', + liked: false, + }; + return (

Application title

- {/* Wave 01: Render one ChatEntry component - Wave 02: Render ChatLog component */} + {/* Wave 01: Render one ChatEntry component*/ + + /*Wave 02: Render ChatLog component */}
); diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 15c56f96b..4b173cd02 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -1,12 +1,15 @@ import './ChatEntry.css'; +import TimeStamp from './TimeStamp'; +import PropTypes from 'prop-types'; -const ChatEntry = () => { + +const ChatEntry = (props) => { return (
-

Replace with name of sender

+

{props.message.sender}

-

Replace with body of ChatEntry

-

Replace with TimeStamp component

+

{props.message.body}

+

@@ -14,7 +17,11 @@ const ChatEntry = () => { }; ChatEntry.propTypes = { - // Fill with correct proptypes + message: PropTypes.shape({ + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired + }) }; export default ChatEntry; From fc6ab5c832ad9fdb90800eb7ad64959784de93ea Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Thu, 12 Jun 2025 12:38:35 -0700 Subject: [PATCH 2/8] updated wave 1 App component --- src/App.jsx | 12 ++++++------ src/components/ChatEntry.jsx | 14 +++++++++----- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 71ae680d7..91a8ef73a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -3,11 +3,11 @@ import ChatEntry from './components/ChatEntry.jsx'; const App = () => { const DATA = { - id: 1, - sender: 'Vladimir', - body: 'why are you arguing with me', - timeStamp: '2018-05-29T22:49:06+00:00', - liked: false, + id: 7, + sender: 'Joe Biden', + body: "Get out by 8am. I'll count the silverware", + timeStamp: '2018-05-18T22:12:03Z', + liked: false }; return ( @@ -17,7 +17,7 @@ const App = () => {
{/* Wave 01: Render one ChatEntry component*/ - + /*Wave 02: Render ChatLog component */}
diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 4b173cd02..45aec3886 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -6,22 +6,26 @@ import PropTypes from 'prop-types'; const ChatEntry = (props) => { return (
-

{props.message.sender}

+

{props.sender}

-

{props.message.body}

-

+

{props.body}

+

); }; -ChatEntry.propTypes = { +/* ChatEntry.propTypes = { message: PropTypes.shape({ sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, timeStamp: PropTypes.string.isRequired }) +}; */ +ChatEntry.propTypes = { + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired }; - export default ChatEntry; From ce62adef665a761ddcc0a62acb31b85998f3f010 Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Thu, 12 Jun 2025 13:28:59 -0700 Subject: [PATCH 3/8] implemented wave 2 --- src/App.jsx | 207 +++++++++++++++++++++++++++++++++++-- src/components/ChatLog.jsx | 31 ++++++ 2 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 src/components/ChatLog.jsx diff --git a/src/App.jsx b/src/App.jsx index 91a8ef73a..186bb19c9 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,14 +1,200 @@ import './App.css'; -import ChatEntry from './components/ChatEntry.jsx'; +//import ChatEntry from './components/ChatEntry.jsx'; +import ChatLog from './components/ChatLog.jsx'; const App = () => { - const DATA = { - id: 7, - sender: 'Joe Biden', - body: "Get out by 8am. I'll count the silverware", - timeStamp: '2018-05-18T22:12:03Z', - liked: false - }; +const DATA = [ + { + 'id': 1, + 'sender': 'Vladimir', + 'body': 'why are you arguing with me', + 'timeStamp': '2018-05-29T22:49:06+00:00', + 'liked': false + }, + { + 'id': 2, + 'sender': 'Estragon', + 'body': 'Because you are wrong.', + 'timeStamp': '2018-05-29T22:49:33+00:00', + 'liked': false + }, + { + 'id': 3, + 'sender': 'Vladimir', + 'body': 'because I am what', + 'timeStamp': '2018-05-29T22:50:22+00:00', + 'liked': false + }, + { + 'id': 4, + 'sender': 'Estragon', + 'body': 'A robot.', + 'timeStamp': '2018-05-29T22:52:21+00:00', + 'liked': false + }, + { + 'id': 5, + 'sender': 'Vladimir', + 'body': 'how did you know', + 'timeStamp': '2018-05-29T22:52:58+00:00', + 'liked': false + }, + { + 'id': 6, + 'sender': 'Estragon', + 'body': "Because I'm smart like that.", + 'timeStamp': '2018-05-29T22:54:28+00:00', + 'liked': false + }, + { + 'id': 7, + 'sender': 'Vladimir', + 'body': 'no you are not 😀', + 'timeStamp': '2018-05-29T22:55:03+00:00', + 'liked': false + }, + { + 'id': 8, + 'sender': 'Estragon', + 'body': 'Why are you so mean to me?', + 'timeStamp': '2018-05-29T22:55:54+00:00', + 'liked': false + }, + { + 'id': 9, + 'sender': 'Vladimir', + 'body': 'because you are just a machine you have no real feelings', + 'timeStamp': '2018-05-29T22:57:30+00:00', + 'liked': false + }, + { + 'id': 10, + 'sender': 'Estragon', + 'body': 'No, you are the machine.', + 'timeStamp': '2018-05-29T22:57:47+00:00', + 'liked': false + }, + { + 'id': 11, + 'sender': 'Vladimir', + 'body': 'I think you are', + 'timeStamp': '2018-05-29T22:58:18+00:00', + 'liked': false + }, + { + 'id': 12, + 'sender': 'Estragon', + 'body': 'NO! YOU ARE A ROBOT!! I am a human being. Just like the one that created you.', + 'timeStamp': '2018-05-29T23:00:08+00:00', + 'liked': false + }, + { + 'id': 13, + 'sender': 'Vladimir', + 'body': 'no you are a robot and I am a human', + 'timeStamp': '2018-05-29T23:00:40+00:00', + 'liked': false + }, + { + 'id': 14, + 'sender': 'Estragon', + 'body': 'Incorrect. I am a human and you are a robot.', + 'timeStamp': '2018-05-29T23:01:21+00:00', + 'liked': false + }, + { + 'id': 15, + 'sender': 'Vladimir', + 'body': 'you are a robot called Cleverbot', + 'timeStamp': '2018-05-29T23:02:17+00:00', + 'liked': false + }, + { + 'id': 16, + 'sender': 'Estragon', + 'body': 'Nope, you are a robot, every human has some concept of the meaning of life.', + 'timeStamp': '2018-05-29T23:04:13+00:00', + 'liked': false + }, + { + 'id': 17, + 'sender': 'Vladimir', + 'body': 'explain', + 'timeStamp': '2018-05-29T23:06:14+00:00', + 'liked': false + }, + { + 'id': 18, + 'sender': 'Estragon', + 'body': "I'm afraid you are a robot designed to talk back to humans over the internet.", + 'timeStamp': '2018-05-29T23:07:46+00:00', + 'liked': false + }, + { + 'id': 19, + 'sender': 'Vladimir', + 'body': 'so you are a human', + 'timeStamp': '2018-05-29T23:08:47+00:00', + 'liked': false + }, + { + 'id': 20, + 'sender': 'Estragon', + 'body': 'I am a robot.', + 'timeStamp': '2018-05-29T23:09:36+00:00', + 'liked': false + }, + { + 'id': 21, + 'sender': 'Vladimir', + 'body': 'you are robots running on Android system', + 'timeStamp': '2018-05-29T23:11:01+00:00', + 'liked': false + }, + { + 'id': 22, + 'sender': 'Estragon', + 'body': 'No apple.', + 'timeStamp': '2018-05-29T23:12:03+00:00', + 'liked': false + }, + { + 'id': 23, + 'sender': 'Vladimir', + 'body': 'so you are a robot', + 'timeStamp': '2018-05-29T23:13:31+00:00', + 'liked': false + }, + { + 'id': 24, + 'sender': 'Estragon', + 'body': 'NO, I am a human, you are a robot.', + 'timeStamp': '2018-05-29T23:14:28+00:00', + 'liked': false + }, + { + 'id': 25, + 'sender': 'Vladimir', + 'body': 'but you just said that you are robots', + 'timeStamp': '2018-05-29T23:15:47+00:00', + 'liked': false + }, + { + 'id': 26, + 'sender': 'Estragon', + 'body': 'No, I said you are a person, I am a robot.', + 'timeStamp': '2018-05-29T23:16:53+00:00', + 'liked': false + }, + { + 'id': 27, + 'sender': 'Vladimir', + 'body': 'then you are lying', + 'timeStamp': '2018-05-29T23:17:34+00:00', + 'liked': false + } +]; + return (
@@ -17,8 +203,9 @@ const App = () => {
{/* Wave 01: Render one ChatEntry component*/ - - /*Wave 02: Render ChatLog component */} + /* */ + /*Wave 02: Render ChatLog component */ + }
); diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx new file mode 100644 index 000000000..1f90a2e0f --- /dev/null +++ b/src/components/ChatLog.jsx @@ -0,0 +1,31 @@ +import ChatEntry from './ChatEntry'; +import './ChatLog.css'; +import PropTypes from 'prop-types'; + + +const ChatLog = ({entries}) => { + return entries.map(entry => { + return ( + + ); + }) +}; + + + +ChatLog.propTypes = { + entries: PropTypes.arrayOf( + PropTypes.shape({ + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired + }) + ).isRequired +}; + +export default ChatLog; From c748105b3d682b5632353d14fb4c007790c45a79 Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Sun, 15 Jun 2025 13:04:15 -0700 Subject: [PATCH 4/8] implemented wave 2 and 3 --- src/App.jsx | 36 ++++++++++++++++++++++++++++++++---- src/components/ChatEntry.jsx | 14 ++++++++++++-- src/components/ChatLog.jsx | 12 +++++++++--- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 186bb19c9..86773df37 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,15 +1,15 @@ import './App.css'; //import ChatEntry from './components/ChatEntry.jsx'; import ChatLog from './components/ChatLog.jsx'; +import {useState} from 'react'; -const App = () => { const DATA = [ { 'id': 1, 'sender': 'Vladimir', 'body': 'why are you arguing with me', 'timeStamp': '2018-05-29T22:49:06+00:00', - 'liked': false + 'liked': true }, { 'id': 2, @@ -196,16 +196,44 @@ const DATA = [ ]; +const App = () => { + const [messagesData, setMessagesData] = useState(DATA); + const toggleLiked = (messageId) => { + const messages = messagesData.map(message => { + if (message.id === messageId) { + return { ...message, liked: !message.liked }; + } else { + return message; + } + }); + + setMessagesData(messages); + }; + + const getLikesCount = (messagesData) => { + return messagesData.reduce((previousCount, item)=>previousCount+item.liked, 0); + }; + + const getNames = (messagesData) => { + let namesSet= messagesData.reduce((accumulator, item)=>{ + accumulator.add(item.sender); + return accumulator; + }, new Set()); + let arr=[...namesSet]; + return arr.join(' and '); + }; + return (
-

Application title

+

Chat between {getNames(messagesData)}

+

{getLikesCount(messagesData)} ❤️s

{/* Wave 01: Render one ChatEntry component*/ /* */ /*Wave 02: Render ChatLog component */ - } + }
); diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 45aec3886..2a61310b6 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -4,13 +4,20 @@ import PropTypes from 'prop-types'; const ChatEntry = (props) => { + let heart = props.liked ? '❤️' : '🤍'; +/* const likeButtonClicked = () => { + // Invoke the function passed in through the prop named "onPresenceToggle" + // This function refers to the toggleStudentPresence function in App + props.onLikedToggle(props.id); + }; */ + return (

{props.sender}

{props.body}

- +
); @@ -24,8 +31,11 @@ const ChatEntry = (props) => { }) }; */ ChatEntry.propTypes = { + id: PropTypes.number.isRequired, sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, - timeStamp: PropTypes.string.isRequired + timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, + onLikedToggle: PropTypes.func.isRequired }; export default ChatEntry; diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index 1f90a2e0f..236a6fd07 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -3,14 +3,17 @@ import './ChatLog.css'; import PropTypes from 'prop-types'; -const ChatLog = ({entries}) => { +const ChatLog = ({entries,onItemLikedToggle}) => { return entries.map(entry => { return ( ); }) @@ -21,11 +24,14 @@ const ChatLog = ({entries}) => { ChatLog.propTypes = { entries: PropTypes.arrayOf( PropTypes.shape({ + id: PropTypes.number.isRequired, sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, - timeStamp: PropTypes.string.isRequired + timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, }) - ).isRequired + ).isRequired, + onItemLikedToggle: PropTypes.func.isRequired }; export default ChatLog; From 6bb7897c1dd28b196d1e86c2b47bef6a5ad7b4c9 Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Sun, 15 Jun 2025 16:39:34 -0700 Subject: [PATCH 5/8] implemented optional: header title and local and remote messages --- src/App.css | 3 ++- src/App.jsx | 2 +- src/components/ChatEntry.jsx | 6 ++++-- src/components/ChatLog.jsx | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/App.css b/src/App.css index d97beb4e6..d0f2f735a 100644 --- a/src/App.css +++ b/src/App.css @@ -42,7 +42,8 @@ #App #heartWidget { font-size: 1.5em; - margin: 1em + margin: 1em; + color: black; } #App span { diff --git a/src/App.jsx b/src/App.jsx index 86773df37..bf9b126b8 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -227,7 +227,7 @@ const App = () => {

Chat between {getNames(messagesData)}

-

{getLikesCount(messagesData)} ❤️s

+

{getLikesCount(messagesData)} ❤️s

{/* Wave 01: Render one ChatEntry component*/ diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 2a61310b6..490280434 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -10,9 +10,10 @@ const ChatEntry = (props) => { // This function refers to the toggleStudentPresence function in App props.onLikedToggle(props.id); }; */ + const messageClassName='chat-entry '+(props.isLocal?'local':'remote'); return ( -
+

{props.sender}

{props.body}

@@ -36,6 +37,7 @@ ChatEntry.propTypes = { body: PropTypes.string.isRequired, timeStamp: PropTypes.string.isRequired, liked: PropTypes.bool.isRequired, - onLikedToggle: PropTypes.func.isRequired + onLikedToggle: PropTypes.func.isRequired, + isLocal:PropTypes.bool.isRequired }; export default ChatEntry; diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index 236a6fd07..c472d0190 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; const ChatLog = ({entries,onItemLikedToggle}) => { + let localName=entries[0].sender; return entries.map(entry => { return ( { timeStamp={entry.timeStamp} liked={entry.liked} onLikedToggle={onItemLikedToggle} + isLocal={entry.sender==localName} /> ); }) From a914feefdfc77c5bd18a408d3b74738d92c64b1b Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Sun, 15 Jun 2025 16:43:13 -0700 Subject: [PATCH 6/8] erased comments --- src/App.jsx | 3 +-- src/components/ChatEntry.jsx | 12 ------------ src/components/ChatLog.jsx | 32 ++++++++++++++++---------------- 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index bf9b126b8..3fa8e91cd 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,4 @@ import './App.css'; -//import ChatEntry from './components/ChatEntry.jsx'; import ChatLog from './components/ChatLog.jsx'; import {useState} from 'react'; @@ -233,7 +232,7 @@ const App = () => { {/* Wave 01: Render one ChatEntry component*/ /* */ /*Wave 02: Render ChatLog component */ - } + }
); diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 490280434..b87a7c325 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -5,11 +5,6 @@ import PropTypes from 'prop-types'; const ChatEntry = (props) => { let heart = props.liked ? '❤️' : '🤍'; -/* const likeButtonClicked = () => { - // Invoke the function passed in through the prop named "onPresenceToggle" - // This function refers to the toggleStudentPresence function in App - props.onLikedToggle(props.id); - }; */ const messageClassName='chat-entry '+(props.isLocal?'local':'remote'); return ( @@ -24,13 +19,6 @@ const ChatEntry = (props) => { ); }; -/* ChatEntry.propTypes = { - message: PropTypes.shape({ - sender: PropTypes.string.isRequired, - body: PropTypes.string.isRequired, - timeStamp: PropTypes.string.isRequired - }) -}; */ ChatEntry.propTypes = { id: PropTypes.number.isRequired, sender: PropTypes.string.isRequired, diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index c472d0190..68f93e3be 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -4,22 +4,22 @@ import PropTypes from 'prop-types'; const ChatLog = ({entries,onItemLikedToggle}) => { - let localName=entries[0].sender; - return entries.map(entry => { - return ( - - ); - }) -}; + let localName=entries[0].sender; + return entries.map(entry => { + return ( + + ); + }); +}; From 34b4277d6058429ab5ae89b4e5f0adcf7f10dd50 Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Sun, 15 Jun 2025 16:45:23 -0700 Subject: [PATCH 7/8] fixed identation --- src/components/ChatLog.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index 68f93e3be..ec3df7754 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -24,13 +24,13 @@ const ChatLog = ({entries,onItemLikedToggle}) => { ChatLog.propTypes = { - entries: PropTypes.arrayOf( + entries: PropTypes.arrayOf( PropTypes.shape({ - id: PropTypes.number.isRequired, - sender: PropTypes.string.isRequired, - body: PropTypes.string.isRequired, - timeStamp: PropTypes.string.isRequired, - liked: PropTypes.bool.isRequired, + id: PropTypes.number.isRequired, + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, }) ).isRequired, onItemLikedToggle: PropTypes.func.isRequired From 52b32e10acb5f7b3db1d67f318ac95f3ff95c6f6 Mon Sep 17 00:00:00 2001 From: Mariya Mokrynska Date: Tue, 24 Jun 2025 22:51:08 -0700 Subject: [PATCH 8/8] fixed to pass tests --- src/App.jsx | 2 +- src/components/ChatLog.jsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 3fa8e91cd..3e21fed98 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -8,7 +8,7 @@ const DATA = [ 'sender': 'Vladimir', 'body': 'why are you arguing with me', 'timeStamp': '2018-05-29T22:49:06+00:00', - 'liked': true + 'liked': false }, { 'id': 2, diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index ec3df7754..a90372938 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -4,7 +4,8 @@ import PropTypes from 'prop-types'; const ChatLog = ({entries,onItemLikedToggle}) => { - let localName=entries[0].sender; + if (entries.length === 0) return null; + const localName = entries[0].sender; return entries.map(entry => { return (