diff --git a/README.md b/README.md index 9ea4e26b3..13c18f6be 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ # 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. +My own version of Twitter. Consists of a main form with an input, and below the answers in the form are shown. +Happy, pastel lights colors were used to build the web. ## 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? +- My third project using React and building different components. Playing around with importing and exporting, writng a clear and easy to follow code using this Java Script library. +- Second project with the State Hook and the first with the Effect Hook. +- Fatching data with a public API (this API was shared with other students for the sue of their project). +- User can write their own happy thoughts and like some of the already published: when the user clicks the heart button on a thought, it sends a POST request (with no body) to the API URL, and the icon changes the color. ## 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://flourishing-creponne-c72c1d.netlify.app/ diff --git a/code/package-lock.json b/code/package-lock.json index f7e97e1e9..fab8e56d2 100644 --- a/code/package-lock.json +++ b/code/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "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", @@ -6205,6 +6206,18 @@ "node": ">=10" } }, + "node_modules/date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -21996,6 +22009,11 @@ "whatwg-url": "^8.0.0" } }, + "date-fns": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", + "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/code/package.json b/code/package.json index 68869f589..4cbbdb2d2 100644 --- a/code/package.json +++ b/code/package.json @@ -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", diff --git a/code/public/index.html b/code/public/index.html index e6730aa66..5d2442dad 100644 --- a/code/public/index.html +++ b/code/public/index.html @@ -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`. --> - Technigo React App + 🐢🌈 Happy Thoughts diff --git a/code/src/App.js b/code/src/App.js index f2007d229..c7fabaf3d 100644 --- a/code/src/App.js +++ b/code/src/App.js @@ -1,9 +1,102 @@ -import React from 'react'; +/* eslint no-underscore-dangle: 0 */ +import React, { useState, useEffect } from 'react'; +import ThoughtList from 'components/ThoughtList'; +import MainForm from 'components/MainForm'; +import Header from 'components/Header'; +import Footer from 'components/Footer'; export const App = () => { + const [thoughtList, setThoughtList] = useState([]); + const [loading, setLoading] = useState(false); + const [newThought, setNewThought] = useState(''); + + const fetchThoughts = () => { + setLoading(true); + fetch('https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts') + .then((res) => { + return res.json(); + }) + .then((data) => { + setThoughtList(data); + }) + .catch((error) => console.error(error)) + .finally(() => setLoading(false)); + } + + useEffect(() => { + fetchThoughts(); + }, []); + + /* eslint-disable no-unused-vars */ + const handleNewThoughtChange = (event) => { + setNewThought(event.target.value); + } + + const handleFormCleanup = () => { + setNewThought(''); + setLoading(false); + } + + const onFormSubmit = (event) => { + event.preventDefault(); + + 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(() => fetchThoughts()) + .finally(() => handleFormCleanup()); + } + + const handleLikes = (_id) => { + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + } + + fetch(`https://happy-thoughts-ux7hkzgmwa-uc.a.run.app/thoughts/${_id}/like`, options) + .then((res) => { + return res.json(); + }) + .then((data) => { + const updatedThoughtList = thoughtList.map((thought) => { + if (thought._id === data._id) { + return { + ...thought, + hearts: data.hearts + }; + } + return thought; + }); + setThoughtList(updatedThoughtList); + }) + .catch((error) => console.error(error)); + } + return ( -
- Find me in src/app.js! +
+
+
+ + +
+
); -} +} \ No newline at end of file diff --git a/code/src/assets/cat.png b/code/src/assets/cat.png new file mode 100644 index 000000000..a3b2eaed7 Binary files /dev/null and b/code/src/assets/cat.png differ diff --git a/code/src/assets/dog.png b/code/src/assets/dog.png new file mode 100644 index 000000000..ad7c841c3 Binary files /dev/null and b/code/src/assets/dog.png differ diff --git a/code/src/assets/githubb.png b/code/src/assets/githubb.png new file mode 100644 index 000000000..899f608c1 Binary files /dev/null and b/code/src/assets/githubb.png differ diff --git a/code/src/assets/nj.png b/code/src/assets/nj.png new file mode 100644 index 000000000..9c986dc2b Binary files /dev/null and b/code/src/assets/nj.png differ diff --git a/code/src/assets/sun.jpg b/code/src/assets/sun.jpg new file mode 100644 index 000000000..c93665b04 Binary files /dev/null and b/code/src/assets/sun.jpg differ diff --git a/code/src/assets/woman.png b/code/src/assets/woman.png new file mode 100644 index 000000000..b401db5a1 Binary files /dev/null and b/code/src/assets/woman.png differ diff --git a/code/src/components/Footer.js b/code/src/components/Footer.js new file mode 100644 index 000000000..dc7e31222 --- /dev/null +++ b/code/src/components/Footer.js @@ -0,0 +1,18 @@ +import React from 'react'; +import GitIcon from '../assets/githubb.png'; + +const Footer = () => { + return ( + + ) +} + +export default Footer \ No newline at end of file diff --git a/code/src/components/Header.js b/code/src/components/Header.js new file mode 100644 index 000000000..6e054e24d --- /dev/null +++ b/code/src/components/Header.js @@ -0,0 +1,18 @@ +import React from 'react'; +import Picture from '../assets/dog.png'; + +const Header = () => { + return ( +
+
+ Happy Dog +
+
+ + ); +} + +export default Header; \ No newline at end of file diff --git a/code/src/components/MainForm.js b/code/src/components/MainForm.js new file mode 100644 index 000000000..38f3d295b --- /dev/null +++ b/code/src/components/MainForm.js @@ -0,0 +1,56 @@ +/* eslint-disable max-len */ +/* eslint-disable jsx-a11y/label-has-associated-control */ +import React, { useState } from 'react'; + +const MainForm = ({ newThought, setNewThought, onFormSubmit }) => { + const [charCount, setCharCount] = useState(0); + + const handleNewThoughtChange = (event) => { + const inputText = event.target.value; + setNewThought(inputText); + setCharCount(inputText.length); + }; + + const isOverLimit = charCount > 140; + + const resetCharCount = () => { + setCharCount(0); + }; + + return ( +
{ + event.preventDefault(); + onFormSubmit(event); + resetCharCount(); // Reset the character count after submitting the form + }} + // The h2 element has an aria-hidden prop set to true. + // This is used to hide the heading from screen readers, since the heading + // text is already included in the label. + // The label element also has a class name of sr-only. + // This is a utility class that is used to visually hide the label while still making it available to screen readers. + aria-label="Happy Thoughts Form"> + + +