-
Notifications
You must be signed in to change notification settings - Fork 113
Ruby - Anh Huynh Chat Log #110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
270651d
a39e16c
f418fae
fbf7621
ec516a7
c27534f
521de59
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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', | ||
| // } | ||
|
|
||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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> | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,4 +97,4 @@ button { | |
|
|
||
| .chat-entry.remote .entry-bubble:hover::before { | ||
| background-color: #a9f6f6; | ||
| } | ||
| } | ||
| 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 ? '❤️' : '🤍'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd recommend having |
||
| onUpdate: PropTypes.func.isRequired, | ||
| }; | ||
|
|
||
| export default ChatEntry; | ||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice job with your prop types! I'd recommend making |
||
| onUpdateChatData: PropTypes.func.isRequired, | ||
| }; | ||
|
|
||
| export default ChatLog; | ||
There was a problem hiding this comment.
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. 🧹😌