diff --git a/src/App.jsx b/src/App.jsx index 14a7f684..1435dc86 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,17 +1,33 @@ import './App.css'; +import ChatLog from './components/ChatLog'; +import MessageData from './data/messages.json'; +import { useState } from 'react'; const App = () => { + const [messages, setMessages] = useState(MessageData); + const onClickLike = (id) => { + setMessages((prevMessages) => + prevMessages.map((entry) => + entry.id === id ? { ...entry, liked: !entry.liked } : entry + ) + ); + }; + + const likeCount = messages.filter((e) => e.liked).length; + return (
-

Application title

+

Chat between Vladimir and Estragon

+
+ {`${likeCount} ❤️s`} +
- {/* Wave 01: Render one ChatEntry component - Wave 02: Render ChatLog component */} +
); }; -export default App; +export default App; \ No newline at end of file diff --git a/src/components/ChatEntry.css b/src/components/ChatEntry.css index 05c3baa4..db6cd1d6 100644 --- a/src/components/ChatEntry.css +++ b/src/components/ChatEntry.css @@ -97,4 +97,14 @@ button { .chat-entry.remote .entry-bubble:hover::before { background-color: #a9f6f6; +} + +.red { + color: #ff0000; + font-weight: bold; +} + +.green { + color: green; + font-weight: bold; } \ No newline at end of file diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx index fe05efa0..270851ec 100644 --- a/src/components/ChatEntry.jsx +++ b/src/components/ChatEntry.jsx @@ -1,21 +1,40 @@ import './ChatEntry.css'; +import PropTypes from 'prop-types'; +import TimeStamp from './TimeStamp'; -const ChatEntry = () => { +const ChatEntry = ({ + id, + sender, + body, + timeStamp, + liked = false, + onToggleLike = () => {}, +}) => { + const sideClass = sender === 'Vladimir' ? 'local' : 'remote'; + const colorClass = sender === 'Vladimir' ? 'red' : 'green'; 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 + id: PropTypes.number.isRequired, + sender: PropTypes.string.isRequired, + body: PropTypes.string.isRequired, + timeStamp: PropTypes.string.isRequired, + liked: PropTypes.bool.isRequired, + onToggleLike: PropTypes.func }; -export default ChatEntry; +export default ChatEntry; \ No newline at end of file diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx new file mode 100644 index 00000000..d0d6152d --- /dev/null +++ b/src/components/ChatLog.jsx @@ -0,0 +1,36 @@ +import './ChatLog.css'; +import PropTypes from 'prop-types'; +import ChatEntry from './ChatEntry'; + +const ChatLog = ({ entries, onClickLike = () => {} }) => { + return ( +
+ {entries.map((message) => ( + + ))} +
+ ); +}; + +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, + }) + ), + onClickLike: PropTypes.func, +}; + +export default ChatLog; \ No newline at end of file