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

Project Happy Thoughts by Emma Engvall #445

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

Replace this readme with your own information about your project.
This week our assignment was to practice React state skills by fetching and posting data to an API.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
The following criteria should be met:
✓ Your page should follow the design as closely as possible
✓ You should list the most recent thoughts at the top and older thoughts at the bottom (sorted)
✓ Your thoughts should show the content of the message and how many likes they've received
✓ You should have a form to post new thoughts
✓ You should implement the heart button to send likes on a thought

## The problem
What I learned from this week's project is that you cannot plan enough. I overcomplicated things and had to spend quite some time just going back and forth and then cleaning up the code.

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?

## View it live
https://happy-thoughts-project-emma-engvall.netlify.app/

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.
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
5 changes: 4 additions & 1 deletion code/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta property="og:title" content="The Happy Thoughts Project"/>
<meta property="og:description" content="The Happy Thoughts Project is a site where you can share your happiest of thoughts with the community around you. It is an app built for the Technigo Front-end developer bootcamp in the spring 2023. The app has been built by Emma Engvall."/>
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap" rel="stylesheet"/>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Expand All @@ -13,7 +16,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>Project Happy Thoughts ❤️ by Emma Engvall</title>
</head>

<body>
Expand Down
86 changes: 83 additions & 3 deletions code/src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,89 @@
import React from 'react';
/* eslint-disable */
import React, { useState, useEffect } from 'react';
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('');

//Fetching the latest 20 thoughts from the API
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();
}, [])

const handleNewThoughtChange = (event) => {
setNewThought(event.target.value)
}

//Posting a new thought to the API

Choose a reason for hiding this comment

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

very good comment

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('')
};

//Handle likes from users when the heart icon has been clicked. The number of likes will be increased by one every time the heart is clicked.
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!
<main>
<ThoughtForm
newThought={newThought}
onNewThoughtChange={handleNewThoughtChange}
onFormSubmit={handleFormSubmit}
/>
<ThoughtList
loading={loading}
thoughtList={thoughtList}
handleLike={handleLike}
/>
</main>
</div>
);
}
}
40 changes: 40 additions & 0 deletions code/src/components/ThoughtForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* eslint-disable */
import React from 'react';

export const ThoughtForm = ({ newThought, onNewThoughtChange, onFormSubmit }) => {

//The submit button is disabled if the message contains less than six characters or more than 140 characters.
const isSubmitButtonDisabled = newThought.length < 6 || newThought.length > 140;
const characterWarning = () => {
if (newThought.length > 140 ) {
return (
<p className="character-warning">You are trying to send too much love.</p>)

Choose a reason for hiding this comment

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

Haha too much love is apparently a thing-in this app, atleast

} else {
return (<p className="character-count">{newThought.length} / 140</p>)
}
}
return (
<section className="form-section">
<form classname="form" onSubmit={onFormSubmit}>
<label className="label" htmlFor="new-thought">
<h2>What is making you happy right now? ❤️</h2>
<textarea
className="new-thought"
id="new-thought"
placeholder="Share your happy thought here..."
rows="4" //maximum of four rows per message
cols="40" //maximum of 40 characters per row.
value={newThought}
onChange={onNewThoughtChange} />
</label>
{characterWarning()}
<button
className="submit-button"
type="submit"
disabled={isSubmitButtonDisabled}>
❤️ Send Happy Thought ❤️
</button>
</form>
</section>
)
}
41 changes: 41 additions & 0 deletions code/src/components/ThoughtList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable */
import React from 'react';
import { formatDistanceToNow } from 'date-fns';


export const ThoughtList = ({ loading, thoughtList, handleLike }) => {
if (loading) {
return <h1>Loading Happy Thoughts 💗</h1>
}

return (
<section className="thought-section">
{thoughtList.map((thought) => {
return (
<div key={thought._id} className="single-thought">
<h4>{thought.message}</h4>
<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( //shows how long it has been since a message was posted
new Date (thought.createdAt),
Date.now(),
{ addSuffix: true }
)}
&nbsp;ago
</span>
</div>
</div>
</div>
)})}
</section>
);
}
99 changes: 95 additions & 4 deletions code/src/index.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,104 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
margin: 0;
font-family: Roboto Mono;
background-color: white;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: flex;
flex-direction: column;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

main {
min-width: 335px;
max-width: 500px;
margin: 1.5rem auto 1rem auto;
}

.form-section {
background-color: #f2f2f2;
max-width: 500px;
min-width: 335px;
border: 1.6px solid;
border-radius: 2px;
box-shadow: 8px 8px;
padding: 1.2rem;
margin: 1rem;
margin-bottom: 2rem;
}

h2 {
font-family: monospace;
font-weight: 400;
font-size: 18px;
}

h4 {
font-weight: 400;
}

.single-thought {
background-color: white;
max-width: 500px;
min-width: 335px;
border: 1.6px solid;
border-radius: 2px;
box-shadow: 8px 8px;
margin: 1.5rem 1rem 1rem 1rem;
padding: 1.2rem;
overflow-wrap: break-word
}

.submit-button {
background-color: pink;
border-radius: 20px;
font-family: monospace;
padding: 8px 10px;
border: none;
cursor: pointer;
color: black;
font-weight: 600;
font-size: 16px;
}

.submit-button:hover {
background-color: #d5c0ff;
}

.character-count {
color: rgb(104, 103, 103);
font-size: 14px;
margin-top: 2px;
}

.thought-details {
display: flex;
justify-content: space-between;
}

.heart-button,
.heart-button-nolikes {
border-radius: 100%;
border: none;
padding: 0.8rem;
margin-right: 0.6rem;
cursor: pointer;
}

.heart-button,
.heart-button-nolikes:hover {
background-color: pink;
}

.time {
color: rgb(168, 167, 167);
}

.thought-section {
margin-top: 2rem;
}

6 changes: 6 additions & 0 deletions package-lock.json

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