From bb2c2c113bf3f4ae1fed666333c254e9502bd95a Mon Sep 17 00:00:00 2001 From: geethavs88 Date: Sat, 13 Dec 2025 17:00:56 -0800 Subject: [PATCH 1/5] Completed wave01. Able to see one chat entry --- src/App.jsx | 23 +++++++++++++++++++++-- src/components/ChatEntry.jsx | 18 ++++++++++++------ src/components/ChatLog.jsx | 6 ++++++ 3 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 src/components/ChatLog.jsx diff --git a/src/App.jsx b/src/App.jsx index 14a7f684d..137726f15 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,15 @@ import './App.css'; +import messages from './data/messages.json'; +import ChatEntry from './components/ChatEntry'; +import ChatLog from './components/ChatLog'; + +const message1 = { + id: 1, + sender: 'Vladimir', + body: 'why are you arguing with me', + timeStamp: '2018-05-29T22:49:06+00:00', + liked: false +}; const App = () => { return ( @@ -7,11 +18,19 @@ const App = () => {

Application title

- {/* Wave 01: Render one ChatEntry component - Wave 02: Render ChatLog component */} + + { + + + /* Wave 01: Render one ChatEntry component + messages + Wave 02: Render ChatLog component */ + // + }
); }; export default App; + diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index fe05efa0f..44e52d9d7 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -1,21 +1,27 @@ import './ChatEntry.css'; +import TimeStamp from './TimeStamp.jsx'; +import PropTypes from 'prop-types'; -const ChatEntry = () => { + + +const ChatEntry = ({ sender, body, timeStamp }) => { return ( // Replace the outer tag name with a semantic element that fits our use case - -

Replace with name of sender

+
+

{sender}

-

Replace with body of ChatEntry

-

Replace with TimeStamp component

+

{body}

+

- +
); }; ChatEntry.propTypes = { // Fill with correct proptypes + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, }; export default ChatEntry; diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx new file mode 100644 index 000000000..3a04788fb --- /dev/null +++ b/src/components/ChatLog.jsx @@ -0,0 +1,6 @@ + + + +const ChatLog = (props) => { + +}; \ No newline at end of file From 89db8124fe546e6bd08ba150f15e9d707a23ef16 Mon Sep 17 00:00:00 2001 From: geethavs88 Date: Mon, 15 Dec 2025 14:14:18 -0800 Subject: [PATCH 2/5] added chatlog components --- src/App.jsx | 6 +++--- src/components/ChatEntry.jsx | 3 ++- src/components/ChatLog.jsx | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 137726f15..e0aaafd99 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -20,12 +20,12 @@ const App = () => {
{ - - + // + // /* Wave 01: Render one ChatEntry component messages Wave 02: Render ChatLog component */ - // + }
diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 44e52d9d7..d63787e59 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; -const ChatEntry = ({ sender, body, timeStamp }) => { +const ChatEntry = ({ id, sender, body, timeStamp }) => { return ( // Replace the outer tag name with a semantic element that fits our use case
@@ -22,6 +22,7 @@ ChatEntry.propTypes = { // Fill with correct proptypes sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired, }; export default ChatEntry; diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index 3a04788fb..c6b554000 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -1,6 +1,34 @@ +import ChatEntry from './ChatEntry.jsx'; +import './ChatLog.css'; +import PropTypes from 'prop-types'; +const ChatLog = ({ entries }) => { + const chatComponents = entries.map(entry => { + return ( + + ); + }); + return ( + <> + {chatComponents} + + + ); +}; +ChatLog.propTypes = { + entries: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.number.isRequired, + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired, + })).isRequired, +}; -const ChatLog = (props) => { -}; \ No newline at end of file +export default ChatLog; \ No newline at end of file From 46f1e64b205d52ad1d97de46d1a51104475feed2 Mon Sep 17 00:00:00 2001 From: geethavs88 Date: Mon, 15 Dec 2025 22:06:19 -0800 Subject: [PATCH 3/5] added behaviour to heart button --- src/App.jsx | 21 ++++++++++++++++++++- src/components/ChatEntry.css | 8 ++++++++ src/components/ChatEntry.jsx | 8 ++++++-- src/components/ChatLog.jsx | 12 ++++++++---- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index e0aaafd99..871769da0 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -2,6 +2,7 @@ import './App.css'; import messages from './data/messages.json'; import ChatEntry from './components/ChatEntry'; import ChatLog from './components/ChatLog'; +import { useState } from 'react'; const message1 = { id: 1, @@ -11,7 +12,23 @@ const message1 = { liked: false }; + + const App = () => { + const[chatData, setChatData] = useState(messages); + + const handleToggleLike = id =>{ + setChatData(chatData => { + return chatData.map(chat => { + if(chat.id === id) { + return ({ ...chat, liked: !chat.liked}); + } else { + return chat; + } + }); + }); + }; + return (
@@ -25,7 +42,9 @@ const App = () => { /* Wave 01: Render one ChatEntry component messages Wave 02: Render ChatLog component */ - + }
diff --git a/src/components/ChatEntry.css b/src/components/ChatEntry.css index 05c3baa44..3814909e2 100644 --- a/src/components/ChatEntry.css +++ b/src/components/ChatEntry.css @@ -97,4 +97,12 @@ button { .chat-entry.remote .entry-bubble:hover::before { background-color: #a9f6f6; +} +.gray { + color: gray; + +} +.red { + color: red; + } \ No newline at end of file diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index d63787e59..e615ed726 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -4,7 +4,9 @@ import PropTypes from 'prop-types'; -const ChatEntry = ({ id, sender, body, timeStamp }) => { +const ChatEntry = ({ id, sender, body, timeStamp, liked, toggleLike }) => { + + const heartColor = liked ? '❤️' : '🤍'; return ( // Replace the outer tag name with a semantic element that fits our use case
@@ -12,7 +14,7 @@ const ChatEntry = ({ id, sender, body, timeStamp }) => {

{body}

- +
); @@ -23,6 +25,8 @@ ChatEntry.propTypes = { sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, + toggleLike: PropTypes.func.isRequired, }; export default ChatEntry; diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index c6b554000..aaf16d360 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -2,22 +2,24 @@ import ChatEntry from './ChatEntry.jsx'; import './ChatLog.css'; import PropTypes from 'prop-types'; -const ChatLog = ({ entries }) => { +const ChatLog = ({ entries, toggleLike }) => { const chatComponents = entries.map(entry => { return ( + timeStamp={entry.timeStamp} + liked={entry.liked} + toggleLike={toggleLike}> ); }); return ( <> - {chatComponents} + {chatComponents} - + ); }; ChatLog.propTypes = { @@ -26,7 +28,9 @@ ChatLog.propTypes = { sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, })).isRequired, + toggleLike: PropTypes.func.isRequired, }; From e9cadd275e42cad8a04df015bf94ec0661ac755d Mon Sep 17 00:00:00 2001 From: geethavs88 Date: Mon, 15 Dec 2025 22:31:16 -0800 Subject: [PATCH 4/5] added the total likes functionality --- src/App.jsx | 18 ++++++++---------- src/components/ChatEntry.jsx | 2 +- src/components/ChatLog.jsx | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 871769da0..578fc392a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,21 +1,18 @@ import './App.css'; import messages from './data/messages.json'; -import ChatEntry from './components/ChatEntry'; + import ChatLog from './components/ChatLog'; import { useState } from 'react'; -const message1 = { - id: 1, - sender: 'Vladimir', - body: 'why are you arguing with me', - timeStamp: '2018-05-29T22:49:06+00:00', - liked: false +const countTotalLikes = (chatData) =>{ + return chatData.reduce((total, chat) => { + return total + (chat.liked ? 1 : 0); + }, 0); }; - - const App = () => { const[chatData, setChatData] = useState(messages); + const totalLikes = countTotalLikes(chatData); const handleToggleLike = id =>{ setChatData(chatData => { @@ -32,7 +29,8 @@ const App = () => { return (
-

Application title

+

Chat between Vladimir and Estragon

+

{totalLikes} ❤️s

diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index e615ed726..69e34211b 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -26,7 +26,7 @@ ChatEntry.propTypes = { body: PropTypes.string.isRequired, timeStamp: PropTypes.string.isRequired, liked: PropTypes.bool.isRequired, - toggleLike: PropTypes.func.isRequired, + toggleLike: PropTypes.func, }; export default ChatEntry; diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index aaf16d360..7b86bbdc3 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -30,7 +30,7 @@ ChatLog.propTypes = { timeStamp: PropTypes.string.isRequired, liked: PropTypes.bool.isRequired, })).isRequired, - toggleLike: PropTypes.func.isRequired, + toggleLike: PropTypes.func, }; From 09a973897cd4020b3503282625690af0239ead36 Mon Sep 17 00:00:00 2001 From: geethavs88 Date: Tue, 16 Dec 2025 06:05:19 -0800 Subject: [PATCH 5/5] Made small changes. Removed extra spaces --- src/App.jsx | 11 ++++------- src/components/ChatEntry.css | 8 -------- src/components/ChatEntry.jsx | 6 +----- src/components/ChatLog.jsx | 2 +- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 578fc392a..798ee2628 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,5 @@ import './App.css'; import messages from './data/messages.json'; - import ChatLog from './components/ChatLog'; import { useState } from 'react'; @@ -33,17 +32,15 @@ const App = () => {

{totalLikes} ❤️s

- { // // /* Wave 01: Render one ChatEntry component - messages - Wave 02: Render ChatLog component */ - + messages*/ } +
); diff --git a/src/components/ChatEntry.css b/src/components/ChatEntry.css index 3814909e2..ece5ad733 100644 --- a/src/components/ChatEntry.css +++ b/src/components/ChatEntry.css @@ -98,11 +98,3 @@ button { .chat-entry.remote .entry-bubble:hover::before { background-color: #a9f6f6; } -.gray { - color: gray; - -} -.red { - color: red; - -} \ No newline at end of file diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index 69e34211b..413463d09 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -2,13 +2,9 @@ import './ChatEntry.css'; import TimeStamp from './TimeStamp.jsx'; import PropTypes from 'prop-types'; - - const ChatEntry = ({ id, sender, body, timeStamp, liked, toggleLike }) => { - const heartColor = liked ? '❤️' : '🤍'; return ( - // Replace the outer tag name with a semantic element that fits our use case

{sender}

@@ -21,7 +17,7 @@ const ChatEntry = ({ id, sender, body, timeStamp, liked, toggleLike }) => { }; ChatEntry.propTypes = { - // Fill with correct proptypes + id: PropTypes.number.isRequired, sender: PropTypes.string.isRequired, body: PropTypes.string.isRequired, timeStamp: PropTypes.string.isRequired, diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx index 7b86bbdc3..6a17bf536 100644 --- a/src/components/ChatLog.jsx +++ b/src/components/ChatLog.jsx @@ -22,6 +22,7 @@ const ChatLog = ({ entries, toggleLike }) => { ); }; + ChatLog.propTypes = { entries: PropTypes.arrayOf(PropTypes.shape({ id: PropTypes.number.isRequired, @@ -34,5 +35,4 @@ ChatLog.propTypes = { }; - export default ChatLog; \ No newline at end of file