Skip to content
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

Sammy: project-happy-thoughts #436

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Happy Thoughts

Replace this readme with your own information about your project.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
Practice React state skills by fetching and posting data to an API.
The task was to follow a design but I kinda failed on that part.

## The problem

Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?
Hard to know what to put in components, had to remove/add/rearrange my code multiple times.
CSS, JS, React, API.

## View it live

Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about.
https://phenomenal-bavarois-c771f2.netlify.app/
18 changes: 18 additions & 0 deletions code/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"babel-eslint": "^10.1.0",
"date-fns": "^2.29.3",
"eslint": "^8.21.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.26.0",
Expand Down
2 changes: 1 addition & 1 deletion code/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Technigo React App</title>
<title>Happy Thougths React app!</title>
</head>

<body>
Expand Down
87 changes: 84 additions & 3 deletions code/src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,90 @@
import React from 'react';
/* eslint-disable linebreak-style */
/* eslint-disable no-underscore-dangle */
import Footer from 'components/Footer';
import React, { useState, useEffect } from 'react';
import Header from './components/Header'
import ThoughtForm from './components/ThoughtForm'
import ThoughtList from './components/ThoughtList'

export const App = () => {
const [thoughtList, setThoughtList] = useState([])
const [loading, setLoading] = useState(false)
const [newThought, setNewThought] = useState('')

/* FETCHES MOST RECENT THOUGHTS */
const fetchThoughts = () => {
setLoading(true);
fetch('https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts')
.then((res) => res.json())
.then((data) => setThoughtList(data))
.catch((error) => console.error(error))
.finally(() => setLoading(false))
}

useEffect(() => {
fetchThoughts();
}, [])

/* WRTIES NEW TEXT-INPUT-VALUE TO SETNEWTHOUGHT */
const handleNewThoughtChange = (event) => {
setNewThought(event.target.value)
}

/* POSTS NEW THOUGHT AND UPDATES STATE */

Choose a reason for hiding this comment

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

Good job commenting!

const postNewThought = () => {
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ message: newThought })
};

fetch('https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts', options)
.then((res) => res.json())
.then((data) => {
setThoughtList((prevList) => [data, ...prevList]);
});
}

const handleFormSubmit = (event) => {
event.preventDefault();
postNewThought();
setNewThought('')
};

/* POSTS NEW LIKES TO API */
const handleLike = (_id) => {
fetch(`https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts/${_id}/like`, { method: 'POST' })
.then((res) => {
return res.json();
})
.then((data) => {
const updateLikes = thoughtList.map((like) => {
if (like._id === data._id) {
like.hearts += 1;
return like;
} else {
return like;
}
});
setThoughtList(updateLikes)
})
}
return (
<div>
Find me in src/app.js!
<Header />
<main>
<ThoughtForm
onFormSubmit={handleFormSubmit}
newThought={newThought}
onNewThoughtChange={handleNewThoughtChange} />
<ThoughtList
loading={loading}
thoughtList={thoughtList}
handleLike={handleLike} />
</main>
<Footer />
</div>
);
}
}

Choose a reason for hiding this comment

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

Very nice structure in your App.js! Impressive!

13 changes: 13 additions & 0 deletions code/src/components/Footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';

const Footer = () => {
return (
<div aria-hidden="true" className="contact">
<p>Happy Thoughts made by <a href="https://www.linkedin.com/in/sammy-olsson/" target="_blank" rel="noreferrer">Sammy Olsson</a>,
Team-🐢
Comment on lines +6 to +7

Choose a reason for hiding this comment

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

Nice add with the contact information!

</p>
</div>
)
};

export default Footer;
14 changes: 14 additions & 0 deletions code/src/components/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* eslint-disable linebreak-style */
import React from 'react';
import logo from './assets/happy-logo.png'

const Header = () => {
return (
<header>
<div className="image-wrapper">
<img className="logo" src={logo} alt="logo happy thoughts" />
</div>
</header>)
}

export default Header;
37 changes: 37 additions & 0 deletions code/src/components/ThoughtForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* eslint-disable linebreak-style */
import React from 'react';

const ThoughtForm = ({ newThought, onNewThoughtChange, onFormSubmit }) => {
const isSubmitButtonDisabled = newThought.length < 6 || newThought.length > 140;
Comment on lines +4 to +5

Choose a reason for hiding this comment

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

Short and consistent code on the length parameters.

/* SHOWS CHARACTER-COUNT OR A WARNING MESSAGE DEPENDING ON NUMBER OF CHARACTERS */
const characterWarning = () => {
if (newThought.length > 140) {
return (<p className="character-warning">Your thought can only be 140 characters long</p>)
} else {
return (<p className="character-count">{newThought.length} / 140, need atleast 6 characters.</p>)
}
}
return (
<section className="form-section">
<form className="form" onSubmit={onFormSubmit}>
<label className="label" htmlFor="thought-input">
What&apos;s making you happy right now?

Choose a reason for hiding this comment

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

Good job adding the: '

<textarea
className="thought-input"
id="thought-input"
placeholder="Enter the happy thought here..."
value={newThought}
onChange={onNewThoughtChange} />
</label>
{characterWarning()}
<button
className="submit-button"
type="submit"
disabled={isSubmitButtonDisabled}>
🖤 Shoot a happy thought!
</button>
</form>
</section>)
}

export default ThoughtForm
43 changes: 43 additions & 0 deletions code/src/components/ThoughtList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable linebreak-style */
/* eslint-disable no-underscore-dangle */
import React from 'react';
import { formatDistanceToNow } from 'date-fns';

const ThoughtList = ({ loading, thoughtList, handleLike }) => {

Choose a reason for hiding this comment

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

Very clear and structured code and props. Your code is easy to follow and understand.

if (loading) {
return <h2>Loading happy thought...</h2>
}
return (
<section className="thought-section">
{thoughtList.map((thought) => {
return (
<div key={thought._id} className="single-thought">
<p>{thought.message}</p>
<div className="thought-details">
<div className="likes-wrapper">
<button
className={thought.hearts === 0 ? 'heart-button-nolikes' : 'heart-button'}
type="button"
onClick={() => handleLike(thought._id)}>
🖤
</button>
<span>x {thought.hearts}</span>
</div>
<div className="time-wrapper">
<span className="time">{formatDistanceToNow(
Comment on lines +26 to +27

Choose a reason for hiding this comment

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

Smart solution with the newDate.

new Date(thought.createdAt),
Date.now(),
{ addSuffix: true }
)}
</span>
</div>
</div>
</div>
)
})}

</section>
)
}

export default ThoughtList
Binary file added code/src/components/assets/happy-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading