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
38 changes: 35 additions & 3 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,46 @@
import { useState } from 'react';
import './App.css';
import ChatLog from './components/ChatLog';
import messages from './data/messages.json'


// import data from messages.json
const LOG = messages;
Comment on lines +4 to +8

Choose a reason for hiding this comment

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

You can directly name messages as LOG on line 4.

Suggested change
import messages from './data/messages.json'
// import data from messages.json
const LOG = messages;
import LOG from './data/messages.json';

Be sure to terminate a statement with semi-colons.



const App = () => {
const [entries, setEntries] = useState(LOG);

// update chat entry => like change
const toggleLike = (id) => {
const updatedEntries = entries.map(entry => {
if (entry.id === id) {
// toggle like
return {... entry, liked: !entry.liked};
} else {
// no change
return entry;
}
});
// update entries
setEntries(updatedEntries);
}

const totalLikes = entries.filter(entry => entry.liked).length;

Choose a reason for hiding this comment

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

Typically, you'd see reduce used to add up some values.

const totalLikes = entries.reduce((totalLikes, entry) => (totalLikes + entry.liked);


return (
<div id="App">
<header>
<h1>Application title</h1>
<h1>Chat Between {entries[0].sender} and {entries[1].sender} </h1>
<h2 id="heartWidget">{totalLikes} ❤️s </h2>
</header>
<main>
{/* Wave 01: Render one ChatEntry component
Wave 02: Render ChatLog component */}
<div>
<ChatLog
entries={entries}
onLikeToggle={toggleLike}
/>
</div>
</main>
</div>
);
Expand Down
38 changes: 31 additions & 7 deletions src/components/ChatEntry.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
import './ChatEntry.css';
import PropTypes from 'prop-types';
import TimeStamp from './TimeStamp';

const ChatEntry = ({id, sender, body, timeStamp,liked, onLikeToggle}) => {

Choose a reason for hiding this comment

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

Suggested change
const ChatEntry = ({id, sender, body, timeStamp,liked, onLikeToggle}) => {
const ChatEntry = ({ id, sender, body, timeStamp,liked, onLikeToggle }) => {

Spaces around curly braces when destructuring


Choose a reason for hiding this comment

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

Linter says "Block must not be padded by blank lines". Remove line 6

Suggested change

Choose a reason for hiding this comment

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

Uploading image.png…
My linter shows all the style issues here. See the pink and green squiggley lines. I recommend configuring your linter so you can catch these issues before opening a PR.

const handleHeartClick = () => {
onLikeToggle(id);
};

let isLocalUser = false

Choose a reason for hiding this comment

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

Suggested change
let isLocalUser = false
let isLocalUser = false;


if (sender === 'Vladimir') {
isLocalUser = true;
}

Choose a reason for hiding this comment

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

Suggested change
}
} ;

Linter calls out that you're missing semi-colons. if you haven't configured your linter, you might want to do that so it can highlight syntax/style issues.

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.

Would prefer to have this logic put in a method and the method get called somewhere.

Suggested change
let isLocalUser = false
if (sender === 'Vladimir') {
isLocalUser = true;
}
const setLocalOrRemote () => {
return sender == 'Vladimir' ? 'local' : 'remote';
};

Then on line 18, you can call the function:

    <div className={`chat-entry ${setLocalOrRemote()}`}>


const ChatEntry = () => {
return (
<div className="chat-entry local">
<h2 className="entry-name">Replace with name of sender</h2>
<div className={isLocalUser?'chat-entry local':'chat-entry remote'}>
<h2 className="entry-name">{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 className='body'>{body}</p>
<TimeStamp time = {timeStamp}></TimeStamp>

Choose a reason for hiding this comment

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

Nice job using the provided Timestamp component here.

Convention is to not have spaces around = sign when passing props

Suggested change
<TimeStamp time = {timeStamp}></TimeStamp>
<TimeStamp time={timeStamp}></TimeStamp>

<button
className='like' //className from test

Choose a reason for hiding this comment

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

Prefer not to have comments in code unless absolutely necessary.

onClick={handleHeartClick}>
{liked ? '❤️' : '🤍'}
</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.isRequired,
onLikeToggle: PropTypes.func.isRequired,

};

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


const ChatLog = ({entries, onLikeToggle}) => {

Choose a reason for hiding this comment

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

Suggested change
const ChatLog = ({entries, onLikeToggle}) => {
const ChatLog = ({ entries, onLikeToggle }) => {

return (
<div className="chat-log">
{entries.map(entry => (
<ChatEntry
key={entry.id}
id={entry.id}
sender={entry.sender}
body={entry.body}
timeStamp={entry.timeStamp}
liked={entry.liked}
onLikeToggle={onLikeToggle}
/>
))}
</div>
);
};
Comment on lines +7 to +22
Copy link

@yangashley yangashley Dec 19, 2024

Choose a reason for hiding this comment

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

It's more typical to see the result of using map referenced by a variable and using that variable in the JSX, like:

    const chatLogs =  entries.map((entry) => {
	      return (
	          <ChatEntry                                 
	            key={entry.id}
	            id={entry.id}
	            sender={entry.sender}
	            body={entry.body}
	            timeStamp={entry.timeStamp}
	            liked={entry.liked}
	            handleLike={handleLike}
	            currentUser={currentUser}
	          />
	        );
	     });
    };

  return (
        <div className="chat-log">
            {chatLogs}
        </div>
  );


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,
onLikeToggle: PropTypes.func.isRequired,
};

export default ChatLog;