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

Happy thoughts Josefin R #438

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2765602
Made component that fetches API
JosefinRobertsson Mar 22, 2023
5791e35
all needed for blue level except styling
JosefinRobertsson Mar 24, 2023
b6045c6
Styling, charcounter, timestamp
JosefinRobertsson Mar 25, 2023
ad252dd
esLint disabled to fix deployment issues
JosefinRobertsson Mar 25, 2023
69f37e2
Update README.md
JosefinRobertsson Mar 29, 2023
3458694
added linebreak and updated timestamp
JosefinRobertsson Mar 29, 2023
8c0e7b0
Merge branch 'master' of https://github.com/JosefinRobertsson/project…
JosefinRobertsson Mar 29, 2023
63b0cd4
changed title
JosefinRobertsson Mar 29, 2023
a7fbf8d
Update README.md
JosefinRobertsson Mar 29, 2023
d6277d5
fixed responsiveness
JosefinRobertsson Mar 30, 2023
2fdcbe1
Merge branch 'master' of https://github.com/JosefinRobertsson/project…
JosefinRobertsson Mar 30, 2023
e914e8f
fixed duplicate function
JosefinRobertsson Mar 30, 2023
6ca7209
added min char disable and red text color
JosefinRobertsson Apr 1, 2023
057a452
updated urls
JosefinRobertsson May 22, 2023
a7ae584
testing timestamp solution
JosefinRobertsson May 22, 2023
cd55192
changing back to prev solution
JosefinRobertsson May 22, 2023
df3e9f0
testing library 'moment' to solve time delay issue
JosefinRobertsson May 22, 2023
f9c2cb9
DataList rewrite and removed loading from input
JosefinRobertsson May 23, 2023
e7186ed
trying to fix vague error
JosefinRobertsson May 23, 2023
e3e14e7
seems the error was from earlier remove of loading
JosefinRobertsson May 23, 2023
6d19ee8
moved single into Datalist return, added .response
JosefinRobertsson May 23, 2023
54ac6a8
everything working on localhost
JosefinRobertsson May 23, 2023
9b397f0
reinstalled moment, npm run build successful
JosefinRobertsson May 23, 2023
1f71e67
changed timestamp handling, dlt redundant comp
JosefinRobertsson May 24, 2023
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# 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 cute little project where you post happy thoughts and like other peoples' happy thoughts and everyone gets happy vibes

## 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?
Create fetches to both post to and get data from the API. Create like button. Follow styling requests

## 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://mellow-duckanoo-8fdcc7.netlify.app/
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>Post happy thoughts!</title>
</head>

<body>
Expand Down
32 changes: 26 additions & 6 deletions code/src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
import React from 'react';
import React, { useState } from 'react';
import DataList from 'components/DataList';
import InputForm from 'components/InputForm';

export const App = () => {
const [happyThoughtsList, setHappyThoughtsList] = useState([]);
const [loading, setLoading] = useState(false);
const [newThought, setNewThought] = useState('');
const [charCount, setCharCount] = useState(140);

return (
<div>
Find me in src/app.js!
</div>
);
}
<>
<InputForm
loading={loading}
setLoading={setLoading}
newThought={newThought}
setNewThought={setNewThought}
setHappyThoughtsList={setHappyThoughtsList}
happyThoughtsList={happyThoughtsList}
charCount={charCount}
setCharCount={setCharCount} />
<DataList
loading={loading}
setLoading={setLoading}
happyThoughtsList={happyThoughtsList}
setHappyThoughtsList={setHappyThoughtsList} />
</>
)
};
56 changes: 56 additions & 0 deletions code/src/components/DataList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import SingleThought from './SingleThought';

const DataList = ({ loading, setLoading, happyThoughtsList, setHappyThoughtsList }) => {
const updateList = (thought) => {
setLoading(true)
const options = {
method: 'POST'
};

console.log('options', options);
// eslint-disable-next-line no-underscore-dangle
fetch(`https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts/${thought._id}/like`, options)
.then((response) => response.json())
.then((updatedThought) => {
console.log(updatedThought);

// create a new array with the updated thought
const updatedThoughtsList = happyThoughtsList.map((thoughtItem) => {
// eslint-disable-next-line no-underscore-dangle
if (thoughtItem._id === updatedThought._id) {
return updatedThought;
}
return thoughtItem;
});

if (loading) {
return (<h2>loading in process...</h2>);
}

// set the updated thoughts list
setHappyThoughtsList(updatedThoughtsList);
})
.catch((error) => console.log(error))
.finally(() => {
setLoading(false);
console.log('heart count increased')
});
};

const heartCountClick = (thought) => {
console.log('like-click')
updateList(thought);
};

return (
<div className="listItems">
{happyThoughtsList.map((thought) => (
// eslint-disable-next-line no-underscore-dangle
<SingleThought key={thought._id} thought={thought} onHeartClick={heartCountClick} />
))}
</div>
)
};

export default DataList;
87 changes: 87 additions & 0 deletions code/src/components/InputForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { useEffect } from 'react';

