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
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.
A project done in React, with the purpose of displaying API:s in both GET and POST.

## 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?
I struggled a lot with this project. I had a hard time structuring the code in a way that felt logical to me. After consulting chat-GPT and viewing a few other students projects I finally found my way.
If I had more time I would find a way to align the timer better. It frustrates me that it's not properly justified to the right, the alignment shifts depending on the length of the sentence.
I would also implement a window alert. I chose not to use one now, since I didn't have time to figure out how to only show it if the user tries to submit with the wrong length, it kept showing on every keystroke from 1-4.

## 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://sunnyhappythoughts.netlify.app/
32 changes: 32 additions & 0 deletions code/package-lock.json

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

2 changes: 2 additions & 0 deletions code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
"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",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
Binary file added code/public/favicon-32.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added code/public/favicon-57.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion code/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="A more positive version of Twitter">
<meta property="og:url" content="https://sunnyhappythoughts.netlify.app">
<meta property="og:type" content="website">
<meta property="og:title" content="Sunny Happy Thoughts">
<meta property="og:description" content="A more positive version of Twitter">
<meta property="og:image" content="%PUBLIC_URL%/screenshot.png">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto&family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
<link rel="icon" type="image/x-icon" href="./favicon-32.png">
<link rel="apple-touch-icon" href="%PUBLIC_URL%/favicon-57.png"/>
<!--
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 +22,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>Sunny Happy Thoughts</title>
</head>

<body>
Expand Down
Binary file added code/public/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 64 additions & 5 deletions code/src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,68 @@
import React from 'react';
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-unused-vars */
import React, { useState, useEffect } from 'react';
import { SubmitThoughts } from 'components/SubmitThoughts';
import { ListThoughts } from 'components/ListThoughts';

export const App = () => {
const [thoughtsList, setThoughtsList] = useState([])
const [submitThoughts, setSubmitThoughts] = useState('')
const [loading, setLoading] = useState(false)

const fetchThoughts = () => {
setLoading(true)
fetch('https://project-happy-thoughts-api-l8j3.onrender.com/thoughts')
.then((response) => response.json())
.then((data) => setThoughtsList(data.response))
.catch((error) => console.log(error))
.finally(() => { setLoading(false) })
}

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

Comment on lines +21 to +24
Copy link

Choose a reason for hiding this comment

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

This hook is to call the fetchThoughts function when the component is mounted so this should/could/would also be moved if so we were to change the structure for a "cleaner" App.js

const handleThoughtChange = (event) => {
setSubmitThoughts(event.target.value)
}

const handleFormSubmit = (event) => {
event.preventDefault()
setLoading(true)

Copy link

Choose a reason for hiding this comment

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

Since the "handleFormSubmit" handles the submission of a new thought it could be moved into your component "submitThoughts.js" instead if we want to continue on "cleaning" the app.js a bit.

const options = {
method: 'POST',
body: JSON.stringify({ message: submitThoughts }),
headers: { 'Content-Type': 'application/json' }
}
fetch('https://project-happy-thoughts-api-l8j3.onrender.com/thoughts', options)
.then((response) => response.json())
.then((data) => { setThoughtsList([data.response, ...thoughtsList]) })
.catch((error) => console.log(error))
.finally(() => { setLoading(false); setSubmitThoughts('') })
}

const handleLikeChange = (thoughtId) => {
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
}
fetch(`https://project-happy-thoughts-api-l8j3.onrender.com/thoughts/${thoughtId}/like`, options)
.then((response) => response.json())
.catch((error) => console.log(error))
.finally(() => fetchThoughts(''))
}

return (
<div>
Find me in src/app.js!
</div>
<section className="mainBody">
<SubmitThoughts
submitThoughts={submitThoughts}
handleThoughtChange={handleThoughtChange}
handleFormSubmit={handleFormSubmit} />
<ListThoughts
loading={loading}
thoughtsList={thoughtsList}
handleLikeChange={handleLikeChange} />
</section>
);
}
}
36 changes: 36 additions & 0 deletions code/src/components/ListThoughts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* eslint-disable no-underscore-dangle */
import React from 'react'
import moment from 'moment'

export const ListThoughts = ({ loading, thoughtsList, handleLikeChange }) => {
if (loading) {
return <h2>Loading...</h2>
}
const getTimeAgo = (createdAt) => {
const timeAgo = moment(createdAt).fromNow();
return timeAgo;
}
return (
<section className="listSection">
{thoughtsList.map((thought) => {
return (
<div className="listBox">
<p className="thought" key={thought._id}>{thought.message}</p>
<div className="list">
<button
className={thought.hearts === 0 ? 'heartBtn' : 'likedBtn'}
type="submit"
onClick={() => handleLikeChange(thought._id)}>
💛
</button>
<p>x {thought.hearts}</p>
<div>
<p className="time">{getTimeAgo(thought.createdAt)}</p>
</div>
</div>
</div>
)
})}
</section>
Comment on lines +13 to +34
Copy link

Choose a reason for hiding this comment

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

Very nice and tidy indentation, pretty code!

)
}
34 changes: 34 additions & 0 deletions code/src/components/SubmitThoughts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* eslint-disable react/no-unescaped-entities */
import React, { useState } from 'react'

export const SubmitThoughts = ({ handleFormSubmit, submitThoughts, handleThoughtChange }) => {
const turnCounterRed = submitThoughts.length > 140 ? 'counter-red' : 'counter';
const [errorAlert, setErrorAlert] = useState('')
const handleLengthError = (event) => {
const textLength = event.target.value.length
if (textLength < 5) {
setErrorAlert('Your message needs to be at least 5 characters long. 😊')
} else if (textLength > 140) {
setErrorAlert('Whoa Nelly! Save the essay for your portfolio. 😄')
Copy link

Choose a reason for hiding this comment

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

I wish I tried writing a message that was to long, fuunny! 😂

} else {
setErrorAlert('')
}
handleThoughtChange(event)
}
return (
<section className="submitBox">
<h1>What's making you happy right now?</h1>
<form onSubmit={handleFormSubmit}>
<textarea type="text" value={submitThoughts} onChange={handleLengthError} />
<div>
<p className={turnCounterRed}>{submitThoughts.length} / 140</p>
</div>
<div className="errorAlert">{errorAlert}</div>
<button
type="submit">
💛 Send happy thought 💛
</button>
</form>
</section>
)
}
Loading