Browse Source

BE notfix

master
Wendy Gardiel 4 weeks ago
parent
commit
6ab79a7812
  1. 2
      .gitignore
  2. 52
      controllers/blogController.js
  3. 5
      index.js
  4. 5
      models/blogModel.js
  5. 23
      package-lock.json
  6. 1
      package.json
  7. 8
      routes/blogRoutes.js
  8. 9
      user.rest

2
.gitignore

@ -115,3 +115,5 @@ dist
.yarn/build-state.yml .yarn/build-state.yml
.yarn/install-state.gz .yarn/install-state.gz
.pnp.* .pnp.*
uploads/

52
controllers/blogController.js

@ -26,20 +26,35 @@ export const getBlogById = async (req, res) => {
} }
}; };
// Get blog by slug
export const getBlogBySlug = async (req, res) => {
try {
const blog = await blogModel.findOne({
where: { slug: req.params.slug },
include: [{ model: blogImage, as: "images" }],
});
if (!blog) return res.status(404).json({ message: "Blog not found" });
res.json(blog);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// Create a new blog // Create a new blog
export const createBlog = async (req, res) => { export const createBlog = async (req, res) => {
try { try {
const { title, description } = req.body; const { title, description } = req.body;
// Pastikan ada file yang diunggah
if (!req.files || req.files.length === 0) { if (!req.files || req.files.length === 0) {
return res.status(400).json({ message: "Minimal 1 gambar diperlukan!" }); return res.status(400).json({ message: "Minimal 1 gambar diperlukan!" });
} }
// Simpan data blog const slug = generateSlug(title); // 🔥 generate slug di sini
const blog = await blogModel.create({ title, description }); const blog = await blogModel.create({ title, description, slug });
// Simpan gambar ke database
const imagePaths = req.files.map((file) => ({ const imagePaths = req.files.map((file) => ({
blogId: blog.id, blogId: blog.id,
imageUrl: `/uploads/${file.filename}`, imageUrl: `/uploads/${file.filename}`,
@ -47,9 +62,8 @@ export const createBlog = async (req, res) => {
await blogImage.bulkCreate(imagePaths); await blogImage.bulkCreate(imagePaths);
// Ambil data blog beserta gambar setelah disimpan
const newBlog = await blogModel.findByPk(blog.id, { const newBlog = await blogModel.findByPk(blog.id, {
include: [{ model: blogImage, as: "images" }], // Pastikan alias sesuai include: [{ model: blogImage, as: "images" }],
}); });
res.status(201).json({ res.status(201).json({
@ -61,12 +75,36 @@ export const createBlog = async (req, res) => {
} }
}; };
const generateSlug = (title) => {
return title
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^\w-]+/g, "");
};
// Update a blog // Update a blog
export const updateBlog = async (req, res) => { export const updateBlog = async (req, res) => {
try { try {
const blog = await blogModel.findByPk(req.params.id); const blog = await blogModel.findByPk(req.params.id);
if (!blog) return res.status(404).json({ message: "Blog not found" }); if (!blog) return res.status(404).json({ message: "Blog not found" });
await blog.update(req.body); const { title, description, slug } = req.body;
// Tentukan slug baru (jika ada title baru dan tidak ada slug manual)
let updatedSlug = blog.slug; // default: slug lama
if (title && !slug) {
updatedSlug = generateSlug(title);
} else if (slug) {
updatedSlug = slug;
}
// Update data
await blog.update({
title: title ?? blog.title,
description: description ?? blog.description,
slug: updatedSlug,
});
res.json(blog); res.json(blog);
} catch (error) { } catch (error) {
res.status(500).json({ message: error.message }); res.status(500).json({ message: error.message });

5
index.js

@ -3,11 +3,14 @@ import db from "./config/database.js";
import dotenv from "dotenv"; import dotenv from "dotenv";
import router from "./routes/index.js"; // Hanya import 1 router import router from "./routes/index.js"; // Hanya import 1 router
import cors from "cors"; import cors from "cors";
import cookieParser from "cookie-parser";
import path from "path";
const app = express(); const app = express();
dotenv.config(); dotenv.config();
const connectToDatabase = async () => { const connectToDatabase = async () => {
// await db.sync({ force: true });
try { try {
await db.authenticate(); await db.authenticate();
console.log("Database connected..."); console.log("Database connected...");
@ -18,8 +21,10 @@ const connectToDatabase = async () => {
connectToDatabase(); connectToDatabase();
app.use(cookieParser());
app.use(cors()); app.use(cors());
app.use(express.json()); app.use(express.json());
app.use(router); app.use(router);
app.use("/uploads", express.static(path.join(process.cwd(), "uploads")));
app.listen(5000, () => console.log("server running at port 5000")); app.listen(5000, () => console.log("server running at port 5000"));

5
models/blogModel.js

@ -13,6 +13,11 @@ const Blog = db.define("blog", {
type: DataTypes.TEXT, type: DataTypes.TEXT,
allowNull: false, allowNull: false,
}, },
slug: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
}); });
// Definisi relasi dengan alias 'images' // Definisi relasi dengan alias 'images'

23
package-lock.json

@ -10,6 +10,7 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"express": "^4.21.2", "express": "^4.21.2",
@ -455,6 +456,28 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/cookie-parser": {
"version": "1.4.7",
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
"integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
"license": "MIT",
"dependencies": {
"cookie": "0.7.2",
"cookie-signature": "1.0.6"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/cookie-parser/node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": { "node_modules/cookie-signature": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",

1
package.json

@ -11,6 +11,7 @@
}, },
"dependencies": { "dependencies": {
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5", "cors": "^2.8.5",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"express": "^4.21.2", "express": "^4.21.2",

8
routes/blogRoutes.js

@ -2,6 +2,7 @@ import express from "express";
import { import {
getAllBlogs, getAllBlogs,
getBlogById, getBlogById,
getBlogBySlug,
createBlog, createBlog,
updateBlog, updateBlog,
deleteBlog, deleteBlog,
@ -13,8 +14,9 @@ const router = express.Router();
router.get("/blog", getAllBlogs); router.get("/blog", getAllBlogs);
router.get("/blog/:id", getBlogById); router.get("/blog/:id", getBlogById);
router.post("/blog", verifyToken, upload.array("images", 5), createBlog); router.get("/blog/slug/:slug", getBlogBySlug);
router.patch("/blog/:id", verifyToken, updateBlog); router.post("/blog", upload.array("images", 5), createBlog);
router.delete("/blog/:id", verifyToken, deleteBlog); router.put("/blog/:id", updateBlog);
router.delete("/blog/:id", deleteBlog);
export default router; export default router;

9
user.rest

@ -1,9 +1,9 @@
POST http://localhost:5000/user/register POST http://localhost:5000/users/register
Content-type: application/json Content-type: application/json
{ {
"name" : "admin2", "name" : "admin",
"email" : "admin2@admin.com", "email" : "admin@admin.com",
"password" : "admin123", "password" : "admin123",
"confirmPassword" : "admin123" "confirmPassword" : "admin123"
} }
@ -20,6 +20,5 @@ Content-Type: application/json
### ###
GET http://localhost:5000/users GET http://localhost:5000/users/token
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsIm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AYWRtaW4uY29tIiwiaWF0IjoxNzQzMDQ0NDg5LCJleHAiOjE3NDMwNDQ1MDl9.m_tpB5DPpFDIaSWQki8jCKWqCbSzsBaKqh3W35a32XI
|||||||
100:0
Loading…
Cancel
Save