├── .DS_Store
├── README.md
├── front-end
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── components
│ ├── CreatePost.js
│ ├── ListPosts.js
│ └── SinglePost.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ ├── pages
│ └── Home.js
│ ├── routes
│ └── index.js
│ ├── services
│ └── postServices.js
│ └── setupTests.js
└── server
├── .eslintrc.json
├── .gitignore
├── .prettierrc.json
├── .vscode
└── settings.json
├── config
├── db.js
└── index.js
├── controllers
├── error.js
└── posts.js
├── index.js
├── middlewares
└── uploadFile.js
├── models
└── posts.js
├── package-lock.json
├── package.json
├── public
└── images
│ ├── 1666301943469-Anisul.png
│ ├── 1666303198381-Anisul.png
│ ├── 1666303214190-Anisul.png
│ ├── 1666303229045-Anisul.png
│ ├── 1666303436288-Anisul.png
│ ├── 1666303462846-Anisul.png
│ ├── 1666303513808-Anisul.png
│ ├── 1666568153702-be8f9650-a8c2-4674-98c1-3ebf5ddc6fce (4).jpg
│ ├── 1666569360764-Desktop - 2.png
│ ├── 1666569381963-Desktop - 2.png
│ ├── 1666639711555-anisul.jpeg
│ ├── 1666639834935-Desktop - 2.png
│ ├── 1666640370602-Desktop - 2.png
│ ├── 1666640391124-Green Nature Rain Sounds Music YouTube Thumbnail (1).png
│ ├── 1666640491695-Desktop - 2.png
│ ├── 1666640552331-anisul.jpeg
│ ├── 1666640571168-Desktop - 2.png
│ ├── 1666641573353-Anisul Islam.png
│ └── 1666681937425-anisul.jpeg
└── routes
└── posts.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/.DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CRUD MERN-STACK APP: blog posts
2 |
3 | - create the api
4 | - use it from front end
5 |
--------------------------------------------------------------------------------
/front-end/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/front-end/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `npm start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
13 |
14 | The page will reload when you make changes.\
15 | You may also see any lint errors in the console.
16 |
17 | ### `npm test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `npm run build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `npm run eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can't go back!**
35 |
36 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
39 |
40 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
48 | ### Code Splitting
49 |
50 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
51 |
52 | ### Analyzing the Bundle Size
53 |
54 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
55 |
56 | ### Making a Progressive Web App
57 |
58 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
59 |
60 | ### Advanced Configuration
61 |
62 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
63 |
64 | ### Deployment
65 |
66 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
67 |
68 | ### `npm run build` fails to minify
69 |
70 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
71 |
--------------------------------------------------------------------------------
/front-end/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front-end",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.4.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "axios": "^1.1.3",
10 | "react": "^18.2.0",
11 | "react-dom": "^18.2.0",
12 | "react-router-dom": "^6.4.2",
13 | "react-scripts": "5.0.1",
14 | "web-vitals": "^2.1.4"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/front-end/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/front-end/public/favicon.ico
--------------------------------------------------------------------------------
/front-end/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/front-end/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/front-end/public/logo192.png
--------------------------------------------------------------------------------
/front-end/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/front-end/public/logo512.png
--------------------------------------------------------------------------------
/front-end/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/front-end/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/front-end/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/front-end/src/App.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | import "./App.css";
4 | import Index from "./routes";
5 |
6 | const App = () => {
7 | return (
8 |
9 |
10 |
11 | );
12 | };
13 |
14 | export default App;
15 |
--------------------------------------------------------------------------------
/front-end/src/App.test.js:
--------------------------------------------------------------------------------
1 | import { render, screen } from '@testing-library/react';
2 | import App from './App';
3 |
4 | test('renders learn react link', () => {
5 | render( );
6 | const linkElement = screen.getByText(/learn react/i);
7 | expect(linkElement).toBeInTheDocument();
8 | });
9 |
--------------------------------------------------------------------------------
/front-end/src/components/CreatePost.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import Post from "../services/postServices";
3 | // var FormData = require("form-data");
4 | const CreatePost = () => {
5 | const [title, setTitle] = useState("");
6 | const [date, setDate] = useState("");
7 | const [image, setImage] = useState("");
8 | const [message, setMessage] = useState("");
9 |
10 | const handleTitleChange = (event) => {
11 | setTitle(event.target.value);
12 | };
13 | const handleDateChange = (event) => {
14 | setDate(event.target.value);
15 | };
16 | const handleImageChange = (event) => {
17 | console.log(event.target.files);
18 | setImage(event.target.files[0]);
19 | };
20 |
21 | const handleSubmit = async (event) => {
22 | event.preventDefault();
23 |
24 | const formData = new FormData();
25 | formData.append("title", title);
26 | formData.append("date", date);
27 | formData.append("image", image);
28 |
29 | // console.log(newUser);
30 | // for (const [key, value] of formData) {
31 | // console.log(key, value);
32 | // }
33 |
34 | await Post.createPost(formData);
35 | };
36 |
37 | return (
38 |
39 |
Create Post
40 |
41 | {/* photo preview and get photo */}
42 | {image && (
43 |
44 |
49 |
50 | )}
51 |
52 |
88 | {message &&
{message}
}
89 |
90 | );
91 | };
92 |
93 | export default CreatePost;
94 |
--------------------------------------------------------------------------------
/front-end/src/components/ListPosts.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import Post from "../services/postServices";
3 | import SinglePost from "./SinglePost";
4 |
5 | const ListPosts = () => {
6 | const [posts, setPosts] = useState([]);
7 |
8 | const fetchPosts = async () => {
9 | const result = await Post.getPosts();
10 | setPosts(result.data.data);
11 | console.log(posts);
12 | };
13 |
14 | const handleDeletePost = async (id) => {
15 | const result = await Post.deletePost(id);
16 | if (result.data.success === true) {
17 | console.log("product is deleted");
18 | fetchPosts();
19 | }
20 | };
21 |
22 | useEffect(() => {
23 | fetchPosts();
24 | }, []);
25 |
26 | return (
27 |
28 |
Posts
29 | {posts.length > 1 &&
30 | posts.map((post) => (
31 |
36 | ))}
37 |
38 | );
39 | };
40 |
41 | export default ListPosts;
42 |
--------------------------------------------------------------------------------
/front-end/src/components/SinglePost.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Post from "../services/postServices";
3 |
4 | const SinglePost = ({ post, onHandleDeletePost }) => {
5 | const handleDelete = (id) => {
6 | onHandleDeletePost(id);
7 | };
8 | return (
9 |
10 |
{post.title}
11 |
{post.date}
12 |
18 |
19 | {
21 | handleDelete(post._id);
22 | }}
23 | >
24 | Delete
25 |
26 |
27 |
28 | );
29 | };
30 |
31 | export default SinglePost;
32 |
--------------------------------------------------------------------------------
/front-end/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/front-end/src/index.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import "./index.css";
4 | import App from "./App";
5 |
6 | const root = ReactDOM.createRoot(document.getElementById("root"));
7 | root.render(
8 |
9 |
10 |
11 | );
12 |
--------------------------------------------------------------------------------
/front-end/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/front-end/src/pages/Home.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 |
3 | const Home = () => {
4 | return (
5 |
6 |
Home Page
7 |
8 | );
9 | };
10 |
11 | export default Home;
12 |
--------------------------------------------------------------------------------
/front-end/src/routes/index.js:
--------------------------------------------------------------------------------
1 | import { BrowserRouter, Routes, Route, Link } from "react-router-dom";
2 | import React from "react";
3 | import CreatePost from "../components/CreatePost";
4 | import Home from "../pages/Home";
5 | import ListPosts from "../components/ListPosts";
6 |
7 | const Index = () => {
8 | return (
9 |
10 |
11 | Home
12 | Create Post
13 | List Posts
14 |
15 |
16 |
17 | } />
18 | } />
19 | } />
20 |
21 |
22 | );
23 | };
24 |
25 | export default Index;
26 |
--------------------------------------------------------------------------------
/front-end/src/services/postServices.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | class Post {
4 | static async createPost(formData) {
5 | return await axios.post("http://localhost:3001/api/v1/posts", formData);
6 | }
7 | static async getPosts() {
8 | return await axios("http://localhost:3001/api/v1/posts");
9 | }
10 | static async deletePost(id) {
11 | return await axios.delete("http://localhost:3001/api/v1/posts/" + id);
12 | }
13 | }
14 | export default Post;
15 |
--------------------------------------------------------------------------------
/front-end/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/server/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es2021": true
6 | },
7 | "extends": "eslint:recommended",
8 | "overrides": [],
9 | "parserOptions": {
10 | "ecmaVersion": "latest"
11 | },
12 | "rules": {
13 | "no-var": "error",
14 | "camelcase": "error",
15 | "no-empty": "error",
16 | "default-case": "error",
17 | "eqeqeq": "error"
18 | // "max-lines": ["error", 50],
19 | // "max-depth": ["error", 3]
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 | .pnpm-debug.log*
9 |
10 | # Diagnostic reports (https://nodejs.org/api/report.html)
11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # Snowpack dependency directory (https://snowpack.dev/)
46 | web_modules/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Optional stylelint cache
58 | .stylelintcache
59 |
60 | # Microbundle cache
61 | .rpt2_cache/
62 | .rts2_cache_cjs/
63 | .rts2_cache_es/
64 | .rts2_cache_umd/
65 |
66 | # Optional REPL history
67 | .node_repl_history
68 |
69 | # Output of 'npm pack'
70 | *.tgz
71 |
72 | # Yarn Integrity file
73 | .yarn-integrity
74 |
75 | # dotenv environment variable files
76 | .env
77 | .env.development.local
78 | .env.test.local
79 | .env.production.local
80 | .env.local
81 |
82 | # parcel-bundler cache (https://parceljs.org/)
83 | .cache
84 | .parcel-cache
85 |
86 | # Next.js build output
87 | .next
88 | out
89 |
90 | # Nuxt.js build / generate output
91 | .nuxt
92 | dist
93 |
94 | # Gatsby files
95 | .cache/
96 | # Comment in the public line in if your project uses Gatsby and not Next.js
97 | # https://nextjs.org/blog/next-9-1#public-directory-support
98 | # public
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # vuepress v2.x temp and cache directory
104 | .temp
105 | .cache
106 |
107 | # Docusaurus cache and generated files
108 | .docusaurus
109 |
110 | # Serverless directories
111 | .serverless/
112 |
113 | # FuseBox cache
114 | .fusebox/
115 |
116 | # DynamoDB Local files
117 | .dynamodb/
118 |
119 | # TernJS port file
120 | .tern-port
121 |
122 | # Stores VSCode versions used for testing VSCode extensions
123 | .vscode-test
124 |
125 | # yarn v2
126 | .yarn/cache
127 | .yarn/unplugged
128 | .yarn/build-state.yml
129 | .yarn/install-state.gz
130 | .pnp.*
--------------------------------------------------------------------------------
/server/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSameLine": true,
3 | "bracketSpacing": true,
4 | "printWidth": 200,
5 | "semi": true,
6 | "singleQuote": true,
7 | "tabWidth": 2,
8 | "trailingComma": "none",
9 | "useTabs": false
10 | }
11 |
--------------------------------------------------------------------------------
/server/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "editor.formatOnSave": true,
4 | "editor.formatOnPaste": true
5 | }
6 |
--------------------------------------------------------------------------------
/server/config/db.js:
--------------------------------------------------------------------------------
1 | const mongoose = require('mongoose');
2 | const dev = require('.');
3 |
4 | const connectDB = async () => {
5 | try {
6 | await mongoose.connect(dev.db.url);
7 | console.log('db is connected');
8 | } catch (error) {
9 | console.log('db is not connected');
10 | console.log(error);
11 | }
12 | };
13 | module.exports = connectDB;
14 |
--------------------------------------------------------------------------------
/server/config/index.js:
--------------------------------------------------------------------------------
1 | require("dotenv").config();
2 | const dev = {
3 | db: {
4 | url: process.env.DB_URL || "mongodb://127.0.0.1:27017/CRUD-DB",
5 | },
6 | app: {
7 | port: process.env.SERVER_PORT || 3002,
8 | },
9 | };
10 |
11 | module.exports = dev;
12 |
--------------------------------------------------------------------------------
/server/controllers/error.js:
--------------------------------------------------------------------------------
1 | exports.clientError = async (res, statusCode, message) => {
2 | res.status(statusCode).send({
3 | success: false,
4 | message: message
5 | });
6 | };
7 | exports.serverError = async (res, statusCode, message) => {
8 | res.status(statusCode).send({
9 | success: false,
10 | message: message
11 | });
12 | };
13 |
--------------------------------------------------------------------------------
/server/controllers/posts.js:
--------------------------------------------------------------------------------
1 | const Post = require('../models/posts');
2 | const { clientError, serverError } = require('./error');
3 |
4 | const getPosts = async (req, res) => {
5 | try {
6 | const posts = await Post.find();
7 | if (posts) {
8 | res.status(200).send({
9 | success: true,
10 | message: 'find all posts',
11 | data: posts
12 | });
13 | } else {
14 | await clientError(res, 404, 'post with this id was not found');
15 | }
16 | } catch (error) {
17 | await serverError(res, 500, error.message);
18 | }
19 | };
20 |
21 | const getPost = async (req, res) => {
22 | try {
23 | const id = req.params.id;
24 | const post = await Post.findOne({ _id: id });
25 | if (post) {
26 | res.status(200).send({
27 | success: true,
28 | message: 'find single posts',
29 | data: post
30 | });
31 | } else {
32 | await clientError(res, 404, 'post with this id was not found');
33 | }
34 | } catch (error) {
35 | await serverError(res, 500, error.message);
36 | }
37 | };
38 |
39 | const addPost = async (req, res) => {
40 | try {
41 | console.log(req.body);
42 | const newPost = new Post({
43 | title: req.body.title,
44 | date: req.body.date,
45 | image: req.file.filename
46 | });
47 | const post = await newPost.save();
48 | if (post) {
49 | res.status(201).send({
50 | success: true,
51 | message: 'post was added',
52 | data: post
53 | });
54 | }
55 | } catch (error) {
56 | await serverError(res, 500, error.message);
57 | }
58 | };
59 |
60 | const deletePost = async (req, res) => {
61 | try {
62 | const id = req.params.id;
63 | const post = await Post.findOne({ _id: id });
64 | if (post) {
65 | await Post.deleteOne({ _id: id });
66 | res.status(200).send({
67 | success: true,
68 | message: 'post was deleted'
69 | });
70 | } else {
71 | await clientError(res, 404, 'post with this id was not found');
72 | }
73 | } catch (error) {
74 | await serverError(res, 500, error.message);
75 | }
76 | };
77 |
78 | const updatePost = async (req, res) => {
79 | try {
80 | if (req.file !== undefined) {
81 | const id = req.body.id;
82 | const post = await Post.findOne({ _id: id });
83 | if (post) {
84 | await Post.updateOne(
85 | { _id: id },
86 | {
87 | $set: {
88 | title: req.body.title,
89 | image: req.file.filename,
90 | date: req.body.date
91 | }
92 | }
93 | );
94 | res.status(200).send({
95 | success: true,
96 | message: 'post was updated'
97 | });
98 | } else {
99 | await clientError(res, 404, 'post with this id was not found');
100 | }
101 | } else {
102 | const id = req.body.id;
103 | await Post.updateOne(
104 | { _id: id },
105 | {
106 | $set: {
107 | title: req.body.title,
108 | date: req.body.date
109 | }
110 | }
111 | );
112 | res.status(200).send({
113 | success: true,
114 | message: 'post was updated'
115 | });
116 | }
117 | } catch (error) {
118 | await serverError(res, 500, error.message);
119 | }
120 | };
121 |
122 | module.exports = { getPosts, getPost, addPost, deletePost, updatePost };
123 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const morgan = require('morgan');
3 | const chalk = require('chalk');
4 | const cors = require('cors');
5 |
6 | const dev = require('./config');
7 | const connectDB = require('./config/db');
8 | const postsRoute = require('./routes/posts');
9 |
10 | const app = express();
11 | const port = dev.app.port;
12 |
13 | app.use(
14 | cors({
15 | origin: '*'
16 | // origin: 'http://localhost:3000'
17 | })
18 | );
19 | app.use(morgan('dev'));
20 |
21 | app.use('/api/v1/posts', postsRoute);
22 |
23 | app.listen(port, async () => {
24 | console.log(chalk.blue(`server is running at http://localhost:${port}`));
25 | await connectDB();
26 | });
27 |
--------------------------------------------------------------------------------
/server/middlewares/uploadFile.js:
--------------------------------------------------------------------------------
1 | const multer = require('multer');
2 | const path = require('path');
3 |
4 | const MAX_FILE_SIZE = process.env.MAX_FILE_SIZE || 1024 * 1024 * 2; // 2MB
5 | const ALLOWED_FILE_TYPES = process.env.ALLOWED_FILE_TYPES || [
6 | 'jpg',
7 | 'jpeg',
8 | 'png',
9 | ];
10 | const UPLOAD_DIR = process.env.UPLOAD_DIR || 'public/images/users';
11 |
12 | const storage = multer.diskStorage({
13 | destination: function (req, file, cb) {
14 | cb(null, UPLOAD_DIR);
15 | },
16 | filename: function (req, file, cb) {
17 | const extname = path.extname(file.originalname);
18 | cb(
19 | null,
20 | Date.now() + '-' + file.originalname.replace(extname, '') + extname
21 | );
22 | },
23 | });
24 |
25 | const fileFilter = (req, file, cb) => {
26 | const extname = path.extname(file.originalname);
27 | if (!ALLOWED_FILE_TYPES.includes(extname.substring(1))) {
28 | const error = new Error('File type not allowed');
29 | console.log('error: ', error);
30 | return cb(error);
31 | }
32 | cb(null, true);
33 | };
34 |
35 | const upload = multer({
36 | storage,
37 | limits: { fileSize: MAX_FILE_SIZE },
38 | fileFilter,
39 | });
40 |
41 | module.exports = upload;
42 |
--------------------------------------------------------------------------------
/server/models/posts.js:
--------------------------------------------------------------------------------
1 | const { Schema, model } = require('mongoose');
2 |
3 | const postsSchema = new Schema({
4 | title: {
5 | type: String,
6 | required: [true, 'post title is required'],
7 | minlength: [3, 'post title must be atleast 3 characters']
8 | },
9 | date: {
10 | type: String,
11 | required: [true, 'post date is required']
12 | },
13 | image: {
14 | type: String,
15 | required: [true, 'post image is required']
16 | }
17 | });
18 |
19 | const Post = model('Posts', postsSchema);
20 | module.exports = Post;
21 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mern-crud-app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "nodemon index.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "cors": "^2.8.5",
14 | "dotenv": "^16.0.3",
15 | "express": "^4.18.2",
16 | "mongoose": "^6.6.6",
17 | "multer": "^1.4.5-lts.1"
18 | },
19 | "devDependencies": {
20 | "chalk": "^4.1.2",
21 | "eslint": "^8.25.0",
22 | "morgan": "^1.10.0",
23 | "nodemon": "^2.0.20"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/server/public/images/1666301943469-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666301943469-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666303198381-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666303198381-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666303214190-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666303214190-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666303229045-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666303229045-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666303436288-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666303436288-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666303462846-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666303462846-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666303513808-Anisul.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666303513808-Anisul.png
--------------------------------------------------------------------------------
/server/public/images/1666568153702-be8f9650-a8c2-4674-98c1-3ebf5ddc6fce (4).jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666568153702-be8f9650-a8c2-4674-98c1-3ebf5ddc6fce (4).jpg
--------------------------------------------------------------------------------
/server/public/images/1666569360764-Desktop - 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666569360764-Desktop - 2.png
--------------------------------------------------------------------------------
/server/public/images/1666569381963-Desktop - 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666569381963-Desktop - 2.png
--------------------------------------------------------------------------------
/server/public/images/1666639711555-anisul.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666639711555-anisul.jpeg
--------------------------------------------------------------------------------
/server/public/images/1666639834935-Desktop - 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666639834935-Desktop - 2.png
--------------------------------------------------------------------------------
/server/public/images/1666640370602-Desktop - 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666640370602-Desktop - 2.png
--------------------------------------------------------------------------------
/server/public/images/1666640391124-Green Nature Rain Sounds Music YouTube Thumbnail (1).png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666640391124-Green Nature Rain Sounds Music YouTube Thumbnail (1).png
--------------------------------------------------------------------------------
/server/public/images/1666640491695-Desktop - 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666640491695-Desktop - 2.png
--------------------------------------------------------------------------------
/server/public/images/1666640552331-anisul.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666640552331-anisul.jpeg
--------------------------------------------------------------------------------
/server/public/images/1666640571168-Desktop - 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666640571168-Desktop - 2.png
--------------------------------------------------------------------------------
/server/public/images/1666641573353-Anisul Islam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666641573353-Anisul Islam.png
--------------------------------------------------------------------------------
/server/public/images/1666681937425-anisul.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/anisul-Islam/mern-crud-app-file-uploading/cd545a0d204cc7fb4388df3e1f3e607d612831a3/server/public/images/1666681937425-anisul.jpeg
--------------------------------------------------------------------------------
/server/routes/posts.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 |
3 | const { getPosts, addPost, getPost, deletePost, updatePost } = require('../controllers/posts');
4 | const upload = require('../middlewares/uploadFile');
5 |
6 | const postsRoute = express();
7 |
8 | // for parsing json and form data from the request body
9 | postsRoute.use(express.json());
10 | postsRoute.use(express.urlencoded({ extended: true }));
11 | postsRoute.use(express.static('public'));
12 |
13 | postsRoute.get('/', getPosts);
14 | postsRoute.get('/:id', getPost);
15 | postsRoute.post('/', upload, addPost);
16 | postsRoute.put('/', upload, updatePost);
17 | postsRoute.delete('/:id', deletePost);
18 |
19 | postsRoute.use('*', (req, res) => {
20 | res.send('Not a valid route');
21 | });
22 |
23 | module.exports = postsRoute;
24 |
--------------------------------------------------------------------------------