const InputForm = ({
loading,
setLoading,
newThought,
setNewThought,
setHappyThoughtsList,
happyThoughtsList,
charCount,
setCharCount
}) => {
const updateThoughtsList = () => {
setLoading(true);

fetch('https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts')
.then((response) => response.json())
.then((data) => setHappyThoughtsList(data))
.catch((error) => console.log(error))
.finally(() => {
console.log('it worked');
setLoading(false);
console.log('loading-Get');
console.log(happyThoughtsList);
});
};

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

console.log('options', options);
fetch('https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts', options)
.then((response) => response.json())
.then((data) => {
setHappyThoughtsList([data, ...happyThoughtsList]);
console.log(data);
})
.catch((error) => console.log(error))
.finally(() => {
setLoading(false);
console.log(happyThoughtsList)
setNewThought(''); // clear textarea
setCharCount(140);
});
};

useEffect(() => {
updateThoughtsList();
// eslint-disable-next-line react-hooks/exhaustive-deps

Choose a reason for hiding this comment

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

Is there a reason why you didn't use eslint-disable in the whole file? Makes it easier (in my own opinion) to remove if necessary in the top level of the file.

}, []);

const handleInputChange = (event) => {
const { value } = event.target;
setNewThought(value);
setCharCount(140 - value.length); // update character count
};

if (loading) {
return (<h2>loading in process...</h2>);
}

return (
<div className="inputForm">
<form onSubmit={handleFormSubmit}>
<h3>What&apos;s making you happy right now?</h3>

Choose a reason for hiding this comment

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

&apos
Nice use off Predefined Character Entities (had to look up that name😅 )

<textarea
value={newThought}
onChange={handleInputChange}
maxLength="140" />
<div id="counter">140/{charCount}</div>
<button type="submit"><span id="heart"> Send Happy Thought&nbsp;</span></button>

Choose a reason for hiding this comment

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

You might want to add a feature that disables the send button if a value (<= 5) is entered in the text box;, to prevent a error message from the API, that gets rendered out in the DataList component.

</form>
</div>
);
};

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

let timeStamp;

const SingleThought = ({ thought, onHeartClick }) => {
const date = new Date(thought.createdAt);
const timeDiff = Math.round((new Date() - date) / (1000 * 60));
if (timeDiff < 1) {
timeStamp = 'just now';
} else if (timeDiff < 90) {
timeStamp = `${timeDiff} min ago`;
} else {
const hoursDiff = Math.round(timeDiff / 60);
timeStamp = `${hoursDiff} hour${hoursDiff > 1 ? 's' : ''} ago`;
}

Choose a reason for hiding this comment

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

A very nice structured function; Its easy to understand.

console.log('singlelistitem')
return (
<div className="singleListItem">
<h3 id="stretched">{thought.message}</h3>
<div className="buttonTimestampBox">
<div className="heartCounter"><button onClick={() => onHeartClick(thought)} type="button"><span id="heartButton">🧡</span></button>
<span> x {thought.hearts}</span>
</div>
<p className="timeStamp">{timeStamp}</p>
</div>
</div>
);
};

export default SingleThought;
115 changes: 114 additions & 1 deletion code/src/index.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
body {
margin: 0;
margin-left: auto;
margin-right: auto;
margin-top: 4em;
max-width: 600px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
Expand All @@ -11,3 +14,113 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

.listItems {
display: flex;
flex-direction: column;
gap: 2em;
word-wrap: break-word;
}

.singleListItem,
.inputForm {
display: block;
border: 1px solid black;
box-shadow: 10px 10px 0 0 black;
}

.inputForm {
background-color: rgb(233, 233, 232);
margin-bottom: 2em;
}

h3 {
display: block;
margin-left: 5%;
margin-right: 5%;
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}

textarea {
margin-left: 2em;
margin-right: 1em;
width: calc(95% - 3em);
height: 4em;
caret-color: rgb(197, 62, 57);
}

button {
margin-left: 5%;
margin-top: 1em;
margin-bottom: 1.5em;
width: 45%;
padding: 10px 10px 10px 10px;
border-radius: 20px;
border: none;
background-color: rgb(252, 166, 163);
font-weight: bold;
font-size: medium;
cursor: pointer;
}

button:active {
background-color: white;
border: 1px solid red;
}

button:active #heartButton {
filter:contrast(50%);
}

.noWrapButton {
white-space:nowrap;
}

#heart::before,
#heart::after {
content: '🧡';
}

.buttonTimestampBox button {
width: 3em;
height: 3em;
border-radius: 50%;
margin-bottom: 16px;
}

#stretched {
font-size: 1.2em;
transform: scaleY(1.2);
}

#counter {
margin-left: 5%;
}

.buttonTimestampBox {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-left: 1em;
margin-right: 2em;
}

.heartCounter {
white-space: nowrap;
align-self: flex-end;
}

.timeStamp {
display: inline-block;
align-self: center;
}

@media screen and (max-width: 667px) {
.inputForm,
.listItems {
margin-left: 1em;
margin-right: 2em;
}
}