diff --git a/Blogs/istockphoto-1147785920-612x612.jpg b/Blogs/istockphoto-1147785920-612x612.jpg new file mode 100644 index 0000000..5733833 Binary files /dev/null and b/Blogs/istockphoto-1147785920-612x612.jpg differ diff --git a/Blogs/istockphoto-1156304531-612x612.jpg b/Blogs/istockphoto-1156304531-612x612.jpg new file mode 100644 index 0000000..b8fa3a5 Binary files /dev/null and b/Blogs/istockphoto-1156304531-612x612.jpg differ diff --git a/Blogs/istockphoto-1164102275-612x612.jpg b/Blogs/istockphoto-1164102275-612x612.jpg new file mode 100644 index 0000000..5abdbfa Binary files /dev/null and b/Blogs/istockphoto-1164102275-612x612.jpg differ diff --git a/Blogs/istockphoto-1168019993-612x612.jpg b/Blogs/istockphoto-1168019993-612x612.jpg new file mode 100644 index 0000000..cf6cea8 Binary files /dev/null and b/Blogs/istockphoto-1168019993-612x612.jpg differ diff --git a/Blogs/istockphoto-1198931639-612x612.jpg b/Blogs/istockphoto-1198931639-612x612.jpg new file mode 100644 index 0000000..59fc247 Binary files /dev/null and b/Blogs/istockphoto-1198931639-612x612.jpg differ diff --git a/Blogs/istockphoto-1241341642-612x612.jpg b/Blogs/istockphoto-1241341642-612x612.jpg new file mode 100644 index 0000000..8832442 Binary files /dev/null and b/Blogs/istockphoto-1241341642-612x612.jpg differ diff --git a/Blogs/istockphoto-1241881284-612x612.jpg b/Blogs/istockphoto-1241881284-612x612.jpg new file mode 100644 index 0000000..e8d6456 Binary files /dev/null and b/Blogs/istockphoto-1241881284-612x612.jpg differ diff --git a/Blogs/istockphoto-1252684502-612x612.jpg b/Blogs/istockphoto-1252684502-612x612.jpg new file mode 100644 index 0000000..9976985 Binary files /dev/null and b/Blogs/istockphoto-1252684502-612x612.jpg differ diff --git a/Blogs/istockphoto-1302647935-612x612.jpg b/Blogs/istockphoto-1302647935-612x612.jpg new file mode 100644 index 0000000..5f5baa4 Binary files /dev/null and b/Blogs/istockphoto-1302647935-612x612.jpg differ diff --git a/Blogs/istockphoto-1345541245-612x612.jpg b/Blogs/istockphoto-1345541245-612x612.jpg new file mode 100644 index 0000000..f1edee8 Binary files /dev/null and b/Blogs/istockphoto-1345541245-612x612.jpg differ diff --git a/Blogs/istockphoto-1408387701-612x612.jpg b/Blogs/istockphoto-1408387701-612x612.jpg new file mode 100644 index 0000000..d07e961 Binary files /dev/null and b/Blogs/istockphoto-1408387701-612x612.jpg differ diff --git a/Blogs/istockphoto-655931794-612x612.jpg b/Blogs/istockphoto-655931794-612x612.jpg new file mode 100644 index 0000000..e1c8aee Binary files /dev/null and b/Blogs/istockphoto-655931794-612x612.jpg differ diff --git a/Blogs/istockphoto-860887528-612x612.jpg b/Blogs/istockphoto-860887528-612x612.jpg new file mode 100644 index 0000000..e50aa5d Binary files /dev/null and b/Blogs/istockphoto-860887528-612x612.jpg differ diff --git a/Blogs/istockphoto-876014518-612x612.jpg b/Blogs/istockphoto-876014518-612x612.jpg new file mode 100644 index 0000000..8bcd0cd Binary files /dev/null and b/Blogs/istockphoto-876014518-612x612.jpg differ diff --git a/backend/app.js b/backend/app.js index 6aa348b..912e95a 100644 --- a/backend/app.js +++ b/backend/app.js @@ -1,16 +1,37 @@ const express = require("express"); const mongoose = require("mongoose"); -const dotenv = require("dotenv"); +const dotenv = require("dotenv"); const cors = require("cors"); const app = express(); -const User = require("./model/User"); const UserRoutes = require("./routes/UserRoutes"); const BlogRoutes = require("./routes/BlogRoutes") - +const multer = require("multer"); +const path = require("path"); +const User = require('./model/User') +const Blog = require('./model/Blogs') +const BlogsController = require('./contollers/BlogsController') dotenv.config(); app.use(cors()); app.use(express.json()) +app.use(express.static('public')); app.use("/api/user", UserRoutes); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, "public/images"); + }, + filename: (req, file, cb) => { + const uniqueSuffix = + Date.now() + + "-" + + Math.round(Math.random() * 1e9) + + path.extname(file.originalname); + cb(null, file.fieldname + uniqueSuffix); + }, +}); +const upload = multer({ storage: storage }); + +app.post("/api/blog/create",upload.single('file'), BlogsController.createBlog); app.use("/api/blog", BlogRoutes); mongoose diff --git a/backend/contollers/BlogsController.js b/backend/contollers/BlogsController.js index aa1c3ce..de538d7 100644 --- a/backend/contollers/BlogsController.js +++ b/backend/contollers/BlogsController.js @@ -38,6 +38,8 @@ const getBlogById = async(req, res) => { } const createBlog = async (req, res) => { + + const image = req.file.filename; const { title, content, creator, author, date } = req.body; try { @@ -46,7 +48,7 @@ const createBlog = async (req, res) => { return res.status(404).json({ message: "User not found" }); } - const newBlog = new Blog({ title, content, creator , author, date}); + const newBlog = new Blog({ title, content, creator , author, date, image}); await newBlog.save(); user.blogs.push(newBlog); diff --git a/backend/model/Blogs.js b/backend/model/Blogs.js index 2d68728..dac2390 100644 --- a/backend/model/Blogs.js +++ b/backend/model/Blogs.js @@ -8,7 +8,7 @@ const isoDate = currentDate.toISOString().split('T')[0]; const BlogSchema = new mongoose.Schema({ title : {type : String, required : true}, content : {type : String, required : true}, - image : {type : String}, + image : {type : String, required : true}, creator : {type : mongoose.Types.ObjectId, required : true, ref : 'User'}, author : {type : String}, date : {type : String} diff --git a/backend/package-lock.json b/backend/package-lock.json index b3a7bbf..cf09f40 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -13,6 +13,7 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "mongoose": "^8.3.1", + "multer": "^1.4.5-lts.1", "uuid": "^9.0.1" }, "devDependencies": { @@ -71,6 +72,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -147,6 +153,22 @@ "node": ">=16.20.1" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -203,6 +225,20 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -235,6 +271,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -633,6 +674,11 @@ "node": ">=0.12.0" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/kareem": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", @@ -721,6 +767,25 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/mongodb": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", @@ -846,6 +911,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -981,6 +1063,11 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1043,6 +1130,25 @@ "node": ">= 0.8" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1207,6 +1313,27 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1274,6 +1401,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -1288,6 +1420,11 @@ "node": ">= 0.8" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -1336,6 +1473,14 @@ "node": ">=16" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/backend/package.json b/backend/package.json index c6af64b..17b3939 100644 --- a/backend/package.json +++ b/backend/package.json @@ -14,6 +14,7 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "mongoose": "^8.3.1", + "multer": "^1.4.5-lts.1", "uuid": "^9.0.1" }, "devDependencies": { diff --git a/backend/public/images/file1713098617694-742881532.png b/backend/public/images/file1713098617694-742881532.png new file mode 100644 index 0000000..2a7ae3e Binary files /dev/null and b/backend/public/images/file1713098617694-742881532.png differ diff --git a/backend/public/images/file1713098648907-711314914.png b/backend/public/images/file1713098648907-711314914.png new file mode 100644 index 0000000..7113f2c Binary files /dev/null and b/backend/public/images/file1713098648907-711314914.png differ diff --git a/backend/public/images/file1713103092130-854150407.png b/backend/public/images/file1713103092130-854150407.png new file mode 100644 index 0000000..2a7ae3e Binary files /dev/null and b/backend/public/images/file1713103092130-854150407.png differ diff --git a/backend/public/images/file1713103281942-971359767.png b/backend/public/images/file1713103281942-971359767.png new file mode 100644 index 0000000..2a7ae3e Binary files /dev/null and b/backend/public/images/file1713103281942-971359767.png differ diff --git a/backend/public/images/file1713109721454-315745900.png b/backend/public/images/file1713109721454-315745900.png new file mode 100644 index 0000000..2a7ae3e Binary files /dev/null and b/backend/public/images/file1713109721454-315745900.png differ diff --git a/backend/public/images/file1713111733223-436840186.jpg b/backend/public/images/file1713111733223-436840186.jpg new file mode 100644 index 0000000..e1c8aee Binary files /dev/null and b/backend/public/images/file1713111733223-436840186.jpg differ diff --git a/backend/public/images/file1713111770018-430670112.jpg b/backend/public/images/file1713111770018-430670112.jpg new file mode 100644 index 0000000..e50aa5d Binary files /dev/null and b/backend/public/images/file1713111770018-430670112.jpg differ diff --git a/backend/public/images/file1713111810489-562152929.jpg b/backend/public/images/file1713111810489-562152929.jpg new file mode 100644 index 0000000..8bcd0cd Binary files /dev/null and b/backend/public/images/file1713111810489-562152929.jpg differ diff --git a/backend/public/images/file1713111907545-407594864.jpg b/backend/public/images/file1713111907545-407594864.jpg new file mode 100644 index 0000000..b8fa3a5 Binary files /dev/null and b/backend/public/images/file1713111907545-407594864.jpg differ diff --git a/backend/public/images/file1713111957089-59714783.jpg b/backend/public/images/file1713111957089-59714783.jpg new file mode 100644 index 0000000..5abdbfa Binary files /dev/null and b/backend/public/images/file1713111957089-59714783.jpg differ diff --git a/backend/public/images/file1713112011535-362797407.jpg b/backend/public/images/file1713112011535-362797407.jpg new file mode 100644 index 0000000..cf6cea8 Binary files /dev/null and b/backend/public/images/file1713112011535-362797407.jpg differ diff --git a/backend/public/images/file1713112042097-888226472.jpg b/backend/public/images/file1713112042097-888226472.jpg new file mode 100644 index 0000000..59fc247 Binary files /dev/null and b/backend/public/images/file1713112042097-888226472.jpg differ diff --git a/backend/public/images/file1713112083638-856167721.jpg b/backend/public/images/file1713112083638-856167721.jpg new file mode 100644 index 0000000..8832442 Binary files /dev/null and b/backend/public/images/file1713112083638-856167721.jpg differ diff --git a/backend/public/images/file1713112141707-659397431.jpg b/backend/public/images/file1713112141707-659397431.jpg new file mode 100644 index 0000000..e8d6456 Binary files /dev/null and b/backend/public/images/file1713112141707-659397431.jpg differ diff --git a/backend/public/images/file1713112178395-69869683.jpg b/backend/public/images/file1713112178395-69869683.jpg new file mode 100644 index 0000000..9976985 Binary files /dev/null and b/backend/public/images/file1713112178395-69869683.jpg differ diff --git a/backend/public/images/file1713112246985-470000357.jpg b/backend/public/images/file1713112246985-470000357.jpg new file mode 100644 index 0000000..5f5baa4 Binary files /dev/null and b/backend/public/images/file1713112246985-470000357.jpg differ diff --git a/backend/public/images/file1713112275985-618774172.jpg b/backend/public/images/file1713112275985-618774172.jpg new file mode 100644 index 0000000..f1edee8 Binary files /dev/null and b/backend/public/images/file1713112275985-618774172.jpg differ diff --git a/backend/routes/BlogRoutes.js b/backend/routes/BlogRoutes.js index 54f975d..501804f 100644 --- a/backend/routes/BlogRoutes.js +++ b/backend/routes/BlogRoutes.js @@ -1,14 +1,18 @@ - const express = require("express"); const BlogsController = require("../contollers/BlogsController"); const router = express.Router(); + + +// app. router.get("/blogs", BlogsController.getAllBlogs); -router.get("/myblogs/:uid", BlogsController.getBlogsByUserId) -router.post("/create",BlogsController.createBlog); +router.get("/myblogs/:uid", BlogsController.getBlogsByUserId); +// router.post("/create", BlogsController.createBlog); + +// router.post("/create", upload.single("file"), BlogsController.createBlog); router.get("/:bid", BlogsController.getBlogById); router.patch("/:bid", BlogsController.updateBlog); -router.delete("/:bid", BlogsController.deleteBlog) +router.delete("/:bid", BlogsController.deleteBlog); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/frontend/src/App.js b/frontend/src/App.js index b6b9f85..9892338 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -18,21 +18,24 @@ import EditBlog from "./components/pages/EditBlog"; function App() { const [isLoggedIn , setIsLoggedIn] = useState(false); const [userId, setUserId ] = useState(null); - const login = (userId) => { + const [name, setName] = useState(""); + const login = (userId, name) => { setIsLoggedIn(true); setUserId(userId); + setName(name); } const logout = () => { setIsLoggedIn(false); setUserId(null); + setName("") } return ( + - diff --git a/frontend/src/Contexts/AuthContext.js b/frontend/src/Contexts/AuthContext.js index 12a2dcd..35146dc 100644 --- a/frontend/src/Contexts/AuthContext.js +++ b/frontend/src/Contexts/AuthContext.js @@ -5,7 +5,7 @@ import {createContext} from "react"; const AuthContext = createContext({ userId : null, isLoggedIn : false, - + name : "", login : () => {}, logout : () => {} }) diff --git a/frontend/src/Utils/DropdownButton.jsx b/frontend/src/Utils/DropdownButton.jsx new file mode 100644 index 0000000..c44978c --- /dev/null +++ b/frontend/src/Utils/DropdownButton.jsx @@ -0,0 +1,39 @@ + + + +import React, { useContext, useState } from 'react'; +import AuthContext from '../Contexts/AuthContext'; +import { Link } from 'react-router-dom'; +const DropdownButton = ({userName}) => { + + + const auth = useContext(AuthContext); + const [isOpen, setIsOpen] = useState(false); + + const firstLetter = userName.charAt(0).toUpperCase(); + const colors = ['#FF5733', '#FFC300', '#FF5733', '#FFC300', '#FF5733']; + const toggleDropdown = () => { + setIsOpen(!isOpen); + }; + const handleLogout = () =>{ + auth.logout(); + } + + return ( +
+ + {isOpen&& auth.isLoggedIn && ( +
+
    +
  • My Blogs
  • +
  • +
+
+ )} +
+ ); +}; + +export default DropdownButton; \ No newline at end of file diff --git a/frontend/src/Utils/ProfilePicture.jsx b/frontend/src/Utils/ProfilePicture.jsx new file mode 100644 index 0000000..9a4b35a --- /dev/null +++ b/frontend/src/Utils/ProfilePicture.jsx @@ -0,0 +1,14 @@ + + +const ProfilePicture = ({userName}) => { + + const firstLetter = userName.charAt(0).toUpperCase(); + const colors = ['#FF5733', '#FFC300', '#FF5733', '#FFC300', '#FF5733']; + return( +
+ {firstLetter} +
+ ); +} + +export default ProfilePicture; \ No newline at end of file diff --git a/frontend/src/components/Blog/Blog.jsx b/frontend/src/components/Blog/Blog.jsx index 1b4acf5..96789e8 100644 --- a/frontend/src/components/Blog/Blog.jsx +++ b/frontend/src/components/Blog/Blog.jsx @@ -1,54 +1,62 @@ - - -import React, { useEffect, useState } from 'react' -import BlogCard from './BlogCard' +import React, { useEffect, useState } from "react"; +import BlogCard from "./BlogCard"; import logo from "../../logo.svg"; -import ErrorModal from '../../Utils/ErrorModal'; - +import ErrorModal from "../../Utils/ErrorModal"; function Blog() { - const[error, setError] = useState(""); - const[blogs , setBlogs] = useState([]); + const [error, setError] = useState(""); + const [blogs, setBlogs] = useState([]); const handleOnDelete = (blogId) => { - setBlogs(prevBlogs => prevBlogs.filter(blog => blog._id !== blogId)) - } + setBlogs((prevBlogs) => prevBlogs.filter((blog) => blog._id !== blogId)); + }; const fetchBlogs = async () => { - try{ - + try { const repsonse = await fetch(`http://localhost:5000/api/blog/blogs`); const result = await repsonse.json(); - if(!repsonse.ok) { + if (!repsonse.ok) { setBlogs([]); console.log("No data found"); throw new Error(); // return ; } - + setBlogs(result); setError(""); - - } - catch(err) { + } catch (err) { console.log(err); - setError("Unable to fetch Blogs this time.") + setError("Unable to fetch Blogs this time."); } - - } + }; useEffect(() => { - const fetchBlogsData = async ()=> { - + const fetchBlogsData = async () => { await fetchBlogs(); - } + }; fetchBlogsData(); }, [blogs]); - + return ( -
- {error && } - {!error && blogs.map( blog => )} +
+ {error && } + {!error && + blogs.map((blog) => ( + + ))}
- ) + ); } -export default Blog \ No newline at end of file +export default Blog; diff --git a/frontend/src/components/Blog/BlogCard.jsx b/frontend/src/components/Blog/BlogCard.jsx index 5a03a6d..3f9b50b 100644 --- a/frontend/src/components/Blog/BlogCard.jsx +++ b/frontend/src/components/Blog/BlogCard.jsx @@ -1,32 +1,46 @@ import React, { useContext, useState } from "react"; import AuthContext from "../../Contexts/AuthContext"; import { Link } from "react-router-dom"; -import {useNavigate} from "react-router-dom" +import { useNavigate } from "react-router-dom"; import ConfirmationModal from "../../Utils/ConfirmationModal"; -const BlogCard = ({ title, author, date, image, content, creator, blogId, onDelete }) => { +const BlogCard = ({ + title, + author, + date, + image, + content, + creator, + blogId, + onDelete, +}) => { const auth = useContext(AuthContext); const [modal, setModal] = useState(false); const navigate = useNavigate(); - const handleDelete = async() => { - try{ - + const handleDelete = async () => { + try { const response = await fetch(`http://localhost:5000/api/blog/${blogId}`, { - method : "DELETE", - }) + method: "DELETE", + }); onDelete(blogId); - setModal(false) + setModal(false); // navigate("/myblogs") - } - catch(err) { + } catch (err) { console.log(err); } - - } + }; // console.log(blogId) return (
- {modal && setModal(false)}/>} + {modal && ( + setModal(false)} + /> + )} {title}
{title}
@@ -47,10 +61,16 @@ const BlogCard = ({ title, author, date, image, content, creator, blogId, onDele
{auth.userId === creator && (
- + Edit - {" "}
diff --git a/frontend/src/components/Blog/BlogForm.jsx b/frontend/src/components/Blog/BlogForm.jsx index 0f18baa..827c445 100644 --- a/frontend/src/components/Blog/BlogForm.jsx +++ b/frontend/src/components/Blog/BlogForm.jsx @@ -1,110 +1,118 @@ import React, { useContext, useEffect, useState } from "react"; import AuthContext from "../../Contexts/AuthContext"; -import {useNavigate} from "react-router-dom" -import getDate from "../../Utils/date-formatter" -const BlogForm = ({prevTitle = "", prevContent = "", isEdit, blogId}) => { - const[title , setTitle] = useState(prevTitle); - const [content , setContent] = useState(prevContent); - const auth = useContext(AuthContext); - const navigate = useNavigate(); - const handleSubmit =async (event) => { - - event.preventDefault(); +import { useNavigate } from "react-router-dom"; +import getDate from "../../Utils/date-formatter"; - if(isEdit) { - try{ - const response = await fetch(`http://localhost:5000/api/blog/${blogId}`, { - method : "PATCH", - headers : { - "Content-Type" : "application/json" - }, - body : JSON.stringify({ - title, - content, - creator : auth.userId - }) - }) - navigate('/myblogs'); - } - catch(err) { - console.log(err); - console.log(err.message); - } - } - else{ +const BlogForm = ({ prevTitle = "", prevContent = "", isEdit, blogId }) => { + const [title, setTitle] = useState(prevTitle); + const [content, setContent] = useState(prevContent); + const [image, setImage] = useState(); + const auth = useContext(AuthContext); + const navigate = useNavigate(); + const handleSubmit = async (event) => { + event.preventDefault(); + if (isEdit) { + try { - const response = await fetch(`http://localhost:5000/api/user/${auth.userId}`); - const result = await response.json(); - - const blog = await fetch(`http://localhost:5000/api/blog/create`, { - method : 'POST', + console.log(image) + const response = await fetch( + `http://localhost:5000/api/blog/${blogId}`, + { + method: "PATCH", headers : { - "Content-Type" : "application/json" + 'Content-Type' : 'application/json' }, - body : JSON.stringify({ - title, - content, - creator : auth.userId, - author : result.name, - date : getDate() + body : JSON.stringify({ + title, + content, + creator : auth.userId }) - }) - navigate("/"); + } + ); + navigate("/myblogs"); + } catch (err) { + console.log(err); + console.log(err.message); } + } else { + const response = await fetch( + `http://localhost:5000/api/user/${auth.userId}` + ); + const result = await response.json(); + const formData = new FormData(); + formData.append('title', title); + formData.append('content', content); + formData.append('creator', auth.userId); + formData.append('file', image); + formData.append('author', result.name); + formData.append('date' , getDate()); + const blog = await fetch(`http://localhost:5000/api/blog/create`, { + method: "POST", + body : formData + }); + navigate("/"); } - useEffect(() => { - setTitle(prevTitle) - setContent(prevContent) - }, [prevTitle, prevContent]) - + }; + useEffect(() => { + setTitle(prevTitle); + setContent(prevContent); + }, [prevTitle, prevContent]); + return ( -
-
-
- - setTitle(e.target.value)} - placeholder="Enter title" - /> -
-
- - -
-
- - + +
+
+ + setTitle(e.target.value)} + placeholder="Enter title" + /> +
+
+ + +
+
+ setImage(e.target.files[0])} + /> +
+
+ +
-
); diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx index d4a51af..0f8f97a 100644 --- a/frontend/src/components/Navbar.jsx +++ b/frontend/src/components/Navbar.jsx @@ -1,22 +1,49 @@ - - - - -import React from "react"; -import logo from '../logo.svg'; +import React, { useContext, useEffect, useState } from "react"; +import logo from "../logo.svg"; import { Link } from "react-router-dom"; - const Navbar = () => { +import ProfilePicture from "../Utils/ProfilePicture"; +import AuthContext from "../Contexts/AuthContext"; +import DropdownButton from "../Utils/DropdownButton"; +const Navbar = () => { + const auth = useContext(AuthContext); + const [profile, setProfile] = useState(); + useEffect(() => { + if (auth.isLoggedIn) { + setProfile(auth.userId); + } else { + setProfile("Login"); + } + }, [auth.isLoggedIn]); return (
@@ -25,4 +52,3 @@ import { Link } from "react-router-dom"; }; export default Navbar; - \ No newline at end of file diff --git a/frontend/src/components/pages/Auth.jsx b/frontend/src/components/pages/Auth.jsx index 50c91ae..e503f5b 100644 --- a/frontend/src/components/pages/Auth.jsx +++ b/frontend/src/components/pages/Auth.jsx @@ -32,7 +32,7 @@ const Auth = () => { setError(result.message); return; } - auth.login(result._id); + auth.login(result._id, result.name); navigate("/") } catch(err) { @@ -58,7 +58,7 @@ const Auth = () => { setError(result.message); return; } - auth.login(result._id); + auth.login(result._id, result.name); navigate("/"); } catch(err) { diff --git a/frontend/src/components/pages/MyBlogs.jsx b/frontend/src/components/pages/MyBlogs.jsx index c2b1683..497ec0e 100644 --- a/frontend/src/components/pages/MyBlogs.jsx +++ b/frontend/src/components/pages/MyBlogs.jsx @@ -9,9 +9,10 @@ function MyBlogs() { const [error, setError] = useState(""); const [blogs, setBlogs] = useState([]); const auth = useContext(AuthContext); + console.log(auth.isLoggedIn); const handleOnDelete = (blogId) => { - setBlogs(prevBlogs => prevBlogs.filter(blog => blog._id !== blogId)); - } + setBlogs((prevBlogs) => prevBlogs.filter((blog) => blog._id !== blogId)); + }; useEffect(() => { const fetchBlogs = async () => { try { @@ -69,14 +70,14 @@ function MyBlogs() {
)} - {blogs.map((blog) => ( + {auth.isLoggedIn && blogs.map((blog) => (