diff --git a/README.md b/README.md index b1e1070..027f00b 100644 --- a/README.md +++ b/README.md @@ -76,3 +76,6 @@ Direct Message Feature ###### upstream/main ###### main + + +test test test \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index dd8f851..64aed64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,10 +1,11 @@ { - "name": "react-auth-boilerplate", + "name": "team-project-frontend", "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { + "name": "team-project-frontend", "version": "0.1.0", "dependencies": { "@testing-library/jest-dom": "^5.16.1", @@ -13,6 +14,7 @@ "axios": "^0.24.0", "bootstrap": "^5.1.3", "dotenv": "^8.2.0", + "express": "^4.18.2", "react": "^17.0.2", "react-bootstrap": "^2.0.3", "react-dom": "^17.0.2", @@ -4384,6 +4386,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-html": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", @@ -19720,9 +19733,11 @@ } }, "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "optional": true, + "peer": true, "engines": { "node": ">=10" }, @@ -25301,6 +25316,13 @@ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "requires": { "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + } } }, "ansi-html": { @@ -37297,9 +37319,11 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "optional": true, + "peer": true }, "type-is": { "version": "1.6.18", diff --git a/package.json b/package.json index ed3e22e..96502d8 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "axios": "^0.24.0", "bootstrap": "^5.1.3", "dotenv": "^8.2.0", + "express": "^4.18.2", "react": "^17.0.2", "react-bootstrap": "^2.0.3", "react-dom": "^17.0.2", @@ -19,7 +20,7 @@ "web-vitals": "^1.1.2" }, "scripts": { - "start": "react-scripts start", + "start": "react-scripts --openssl-legacy-provider start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" diff --git a/src/App.js b/src/App.js index c7583d8..8197ef5 100644 --- a/src/App.js +++ b/src/App.js @@ -12,6 +12,9 @@ import SignUp from './components/auth/SignUp' import SignIn from './components/auth/SignIn' import SignOut from './components/auth/SignOut' import ChangePassword from './components/auth/ChangePassword' +import Comments from './components/comments/comments' + + const App = () => { @@ -41,46 +44,56 @@ const App = () => { } return ( - -
- - } /> - } - /> - } - /> - - - - } - /> - - - } - /> - - {msgAlerts.map((msgAlert) => ( - + + +
+ + } /> + } + /> + } + /> + + + + } + /> + + + } + /> + + {msgAlerts.map((msgAlert) => ( + - ))} - + /> + ))} + + + + + ) -} + } export default App diff --git a/src/api/auth.js b/src/api/auth.js index 5a8c629..52bc72e 100644 --- a/src/api/auth.js +++ b/src/api/auth.js @@ -1,6 +1,8 @@ import apiUrl from '../apiConfig' import axios from 'axios' + + export const signUp = (credentials) => { return axios({ method: 'POST', @@ -53,3 +55,59 @@ export const changePassword = (passwords, user) => { }, }) } + + + +export const getComments = async (user) => { + return axios({ + url: apiUrl + '/comments', + method: 'GET', + headers: { + Authorization: `Token token=${user.token}`, + }, + }) + } + + export const createComment = async (text, parentId, user) => { + console.log("hello world", user) + + return axios({ + url: apiUrl + '/comments/' + user._id, + method: 'POST', + headers: { + Authorization: `Token token=${user.token}`, + }, + data: { + comments: { + body: text, + parentId: parentId, + }, + }, + }) + } + + export const updateComment = async (text, id, user) => { + return axios({ + url: apiUrl + '/comments/' + id, + method: 'PATCH', + headers: { + Authorization: `Token token=${user.token}`, + }, + data: { + comments: { + body: text, + }, + }, + }) + } + + export const deleteComment = async (id, user) => { + return axios({ + url: apiUrl + '/comments/' + id, + method: 'DELETE', + headers: { + Authorization: `Token token=${user.token}`, + }, + }) + } + \ No newline at end of file diff --git a/src/components/Home.js b/src/components/Home.js index d90311e..acb4e9a 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -3,10 +3,11 @@ const Home = (props) => { console.log('props in home', props) return ( - <> -

Home Page

- +
+

Home

+
) } export default Home + \ No newline at end of file diff --git a/src/components/auth/SignUp.js b/src/components/auth/SignUp.js index a97d4d0..c57bcb8 100644 --- a/src/components/auth/SignUp.js +++ b/src/components/auth/SignUp.js @@ -8,6 +8,7 @@ import messages from '../shared/AutoDismissAlert/messages' import Form from 'react-bootstrap/Form' import Button from 'react-bootstrap/Button' + const SignUp = (props) => { // constructor(props) { // super(props) diff --git a/src/components/comments/comment.js b/src/components/comments/comment.js new file mode 100644 index 0000000..cc3de79 --- /dev/null +++ b/src/components/comments/comment.js @@ -0,0 +1,116 @@ +import { useEffect } from "react"; +import CommentForm from "./commentForm" + +const Comment = ({ + comment, + replies, + setActiveComment, + activeComment, + updateComment, + deleteComment, + addComment, + parentId = null, + currentUserId, +}) => { + const isEditing = + activeComment && + activeComment.id === comment.id && + activeComment.type === "editing" + const isReplying = + activeComment && + activeComment.id === comment.id && + activeComment.type === "replying" + const fiveMinutes = 300000 + const timePassed = new Date() - new Date(comment.createdAt) > fiveMinutes + const canDelete = + currentUserId === comment.userId && replies.length === 0 && !timePassed + const canReply = Boolean(currentUserId) + const canEdit = currentUserId === comment.userId && !timePassed + const replyId = parentId ? parentId : comment.id + useEffect (() => { + }, ) + console.log("hello" + replyId) + const createdAt = new Date(comment.createdAt).toLocaleDateString() + return ( +
+
+ +
+
+
+
{comment.username}
+
{createdAt}
+
+ {!isEditing &&
{comment.body}
} + {isEditing && ( + updateComment(text, comment.id)} + handleCancel={() => { + setActiveComment(null) + }} + /> + )} +
+ {canReply && ( +
+ setActiveComment({ id: comment.id, type: "replying" }) + } + > + Reply +
+ )} + {canEdit && ( +
+ setActiveComment({ id: comment.id, type: "editing" }) + } + > + Edit +
+ )} + {canDelete && ( +
deleteComment(comment.id)} + > + Delete +
+ )} +
+ {isReplying && ( + addComment(text, replyId)} + /> + )} + {replies.length > 0 && ( +
+ {replies.map((reply) => ( + + ))} +
+ )} +
+
+ ); +}; + +export default Comment + diff --git a/src/components/comments/commentForm.js b/src/components/comments/commentForm.js new file mode 100644 index 0000000..1ba48b8 --- /dev/null +++ b/src/components/comments/commentForm.js @@ -0,0 +1,41 @@ +import { useState } from "react" + +const CommentForm = ({ + handleSubmit, + submitLabel, + hasCancelButton = false, + handleCancel, + initialText = "", +}) => { + const [text, setText] = useState(initialText) + const isTextareaDisabled = text.length === 0 + const onSubmit = (event) => { + console.log(event) + event.preventDefault() + handleSubmit(text, ) + setText("") + }; + return ( +
+