Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion project-docs/wave-03.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ In this wave we will update the components to manage a **like** feature.
## Tests

The tests for this component are integration tests. They don't make assumptions about the implementation details of like feature. The tests verify the following functionality:
- When the user click on a 🤍 button it changes to a ❤️, and when the user clicks on a ❤️ it changes to a 🤍. This test also verifies that clicking on one `ChatEntry`'s like button (🤍) doesn't change other `ChatEntry`'s buttons.
- When the user clicks on a 🤍 button it changes to a ❤️, and when the user clicks on a ❤️ it changes to a 🤍. This test also verifies that clicking on one `ChatEntry`'s like button (🤍) doesn't change other `ChatEntry`'s buttons.
- The correct number of filled hearts is displayed at the top of the screen.
- If you make a design decision to use a different emoji, you will need to change the tests accordingly.
43 changes: 40 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,53 @@
import React from 'react';
import './App.css';
import chatMessages from './data/messages.json';
// import ChatEntry from './components/ChatEntry';
import ChatLog from './components/ChatLog';
import { useState } from 'react';


const App = () => {
const [chatData, setChatData] = useState(chatMessages);
// {
// 'sender':'Vladimir',
// 'body':'why are you arguing with me',
// 'timeStamp':'2018-05-29T22:49:06+00:00',
// }
Comment on lines +11 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be sure to remove unused code, print tests, and any comments that shouldn't be published before finalizing a project. It's good practice to keep a clean main branch that's production ready. This helps with the readability and maintainability of a project. 🧹😌


const updateChatData = (updatedChatEntry) => {
const updatedChatEntries = chatData.map((chatEntry) => {
if (chatEntry.id === updatedChatEntry.id) {
return updatedChatEntry;
} else {
return chatEntry;
}
});

setChatData(updatedChatEntries);
};

const likeCounts = () => {
let likeCount = 0;
for (let entry of chatData) {
if (entry.liked === true) {
likeCount += 1;
}
}
return likeCount;
};
Comment on lines +29 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job calculating the number of likes from state! ✨


return (
<div id="App">
<header>
<h1>Application title</h1>
<h1>Chat between Vladimir and Estragon</h1>
<h2>Total Number of Likes: {likeCounts()} ❤️s</h2>
</header>
<main>
{/* Wave 01: Render one ChatEntry component
Wave 02: Render ChatLog component */}
{/* <ChatEntry sender={chatData.sender} body={chatData.body} timeStamp={chatData.timeStamp}></ChatEntry> */}
<ChatLog
entries={chatData}
onUpdateChatData={updateChatData}
></ChatLog>
</main>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/ChatEntry.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ button {

.chat-entry.remote .entry-bubble:hover::before {
background-color: #a9f6f6;
}
}
37 changes: 32 additions & 5 deletions src/components/ChatEntry.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
import React from 'react';
import './ChatEntry.css';
import PropTypes from 'prop-types';
import TimeStamp from './TimeStamp';
// import { useState } from 'react';

const ChatEntry = (props) => {
// const [isLiked, setIsLiked] = useState(false);

// const toggleLike = () => {
// setIsLiked(!isLiked);
// };

const onLikeButtonClick = () => {
const updatedChatEntry = {
id: props.id,
sender: props.sender,
body: props.body,
timeStamp: props.timeStamp,
liked: !props.liked,
};
props.onUpdate(updatedChatEntry);
};

const like = props.liked ? '❤️' : '🤍';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good usage of the ternary operator ✨


return (
<div className="chat-entry local">
<h2 className="entry-name">Replace with name of sender</h2>
<h2 className="entry-name">{props.sender}</h2>
<section className="entry-bubble">
<p>Replace with body of ChatEntry</p>
<p className="entry-time">Replace with TimeStamp component</p>
<button className="like">🤍</button>
<p>{props.id}</p>
<p>{props.body}</p>
<p className="entry-time"><TimeStamp time={props.timeStamp}></TimeStamp></p>
<button className="like" onClick={onLikeButtonClick}>{like}</button>
</section>
</div>
);
};

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,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend having liked be a required prop here too

onUpdate: PropTypes.func.isRequired,
};

export default ChatEntry;
42 changes: 42 additions & 0 deletions src/components/ChatLog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import './ChatLog.css';
import PropTypes from 'prop-types';
import ChatEntry from './ChatEntry';

const ChatLog = (props) => {
const chatEntryComponents = props.entries.map((entry, index) => {
return (
<li key={index}>
<ChatEntry
Comment on lines +7 to +10

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that it's best practice not to use the index of an item as the list item key in React since the order of items in an array can change. I'd recommend using the entry ID as the key. Also, to cut down on the number of tags, you can put the key attribute directly on the <ChatEntry> component and drop the <li> tag. This means you also won't need the <ul> tag on line 24.

id={entry.id}
sender={entry.sender}
body={entry.body}
timeStamp={entry.timeStamp}
liked={entry.liked}
onUpdate={props.onUpdateChatData}
></ChatEntry>
</li>
);
});

return (
<section className="chat-log">
<ul>{chatEntryComponents}</ul>
</section>
);
};

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,
})
),
Comment on lines +29 to +38

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job with your prop types! I'd recommend making liked required and also the entries array required too.

onUpdateChatData: PropTypes.func.isRequired,
};

export default ChatLog;