From add86c824ffea591b8b50d4782c59640fa1ae8a7 Mon Sep 17 00:00:00 2001 From: mckay Date: Thu, 26 Jan 2023 16:54:14 -0500 Subject: [PATCH 1/5] implement ChatEntry component --- src/App.js | 8 ++++++++ src/components/ChatEntry.js | 11 +++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index c10859093..51460db0f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,14 +1,22 @@ import React from 'react'; import './App.css'; +import ChatEntry from './components/ChatEntry'; import chatMessages from './data/messages.json'; const App = () => { + const firstMessage = chatMessages[0]; + return (

Application title

+ {/* Wave 01: Render one ChatEntry component Wave 02: Render ChatLog component */}
diff --git a/src/components/ChatEntry.js b/src/components/ChatEntry.js index b92f0b7b2..8e7640688 100644 --- a/src/components/ChatEntry.js +++ b/src/components/ChatEntry.js @@ -1,14 +1,17 @@ import React from 'react'; import './ChatEntry.css'; import PropTypes from 'prop-types'; +import TimeStamp from './TimeStamp'; -const ChatEntry = (props) => { +const ChatEntry = ({ sender, body, timeStamp }) => { return (
-

Replace with name of sender

+

{sender}

-

Replace with body of ChatEntry

-

Replace with TimeStamp component

+

{body}

+

+ +

From 4d6c053b7bd3455cbadf64b1e12e53495a67c2e5 Mon Sep 17 00:00:00 2001 From: mckay Date: Thu, 26 Jan 2023 22:05:57 -0500 Subject: [PATCH 2/5] implemented wave 2 --- src/App.js | 11 ++------ src/components/ChatEntry.js | 6 ++-- src/components/ChatEntry.test.js | 16 +++++------ src/components/ChatLog.js | 19 +++++++++++++ src/components/ChatLog.test.js | 48 ++++++++++++++++---------------- 5 files changed, 57 insertions(+), 43 deletions(-) create mode 100644 src/components/ChatLog.js diff --git a/src/App.js b/src/App.js index 51460db0f..edf008b4f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,17 @@ import React from 'react'; import './App.css'; import ChatEntry from './components/ChatEntry'; +import ChatLog from './components/ChatLog'; import chatMessages from './data/messages.json'; const App = () => { - const firstMessage = chatMessages[0]; - return (

Application title

- - {/* Wave 01: Render one ChatEntry component - Wave 02: Render ChatLog component */} +
); diff --git a/src/components/ChatEntry.js b/src/components/ChatEntry.js index 8e7640688..6710a65dd 100644 --- a/src/components/ChatEntry.js +++ b/src/components/ChatEntry.js @@ -3,7 +3,7 @@ import './ChatEntry.css'; import PropTypes from 'prop-types'; import TimeStamp from './TimeStamp'; -const ChatEntry = ({ sender, body, timeStamp }) => { +const ChatEntry = ({ id, sender, body, timeStamp }) => { return (

{sender}

@@ -19,7 +19,9 @@ const ChatEntry = ({ sender, body, timeStamp }) => { }; ChatEntry.propTypes = { - //Fill with correct proptypes + sender: PropTypes.string.isRequired, + body: PropTypes.string, + timeStamp: PropTypes.string, }; export default ChatEntry; diff --git a/src/components/ChatEntry.test.js b/src/components/ChatEntry.test.js index b69270c03..4a9a2b09f 100644 --- a/src/components/ChatEntry.test.js +++ b/src/components/ChatEntry.test.js @@ -1,9 +1,9 @@ -import React from "react"; -import "@testing-library/jest-dom/extend-expect"; -import ChatEntry from "./ChatEntry"; -import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import React from 'react'; +import '@testing-library/jest-dom/extend-expect'; +import ChatEntry from './ChatEntry'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -describe("Wave 01: ChatEntry", () => { +describe('Wave 01: ChatEntry', () => { beforeEach(() => { render( { ); }); - test("renders without crashing and shows the sender", () => { + test('renders without crashing and shows the sender', () => { expect(screen.getByText(/Joe Biden/)).toBeInTheDocument(); }); - test("that it will display the body", () => { + test('that it will display the body', () => { expect(screen.getByText(/Get out by 8am/)).toBeInTheDocument(); }); - test("that it will display the time", () => { + test('that it will display the time', () => { expect(screen.getByText(/\d+ years ago/)).toBeInTheDocument(); }); }); diff --git a/src/components/ChatLog.js b/src/components/ChatLog.js new file mode 100644 index 000000000..0d5daa197 --- /dev/null +++ b/src/components/ChatLog.js @@ -0,0 +1,19 @@ +import React from 'react'; +import ChatEntry from './ChatEntry'; +import './ChatLog.css'; + +const ChatLog = ({ entries }) => { + const entriesComponents = entries.map((entry) => { + return ( + + ); + }); + return
{entriesComponents}
; +}; + +export default ChatLog; diff --git a/src/components/ChatLog.test.js b/src/components/ChatLog.test.js index 96f89ebc3..5bafee291 100644 --- a/src/components/ChatLog.test.js +++ b/src/components/ChatLog.test.js @@ -1,49 +1,49 @@ -import React from "react"; -import "@testing-library/jest-dom/extend-expect"; -import ChatLog from "./ChatLog"; -import { render, screen } from "@testing-library/react"; +import React from 'react'; +import '@testing-library/jest-dom/extend-expect'; +import ChatLog from './ChatLog'; +import { render, screen } from '@testing-library/react'; const LOG = [ { - sender: "Vladimir", - body: "why are you arguing with me", - timeStamp: "2018-05-29T22:49:06+00:00", + sender: 'Vladimir', + body: 'why are you arguing with me', + timeStamp: '2018-05-29T22:49:06+00:00', }, { - sender: "Estragon", - body: "Because you are wrong.", - timeStamp: "2018-05-29T22:49:33+00:00", + sender: 'Estragon', + body: 'Because you are wrong.', + timeStamp: '2018-05-29T22:49:33+00:00', }, { - sender: "Vladimir", - body: "because I am what", - timeStamp: "2018-05-29T22:50:22+00:00", + sender: 'Vladimir', + body: 'because I am what', + timeStamp: '2018-05-29T22:50:22+00:00', }, { - sender: "Estragon", - body: "A robot.", - timeStamp: "2018-05-29T22:52:21+00:00", + sender: 'Estragon', + body: 'A robot.', + timeStamp: '2018-05-29T22:52:21+00:00', }, { - sender: "Vladimir", - body: "Notabot", - timeStamp: "2019-07-23T22:52:21+00:00", + sender: 'Vladimir', + body: 'Notabot', + timeStamp: '2019-07-23T22:52:21+00:00', }, ]; -describe("Wave 02: ChatLog", () => { +describe('Wave 02: ChatLog', () => { beforeEach(() => { render(); }); - test("renders without crashing and shows all the names", () => { + test('renders without crashing and shows all the names', () => { [ { - name: "Vladimir", + name: 'Vladimir', numChats: 3, }, { - name: "Estragon", + name: 'Estragon', numChats: 2, }, ].forEach((person) => { @@ -56,7 +56,7 @@ describe("Wave 02: ChatLog", () => { }); }); - test("renders an empty list without crashing", () => { + test('renders an empty list without crashing', () => { const element = render(); expect(element).not.toBeNull(); }); From fb61bc90d69aa80b4655610a3b7dea22b96611e4 Mon Sep 17 00:00:00 2001 From: mckay Date: Tue, 31 Jan 2023 19:27:47 -0500 Subject: [PATCH 3/5] add state and event handling for liked messages --- src/App.js | 17 ++++++++++++++--- src/components/ChatEntry.js | 21 +++++++++++++++++++-- src/components/ChatLog.js | 19 +++++++++++++++++-- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/App.js b/src/App.js index edf008b4f..0ca50d3d9 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,28 @@ -import React from 'react'; +import React, { useState } from 'react'; import './App.css'; -import ChatEntry from './components/ChatEntry'; import ChatLog from './components/ChatLog'; import chatMessages from './data/messages.json'; const App = () => { + const [entries, setEntries] = useState(chatMessages); + + const updateEntry = (entryToUpdate) => { + const updatedEntries = entries.map((entry) => { + if (entry.id === entryToUpdate.id) { + return entryToUpdate; + } + return entry; + }); + setEntries(updatedEntries); + }; + return (

Application title

- +
); diff --git a/src/components/ChatEntry.js b/src/components/ChatEntry.js index 6710a65dd..7edeba28a 100644 --- a/src/components/ChatEntry.js +++ b/src/components/ChatEntry.js @@ -3,7 +3,19 @@ import './ChatEntry.css'; import PropTypes from 'prop-types'; import TimeStamp from './TimeStamp'; -const ChatEntry = ({ id, sender, body, timeStamp }) => { +const ChatEntry = ({ id, sender, body, timeStamp, liked, onUpdateLiked }) => { + const toggleLikes = () => { + onUpdateLiked({ + id, + sender, + body, + timeStamp, + liked: !liked, + }); + }; + + const heartColor = liked ? '❤️' : '🤍'; + return (

{sender}

@@ -12,16 +24,21 @@ const ChatEntry = ({ id, sender, body, timeStamp }) => {

- +
); }; ChatEntry.propTypes = { + id: PropTypes.number.isRequired, sender: PropTypes.string.isRequired, body: PropTypes.string, timeStamp: PropTypes.string, + liked: PropTypes.bool.isRequired, + onUpdateLiked: PropTypes.func.isRequired, }; export default ChatEntry; diff --git a/src/components/ChatLog.js b/src/components/ChatLog.js index 0d5daa197..2244cb648 100644 --- a/src/components/ChatLog.js +++ b/src/components/ChatLog.js @@ -1,8 +1,8 @@ -import React from 'react'; import ChatEntry from './ChatEntry'; +import PropTypes from 'prop-types'; import './ChatLog.css'; -const ChatLog = ({ entries }) => { +const ChatLog = ({ entries, onUpdateLiked }) => { const entriesComponents = entries.map((entry) => { return ( { sender={entry.sender} body={entry.body} timeStamp={entry.timeStamp} + liked={entry.liked} + onUpdateLiked={onUpdateLiked} /> ); }); return
{entriesComponents}
; }; +ChatLog.propTypes = { + entries: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + sender: PropTypes.string.isRequired, + body: PropTypes.string, + timeStamp: PropTypes.string, + liked: PropTypes.bool.isRequired, + }).isRequired + ), + onUpdateLiked: PropTypes.func.isRequired, +}; + export default ChatLog; From a722cbbed648fd193f7e28ce15ebba74e0a18337 Mon Sep 17 00:00:00 2001 From: mckay Date: Tue, 31 Jan 2023 20:29:22 -0500 Subject: [PATCH 4/5] add heart count display --- src/App.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/App.js b/src/App.js index 0ca50d3d9..a4ab27084 100644 --- a/src/App.js +++ b/src/App.js @@ -6,6 +6,16 @@ import chatMessages from './data/messages.json'; const App = () => { const [entries, setEntries] = useState(chatMessages); + const getTotalHearts = () => { + let totalHearts = 0; + entries.forEach((entry) => { + if (entry.liked) { + totalHearts++; + } + }); + return totalHearts; + }; + const updateEntry = (entryToUpdate) => { const updatedEntries = entries.map((entry) => { if (entry.id === entryToUpdate.id) { @@ -20,6 +30,11 @@ const App = () => {

Application title

+
+

+ {getTotalHearts()} ❤️s +

+
From 80df53dd2526ca0141f0507893549c984ecdd7d5 Mon Sep 17 00:00:00 2001 From: mckay Date: Wed, 1 Feb 2023 15:09:32 -0500 Subject: [PATCH 5/5] add key to ChatEntry components --- src/components/ChatLog.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/ChatLog.js b/src/components/ChatLog.js index 2244cb648..5b673e7a7 100644 --- a/src/components/ChatLog.js +++ b/src/components/ChatLog.js @@ -6,6 +6,7 @@ const ChatLog = ({ entries, onUpdateLiked }) => { const entriesComponents = entries.map((entry) => { return (