From f86ee5f1062f8f1b57c45542da0bbd439418ee9d Mon Sep 17 00:00:00 2001 From: ellen Date: Sat, 6 Apr 2024 19:10:18 +0900 Subject: [PATCH 1/3] task 1 done --- client/src/pages/feed.tsx | 20 ++++++++++++++++++++ seminar/src/routes/feed.js | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/client/src/pages/feed.tsx b/client/src/pages/feed.tsx index b64c53b..ab7dc6c 100644 --- a/client/src/pages/feed.tsx +++ b/client/src/pages/feed.tsx @@ -44,6 +44,21 @@ const FeedPage = (props: {}) => { asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); } + const editPost = (id: string, editedTitle: string, editedContent: string) => { + const asyncFun = async () => { + await axios.post( SAPIBase + '/feed/editFeed', { id: id, title: editedTitle, content: editedContent } ); + const updatedPosts = LAPIResponse.map( (val) => { + if (val.id === parseInt(id)) { + val.title = editedTitle; + val.content = editedContent; + } + return val; + }); + setLAPIResponse(updatedPosts); + } + asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); + } + return (
@@ -57,6 +72,11 @@ const FeedPage = (props: {}) => {
{ LAPIResponse.map( (val, i) =>
+
{ + const editedTitle = window.prompt("Enter the new title", val.title); + const editedContent = window.prompt("Enter the new content", val.content); + if (editedTitle !== null && editedContent !== null) editPost(`${val.id}`, editedTitle, editedContent); + }}>✏️
deletePost(`${val.id}`)}>ⓧ

{ val.title }

{ val.content }

diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index f9c19d9..45733d1 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -36,6 +36,16 @@ class FeedDB { if (BItemDeleted) id--; return BItemDeleted; } + + editItem = ( id, title, content ) => { + this.#LDataDB = this.#LDataDB.map((value) => { + if (value.id === id) { + value.title = title; + value.content = content; + } + return value; + }); + } } const feedDBInst = FeedDB.getInst(); @@ -73,4 +83,14 @@ router.post('/deleteFeed', (req, res) => { } }) +router.post('/editFeed', (req, res) => { + try { + const { id, title, content } = req.body; + feedDBInst.editItem(parseInt(id), title, content); + return res.status(200).json({ isOK: true }); + } catch (e) { + return res.status(500).json({ error: e }); + } +}) + module.exports = router; \ No newline at end of file From 1306cef5c3a7ea79c5db4cd8defcca8107ed9105 Mon Sep 17 00:00:00 2001 From: ellen Date: Sat, 6 Apr 2024 19:52:05 +0900 Subject: [PATCH 2/3] task 2 done --- client/src/pages/account.tsx | 15 ++++++++++++--- seminar/.env.example | 4 +++- seminar/src/middleware/auth.js | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/client/src/pages/account.tsx b/client/src/pages/account.tsx index 37341f5..06e0176 100644 --- a/client/src/pages/account.tsx +++ b/client/src/pages/account.tsx @@ -6,13 +6,15 @@ import "./css/account.css"; const AccountPage = () => { const [ SAPIKEY, setSAPIKEY ] = React.useState(""); + const [ SID, setID ] = React.useState(""); + const [ SPASSWD, setPASSWD ] = React.useState(""); const [ NBalance, setNBalance ] = React.useState("Not Authorized"); const [ NTransaction, setNTransaction ] = React.useState(0); const getAccountInformation = () => { const asyncFun = async() => { interface IAPIResponse { balance: number }; - const { data } = await axios.post(SAPIBase + '/account/getInfo', { credential: SAPIKEY }); + const { data } = await axios.post(SAPIBase + '/account/getInfo', { id: SID, passwd: SPASSWD }); setNBalance(data.balance); } asyncFun().catch((e) => window.alert(`AN ERROR OCCURED: ${e}`)); @@ -22,7 +24,7 @@ const AccountPage = () => { const asyncFun = async() => { if (amount === '') return; interface IAPIResponse { success: boolean, balance: number, msg: string }; - const { data } = await axios.post(SAPIBase + '/account/transaction', { credential: SAPIKEY, amount: amount }); + const { data } = await axios.post(SAPIBase + '/account/transaction', {id: SID, passwd: SPASSWD, amount: amount }); setNTransaction(0); if (!data.success) { window.alert('Transaction Failed:' + data.msg); @@ -39,9 +41,16 @@ const AccountPage = () => {

Account

-
+ {/*
Enter API Key: setSAPIKEY(e.target.value)}/> +
*/} +
+ Enter User Name: setID(e.target.value)}/> +
+
+ Enter Password: setPASSWD(e.target.value)}/> +

The National Bank of SPARCS API

diff --git a/seminar/.env.example b/seminar/.env.example index f84e5b2..778725d 100644 --- a/seminar/.env.example +++ b/seminar/.env.example @@ -1,3 +1,5 @@ PORT=8080 NODE_ENV=DEVELOPMENT -API_KEY= \ No newline at end of file +API_KEY= +ID=name +PASSWD=1234 \ No newline at end of file diff --git a/seminar/src/middleware/auth.js b/seminar/src/middleware/auth.js index 480f41d..5e6f635 100644 --- a/seminar/src/middleware/auth.js +++ b/seminar/src/middleware/auth.js @@ -1,5 +1,6 @@ const authMiddleware = (req, res, next) => { - if (req.body.credential === process.env.API_KEY) { + const { id, passwd } = req.body; + if (id === process.env.ID && passwd === process.env.PASSWD) { console.log("[AUTH-MIDDLEWARE] Authorized User"); next(); } From 0e4c890c34fd2fcfb8140301710e13be3baf4849 Mon Sep 17 00:00:00 2001 From: ellen Date: Sat, 6 Apr 2024 22:31:43 +0900 Subject: [PATCH 3/3] extra feature: likes --- client/src/pages/css/feed.css | 26 ++++++++++++++++++++++++++ client/src/pages/feed.tsx | 27 ++++++++++++++++----------- seminar/src/routes/feed.js | 29 ++++++++++++++++++++++++----- 3 files changed, 66 insertions(+), 16 deletions(-) diff --git a/client/src/pages/css/feed.css b/client/src/pages/css/feed.css index 53580df..23ed893 100644 --- a/client/src/pages/css/feed.css +++ b/client/src/pages/css/feed.css @@ -6,6 +6,7 @@ } .feed-item { + position: relative; border: solid 1px rgba(0,0,0,0.2); border-radius: 15px; width: 100%; @@ -13,6 +14,31 @@ position: relative; } +.edit-item { + position: absolute; + right: 50px; + top: 12px; + color: red; + font-size: 18px; +} + +.like-button{ + position: absolute; + right: 85px; + top: 7px; + color: red; + align-items: center; + background-color: rgb(255, 131, 131); + font-size: 14px; + color:rgb(255, 255, 255); + border-radius: 15px; + border: none; + padding: 7px; + font-weight: bold; + box-shadow: 1px 1px 1px rgb(220, 220, 220); +} + + .feed-item-add { border: dotted 1px black; border-radius: 15px; diff --git a/client/src/pages/feed.tsx b/client/src/pages/feed.tsx index ab7dc6c..0bccba1 100644 --- a/client/src/pages/feed.tsx +++ b/client/src/pages/feed.tsx @@ -4,13 +4,14 @@ import { SAPIBase } from "../tools/api"; import Header from "../components/header"; import "./css/feed.css"; -interface IAPIResponse { id: number, title: string, content: string } +interface IAPIResponse { id: number, title: string, content: string, likes: number } const FeedPage = (props: {}) => { const [ LAPIResponse, setLAPIResponse ] = React.useState([]); const [ NPostCount, setNPostCount ] = React.useState(0); const [ SNewPostTitle, setSNewPostTitle ] = React.useState(""); const [ SNewPostContent, setSNewPostContent ] = React.useState(""); + const [ LikeCounts, setLikeCounts ] = React.useState(0); React.useEffect( () => { let BComponentExited = false; @@ -27,7 +28,7 @@ const FeedPage = (props: {}) => { const createNewPost = () => { const asyncFun = async () => { - await axios.post( SAPIBase + '/feed/addFeed', { title: SNewPostTitle, content: SNewPostContent } ); + await axios.post( SAPIBase + '/feed/addFeed', { title: SNewPostTitle, content: SNewPostContent, likes: 0 } ); setNPostCount(NPostCount + 1); setSNewPostTitle(""); setSNewPostContent(""); @@ -47,18 +48,21 @@ const FeedPage = (props: {}) => { const editPost = (id: string, editedTitle: string, editedContent: string) => { const asyncFun = async () => { await axios.post( SAPIBase + '/feed/editFeed', { id: id, title: editedTitle, content: editedContent } ); - const updatedPosts = LAPIResponse.map( (val) => { - if (val.id === parseInt(id)) { - val.title = editedTitle; - val.content = editedContent; - } - return val; - }); - setLAPIResponse(updatedPosts); + const { data } = await axios.get( SAPIBase + `/feed/getFeed?count=${ NPostCount }`); + setLAPIResponse(data); } asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); } + const updateLikes = (id: string, likes: number) => { + const asyncFun = async () => { + // One can set X-HTTP-Method header to DELETE to specify deletion as well + await axios.post( SAPIBase + '/feed/updateLikes', { id, likes } ); + const { data } = await axios.get( SAPIBase + `/feed/getFeed?count=${ NPostCount }`); + setLAPIResponse(data); + } + asyncFun().catch(e => window.alert(`AN ERROR OCCURED! ${e}`)); + } return (
@@ -72,14 +76,15 @@ const FeedPage = (props: {}) => {
{ LAPIResponse.map( (val, i) =>
+
deletePost(`${val.id}`)}>ⓧ
{ const editedTitle = window.prompt("Enter the new title", val.title); const editedContent = window.prompt("Enter the new content", val.content); if (editedTitle !== null && editedContent !== null) editPost(`${val.id}`, editedTitle, editedContent); }}>✏️
-
deletePost(`${val.id}`)}>ⓧ

{ val.title }

{ val.content }

+
) }
diff --git a/seminar/src/routes/feed.js b/seminar/src/routes/feed.js index 45733d1..539408a 100644 --- a/seminar/src/routes/feed.js +++ b/seminar/src/routes/feed.js @@ -9,7 +9,7 @@ class FeedDB { return FeedDB._inst_; } - #id = 1; #itemCount = 1; #LDataDB = [{ id: 0, title: "test1", content: "Example body" }]; + #id = 1; #itemCount = 1; #LDataDB = [{ id: 0, title: "test1", content: "Example body", likes: 0 }]; constructor() { console.log("[Feed-DB] DB Init Completed"); } @@ -20,8 +20,8 @@ class FeedDB { } insertItem = ( item ) => { - const { title, content } = item; - this.#LDataDB.push({ id: this.#id, title, content }); + const { title, content, likes } = item; + this.#LDataDB.push({ id: this.#id, title, content, likes }); this.#id++; this.#itemCount++; return true; } @@ -46,6 +46,15 @@ class FeedDB { return value; }); } + + updateLikes = (id , likes) => { + this.#LDataDB = this.#LDataDB.map((value) => { + if (value.id === id) { + value.likes += 1; + } + return value; + }); + } } const feedDBInst = FeedDB.getInst(); @@ -63,8 +72,8 @@ router.get('/getFeed', (req, res) => { router.post('/addFeed', (req, res) => { try { - const { title, content } = req.body; - const addResult = feedDBInst.insertItem({ title, content }); + const { title, content, likes } = req.body; + const addResult = feedDBInst.insertItem({ title, content, likes }); if (!addResult) return res.status(500).json({ error: dbRes.data }) else return res.status(200).json({ isOK: true }); } catch (e) { @@ -93,4 +102,14 @@ router.post('/editFeed', (req, res) => { } }) +router.post('/updateLikes', (req, res) => { + try { + const { id, likes } = req.body; + feedDBInst.updateLikes(parseInt(id), likes); + return res.status(200).json({ isOK: true }); + } catch (e) { + return res.status(500).json({ error: e }); + } +}) + module.exports = router; \ No newline at end of file