diff --git a/src/App.css b/src/App.css
index d97beb4e..a5549b56 100644
--- a/src/App.css
+++ b/src/App.css
@@ -27,6 +27,9 @@
}
#App header section {
+ display: flex;
+ justify-content: space-around;
+ color: black;
background-color: #e0ffff;
}
diff --git a/src/App.jsx b/src/App.jsx
index 14a7f684..7ac5d3be 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,14 +1,76 @@
+import { useState } from 'react';
+import messages from './data/messages.json';
+import ChatLog from './components/ChatLog';
+import ColorChoice from './components/ColorChoice';
import './App.css';
+const numOfLikes = (messageData) => {
+ return messageData.reduce(
+ (count, message) => {
+ return message.liked ? count + 1 : count;
+ },
+ 0
+ );
+};
+
const App = () => {
+ const [messageData, setMessageData] = useState(messages);
+ const [messageColors, setMessageColors] = useState({ local: 'green', remote: 'blue' });
+
+ const localSender = messageData[0]?.sender;
+ const remoteSender = messageData.find(message => message.sender !== localSender)?.sender;
+
+ const handleLikeStatus = messageId => {
+ setMessageData((prevMessages) => (
+ prevMessages.map(message =>
+ message.id === messageId
+ ? { ...message, liked: !message.liked }
+ : message
+ )
+ ));
+ };
+
+ const getSenderType = (senderName) => (
+ senderName === localSender ? 'local' : 'remote'
+ );
+
+ const updateMessageColor = (sender, color) => {
+ const senderType = getSenderType(sender);
+ setMessageColors(prevColors => (
+ { ...prevColors, [senderType]: color }
+ ));
+ };
+
+ const totalLikes = numOfLikes(messageData);
+
return (
- Application title
+
+ Chat Between{' '}
+ {localSender}{' '}
+ and{' '}
+ {remoteSender}
+
+
+
+
{localSender}'s color:
+
+
+ {totalLikes} ❤️s
+
+
{remoteSender}'s color:
+
+
+
- {/* Wave 01: Render one ChatEntry component
- Wave 02: Render ChatLog component */}
+
);
diff --git a/src/components/ChatEntry.css b/src/components/ChatEntry.css
index 05c3baa4..d0e8d653 100644
--- a/src/components/ChatEntry.css
+++ b/src/components/ChatEntry.css
@@ -97,4 +97,5 @@ button {
.chat-entry.remote .entry-bubble:hover::before {
background-color: #a9f6f6;
-}
\ No newline at end of file
+}
+
diff --git a/src/components/ChatEntry.jsx b/src/components/ChatEntry.jsx
index fe05efa0..f625a518 100644
--- a/src/components/ChatEntry.jsx
+++ b/src/components/ChatEntry.jsx
@@ -1,21 +1,41 @@
+import PropTypes from 'prop-types';
import './ChatEntry.css';
+import TimeStamp from './TimeStamp';
+import { messageDataProtoTypes, messageColorsProtoTypes } from './sharedPropTypes';
+
+const ChatEntry = ({
+ id,
+ sender,
+ body,
+ timeStamp,
+ liked,
+ onToggleLike,
+ messageColors,
+ getSenderType,
+}) => {
+
+ const senderType = getSenderType && getSenderType(sender);
-const ChatEntry = () => {
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
+ ...messageDataProtoTypes,
+ onToggleLike: PropTypes.func,
+ messageColors: PropTypes.shape(
+ messageColorsProtoTypes
+ ),
+ getSenderType: PropTypes.func,
};
export default ChatEntry;
diff --git a/src/components/ChatEntry.test.jsx b/src/components/ChatEntry.test.jsx
index 85eff925..084ed5bc 100644
--- a/src/components/ChatEntry.test.jsx
+++ b/src/components/ChatEntry.test.jsx
@@ -15,6 +15,7 @@ describe('Wave 01: ChatEntry', () => {
);
});
+
test('renders without crashing and shows the sender', () => {
expect(screen.getByText(/Joe Biden/)).toBeInTheDocument();
});
diff --git a/src/components/ChatLog.css b/src/components/ChatLog.css
index 378848d1..02100de1 100644
--- a/src/components/ChatLog.css
+++ b/src/components/ChatLog.css
@@ -2,3 +2,5 @@
margin: auto;
max-width: 50rem;
}
+
+
diff --git a/src/components/ChatLog.jsx b/src/components/ChatLog.jsx
new file mode 100644
index 00000000..b2510039
--- /dev/null
+++ b/src/components/ChatLog.jsx
@@ -0,0 +1,42 @@
+import PropTypes from 'prop-types';
+import './ChatLog.css';
+import ChatEntry from './ChatEntry';
+import { messageDataProtoTypes, messageColorsProtoTypes } from './sharedPropTypes';
+
+const ChatLog = ({
+ entries,
+ onToggleMessageLike,
+ messageColors,
+ getSenderType,
+}) => {
+
+ return (
+
+ {entries.map(message =>
+ )}
+
+ );
+};
+
+ChatLog.propTypes = {
+ entries: PropTypes.arrayOf(PropTypes.shape({
+ ...messageDataProtoTypes
+ })).isRequired,
+ onToggleMessageLike: PropTypes.func,
+ messageColors: PropTypes.shape(
+ messageColorsProtoTypes
+ ),
+ getSenderType: PropTypes.func,
+};
+
+export default ChatLog;
\ No newline at end of file
diff --git a/src/components/ColorChoice.css b/src/components/ColorChoice.css
new file mode 100644
index 00000000..47f6f327
--- /dev/null
+++ b/src/components/ColorChoice.css
@@ -0,0 +1,9 @@
+.color-container {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+}
+
+.button-size {
+ font-size: 2rem;
+}
\ No newline at end of file
diff --git a/src/components/ColorChoice.jsx b/src/components/ColorChoice.jsx
new file mode 100644
index 00000000..687ddae2
--- /dev/null
+++ b/src/components/ColorChoice.jsx
@@ -0,0 +1,29 @@
+import PropTypes from 'prop-types';
+import './ColorChoice.css';
+
+const COLORS = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
+
+const ColorChoice = ({ sender, onUpdateColor }) => {
+ return (
+
+ {COLORS.map((color, index) => {
+ return (
+
+ );
+ })}
+
+ );
+};
+
+ColorChoice.propTypes = {
+ sender: PropTypes.string.isRequired,
+ onUpdateColor: PropTypes.func.isRequired
+};
+
+export default ColorChoice;
diff --git a/src/components/sharedPropTypes.js b/src/components/sharedPropTypes.js
new file mode 100644
index 00000000..a3296c20
--- /dev/null
+++ b/src/components/sharedPropTypes.js
@@ -0,0 +1,14 @@
+import PropTypes from 'prop-types';
+
+export const messageDataProtoTypes = {
+ id: PropTypes.number.isRequired,
+ sender: PropTypes.string.isRequired,
+ body: PropTypes.string.isRequired,
+ timeStamp: PropTypes.string.isRequired,
+ liked: PropTypes.bool.isRequired,
+};
+
+export const messageColorsProtoTypes = {
+ local: PropTypes.string.isRequired,
+ remote: PropTypes.string.isRequired,
+};
\ No newline at end of file