diff --git a/project-docs/wave-01.md b/project-docs/wave-01.md index cf05e2651..6b3309504 100644 --- a/project-docs/wave-01.md +++ b/project-docs/wave-01.md @@ -1,8 +1,7 @@ # Wave 01: Presentational Component **Learn Topics: React Components and Props required for this wave** - -Update the `ChatEntry` and `App` components to display a single chat message bubble with the message text and relative timestamp, plus the sender's name above it. + A good way to test this code as you write it would be to take the first chat message from the [JSON data file](../src/data/messages.json) and use it as the data for the `ChatEntry` component. diff --git a/src/App.jsx b/src/App.jsx index 14a7f684d..c75e798e8 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,14 +1,36 @@ +import { useState } from 'react'; +import ChatLog from './components/ChatLog'; +import initialMessages from './data/messages'; import './App.css'; const App = () => { + const senders = Array.from(new Set(initialMessages.map(initialMessage => initialMessage.sender))); + const chatHeader = `Chat between ${senders.join(' and ')}`; + + const [messages, setMessages] = useState(initialMessages); + + const toggleLike = (id) => { + setMessages((prevMessages) => + prevMessages.map((message) => + message.id === id + ? { ...message, liked: !message.liked } + : message + ) + ); + }; + + const getTotalLikes = () => { + return messages.filter((message) => message.liked).length; + }; + return (
-

Application title

+

{chatHeader}

+

{getTotalLikes()} ❤️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 15c56f96b..2f97bd6bd 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -1,20 +1,32 @@ +import PropTypes from 'prop-types'; import './ChatEntry.css'; +import TimeStamp from './TimeStamp.jsx'; -const ChatEntry = () => { +const ChatEntry = ({ sender, body, timeStamp, liked, onLikeToggle, type }) => { return ( -
-

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, + timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, + onLikeToggle: PropTypes.func.isRequired, }; export default ChatEntry; + + diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx new file mode 100644 index 000000000..6402d5a22 --- /dev/null +++ b/src/components/ChatLog.jsx @@ -0,0 +1,38 @@ +import PropTypes from 'prop-types'; +import ChatEntry from './ChatEntry'; +import './ChatLog.css'; +import messages from '../data/messages'; + +const localUser = messages.length > 0 ? messages[0].sender : null; +const ChatLog = ({ entries, toggleLike }) => { + return ( +
+ {entries.map((entry) => ( + toggleLike(entry.id)} + type={entry.sender === localUser ? 'local' : 'remote'} + /> + ))} +
+ ); +}; + +ChatLog.propTypes = { + 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, + }) + ).isRequired, + toggleLike: PropTypes.func.isRequired, +}; + +export default ChatLog; \ No newline at end of file diff --git a/src/data/messages.json b/src/data/messages.json index 64fdb053c..3393000ae 100644 --- a/src/data/messages.json +++ b/src/data/messages.json @@ -4,188 +4,215 @@ "sender":"Vladimir", "body":"why are you arguing with me", "timeStamp":"2018-05-29T22:49:06+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 2, "sender":"Estragon", "body":"Because you are wrong.", "timeStamp":"2018-05-29T22:49:33+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 3, "sender":"Vladimir", "body":"because I am what", "timeStamp":"2018-05-29T22:50:22+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 4, "sender":"Estragon", "body":"A robot.", "timeStamp":"2018-05-29T22:52:21+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 5, "sender":"Vladimir", "body":"how did you know", "timeStamp":"2018-05-29T22:52:58+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 6, "sender":"Estragon", "body":"Because I'm smart like that.", "timeStamp":"2018-05-29T22:54:28+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 7, "sender":"Vladimir", "body":"no you are not 😀", "timeStamp":"2018-05-29T22:55:03+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 8, "sender":"Estragon", "body":"Why are you so mean to me?", "timeStamp":"2018-05-29T22:55:54+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "id": 10, "sender":"Estragon", "body":"No, you are the machine.", "timeStamp":"2018-05-29T22:57:47+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 11, "sender":"Vladimir", "body":"I think you are", "timeStamp":"2018-05-29T22:58:18+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "id": 15, "sender":"Vladimir", "body":"you are a robot called Cleverbot", "timeStamp":"2018-05-29T23:02:17+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "id": 17, "sender":"Vladimir", "body":"explain", "timeStamp":"2018-05-29T23:06:14+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "id": 19, "sender":"Vladimir", "body":"so you are a human", "timeStamp":"2018-05-29T23:08:47+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 20, "sender":"Estragon", "body":"I am a robot.", "timeStamp":"2018-05-29T23:09:36+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 21, "sender":"Vladimir", "body":"you are robots running on Android system", "timeStamp":"2018-05-29T23:11:01+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 22, "sender":"Estragon", "body":"No apple.", "timeStamp":"2018-05-29T23:12:03+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 23, "sender":"Vladimir", "body":"so you are a robot", "timeStamp":"2018-05-29T23:13:31+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 24, "sender":"Estragon", "body":"NO, I am a human, you are a robot.", "timeStamp":"2018-05-29T23:14:28+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "id": 25, "sender":"Vladimir", "body":"but you just said that you are robots", "timeStamp":"2018-05-29T23:15:47+00:00", - "liked": false + "liked": false, + "likeCount": 0 }, { "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 + "liked": false, + "likeCount": 0 }, { "id": 27, "sender":"Vladimir", "body":"then you are lying", "timeStamp":"2018-05-29T23:17:34+00:00", - "liked": false + "liked": false, + "likeCount": 0 } ]