├── models ├── blog.js ├── admin.js └── trainer.js ├── eslint.config.js ├── routes ├── auth.routes.js ├── root.routes.js ├── blog.routes.js ├── admin.routes.js └── trainer.routes.js ├── middlewares ├── Uploader.js └── isAuth.js ├── package.json ├── .gitignore ├── index.js └── controllers ├── admin.controller.js ├── auth.controller.js ├── trainer.controller.js └── blog.controller.js /models/blog.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const BlogSchema = new mongoose.Schema( 4 | { 5 | title: { type: String, required: true }, 6 | description: { type: String }, 7 | photos: [String], 8 | }, 9 | { timestamps: true } 10 | ); 11 | 12 | export default mongoose.model("Blog", BlogSchema); 13 | -------------------------------------------------------------------------------- /models/admin.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const AdminSchema = new mongoose.Schema( 4 | { 5 | fullName: { type: String, required: true }, 6 | phoneNumber: { type: String, required: true, unique: true }, 7 | password: { type: String, required: true }, 8 | }, 9 | { timestamps: true } 10 | ); 11 | 12 | export default mongoose.model("Admin", AdminSchema); 13 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from "@eslint/js"; 2 | import globals from "globals"; 3 | import { defineConfig } from "eslint/config"; 4 | 5 | export default defineConfig([ 6 | { 7 | files: ["**/*.{js,mjs,cjs}"], 8 | plugins: { js }, 9 | extends: ["js/recommended"], 10 | }, 11 | { 12 | files: ["**/*.{js,mjs,cjs}"], 13 | languageOptions: { 14 | globals: globals.node, 15 | }, 16 | }, 17 | ]); 18 | -------------------------------------------------------------------------------- /routes/auth.routes.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { 3 | changePassword, 4 | login, 5 | register, 6 | } from "../controllers/auth.controller.js"; 7 | import isAuth from "../middlewares/isAuth.js"; 8 | 9 | const router = express.Router(); 10 | 11 | router.post("/login", login); 12 | router.post("/register", isAuth, register); 13 | router.post("/change-password", isAuth, changePassword); 14 | 15 | export default router; 16 | -------------------------------------------------------------------------------- /routes/root.routes.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import BlogRoutes from "./blog.routes.js"; 3 | import TrainerRoutes from "./trainer.routes.js"; 4 | import AdminRoutes from "./admin.routes.js"; 5 | import AuthRoutes from "./auth.routes.js"; 6 | 7 | const router = express.Router(); 8 | 9 | router.use("/auth", AuthRoutes); 10 | router.use("/blog", BlogRoutes); 11 | router.use("/trainer", TrainerRoutes); 12 | router.use("/admin", AdminRoutes); 13 | 14 | export default router; 15 | -------------------------------------------------------------------------------- /models/trainer.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const TrainerSchema = new mongoose.Schema( 4 | { 5 | fullName: { type: String, required: true }, 6 | photo: { type: String, required: true }, 7 | experience: { type: String, required: true }, 8 | level: { type: String, required: true }, 9 | students: { type: String, required: true }, 10 | }, 11 | { timestamps: true } 12 | ); 13 | 14 | export default mongoose.model("Trainer", TrainerSchema); 15 | -------------------------------------------------------------------------------- /routes/blog.routes.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { 3 | createBlog, 4 | deleteBlog, 5 | getAllBlogs, 6 | getBlogById, 7 | updateBlog, 8 | } from "../controllers/blog.controller.js"; 9 | import isAuth from "../middlewares/isAuth.js"; 10 | 11 | const router = express.Router(); 12 | 13 | router.get("/", getAllBlogs); 14 | router.get("/:id", getBlogById); 15 | router.post("/", isAuth, createBlog); 16 | router.put("/:id", isAuth, updateBlog); 17 | router.delete("/:id", isAuth, deleteBlog); 18 | 19 | export default router; 20 | -------------------------------------------------------------------------------- /routes/admin.routes.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import isAuth from "../middlewares/isAuth.js"; 3 | import { 4 | deleteAdmin, 5 | getAllAdmins, 6 | getUser, 7 | getAdmin, 8 | updateAdmin, 9 | } from "../controllers/admin.controller.js"; 10 | 11 | const router = express.Router(); 12 | 13 | router.use(isAuth); 14 | 15 | router.get("/", getAllAdmins); 16 | router.get("/profile", getUser); 17 | router.get("/:id", getAdmin); 18 | router.put("/:id", updateAdmin); 19 | router.delete("/:id", deleteAdmin); 20 | 21 | export default router; 22 | -------------------------------------------------------------------------------- /routes/trainer.routes.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { 3 | getAllTrainers, 4 | getTrainerById, 5 | createTrainer, 6 | updateTrainer, 7 | deleteTrainer, 8 | } from "../controllers/trainer.controller.js"; 9 | import isAuth from "../middlewares/isAuth.js"; 10 | 11 | const router = express.Router(); 12 | 13 | router.get("/", getAllTrainers); 14 | router.get("/:id", getTrainerById); 15 | router.post("/", isAuth, createTrainer); 16 | router.put("/:id", isAuth, updateTrainer); 17 | router.delete("/:id", isAuth, deleteTrainer); 18 | 19 | export default router; 20 | -------------------------------------------------------------------------------- /middlewares/Uploader.js: -------------------------------------------------------------------------------- 1 | import multer from "multer"; 2 | import crypto from "crypto"; 3 | import path from "path"; 4 | 5 | const storage = multer.diskStorage({ 6 | destination: (req, file, cb) => { 7 | cb(null, "uploads"); 8 | }, 9 | filename: (req, file, cb) => { 10 | const hash = crypto.randomBytes(16).toString("hex"); 11 | const ext = path.extname(file.originalname); 12 | cb(null, `${hash}${ext}`); 13 | }, 14 | }); 15 | 16 | export const upload = multer({ 17 | storage, 18 | fileFilter: (req, file, cb) => { 19 | if (!file.mimetype.startsWith("image/")) { 20 | return cb(new Error("Only image files are allowed!"), false); 21 | } 22 | cb(null, true); 23 | }, 24 | }); 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-server", 3 | "version": "1.0.0", 4 | "description": "backend side of seven sport center", 5 | "license": "ISC", 6 | "author": "Suhrob Rahmatullayev", 7 | "type": "module", 8 | "main": "index.js", 9 | "scripts": { 10 | "lint": "eslint .", 11 | "lint:fix": "eslint . --fix", 12 | "start": "node index.js", 13 | "dev": "nodemon index.js" 14 | }, 15 | "devDependencies": { 16 | "@eslint/js": "^9.24.0", 17 | "eslint": "^9.24.0", 18 | "globals": "^16.0.0", 19 | "nodemon": "^3.1.9" 20 | }, 21 | "dependencies": { 22 | "bcrypt": "^5.1.1", 23 | "cors": "^2.8.5", 24 | "dotenv": "^16.4.7", 25 | "express": "^4.21.2", 26 | "get-port": "^7.1.0", 27 | "jsonwebtoken": "^9.0.2", 28 | "mongoose": "^8.12.1", 29 | "multer": "^1.4.5-lts.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # static folders 2 | /uploads 3 | 4 | # compiled output 5 | /dist 6 | /node_modules 7 | /build 8 | 9 | # Logs 10 | logs 11 | *.log 12 | npm-debug.log* 13 | pnpm-debug.log* 14 | yarn-debug.log* 15 | yarn-error.log* 16 | lerna-debug.log* 17 | 18 | # OS 19 | .DS_Store 20 | 21 | # Tests 22 | /coverage 23 | /.nyc_output 24 | 25 | # IDEs and editors 26 | /.idea 27 | .project 28 | .classpath 29 | .c9/ 30 | *.launch 31 | .settings/ 32 | *.sublime-workspace 33 | 34 | # IDE - VSCode 35 | .vscode/* 36 | !.vscode/settings.json 37 | !.vscode/tasks.json 38 | !.vscode/launch.json 39 | !.vscode/extensions.json 40 | 41 | # dotenv environment variable files 42 | .env 43 | .env.development.local 44 | .env.test.local 45 | .env.production.local 46 | .env.local 47 | 48 | # temp directory 49 | .temp 50 | .tmp 51 | 52 | # Runtime data 53 | pids 54 | *.pid 55 | *.seed 56 | *.pid.lock 57 | 58 | # Diagnostic reports (https://nodejs.org/api/report.html) 59 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 60 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import mongoose from "mongoose"; 3 | import dotenv from "dotenv"; 4 | import cors from "cors"; 5 | import path from "path"; 6 | import { fileURLToPath } from "url"; 7 | import getPort from "get-port"; 8 | 9 | import RootRoutes from "./routes/root.routes.js"; 10 | 11 | // .env faylini yuklash 12 | dotenv.config(); 13 | 14 | // Fayl va papka yo‘lini aniqlash 15 | const __filename = fileURLToPath(import.meta.url); 16 | const __dirname = path.dirname(__filename); 17 | 18 | const app = express(); 19 | const DEFAULT_PORT = parseInt(process.env.PORT) || 3000; 20 | const MONGODB_URI = process.env.MONGODB_URI; 21 | 22 | // Middleware’lar 23 | app.use(cors()); 24 | app.use(express.json()); 25 | 26 | // Yuklangan fayllarni servis qilish 27 | app.use("/uploads", express.static(path.resolve(__dirname, "uploads"))); 28 | 29 | // Test uchun oddiy route 30 | app.get("/", (_, res) => res.send("Salom, dunyo!")); 31 | 32 | // API route’lar 33 | app.use("/api", RootRoutes); 34 | 35 | // Serverni ishga tushuruvchi funksiyasi 36 | const startServer = async () => { 37 | if (!MONGODB_URI) { 38 | console.error("❌ MongoDB URI .env faylida ko‘rsatilmagan."); 39 | process.exit(1); 40 | } 41 | 42 | try { 43 | await mongoose.connect(MONGODB_URI); 44 | console.log("✅ MongoDB bilan muvaffaqiyatli ulanildi."); 45 | 46 | const availablePort = await getPort({ port: DEFAULT_PORT }); 47 | 48 | app.listen(availablePort, () => { 49 | console.log(`🚀 Server ishga tushdi: http://localhost:${availablePort}`); 50 | if (availablePort !== DEFAULT_PORT) { 51 | console.log( 52 | `ℹ️ ${DEFAULT_PORT}-port band edi. ${availablePort}-port tanlandi.` 53 | ); 54 | } 55 | }); 56 | } catch (error) { 57 | console.error("❌ Serverni ishga tushirishda xatolik:", error.message); 58 | process.exit(1); 59 | } 60 | }; 61 | 62 | startServer(); 63 | -------------------------------------------------------------------------------- /middlewares/isAuth.js: -------------------------------------------------------------------------------- 1 | import jwt from "jsonwebtoken"; 2 | import Admin from "../models/admin.js"; 3 | 4 | // Foydalanuvchi tizimga kirganini tekshiruvchi oddiy middleware 5 | const checkAuth = async (req, res, next) => { 6 | try { 7 | // So‘rov sarlavhasidan tokenni olish 8 | const authHeader = req.headers.authorization; 9 | const token = 10 | authHeader && authHeader.startsWith("Bearer ") 11 | ? authHeader.slice(7) 12 | : authHeader; 13 | 14 | // Agar token taqdim etilmagan bo‘lsa 15 | if (!token) { 16 | return res.status(401).json({ 17 | success: false, 18 | message: 19 | "Ruxsat berilmadi. Token mavjud emas. Iltimos, avval tizimga kiring.", 20 | }); 21 | } 22 | 23 | // Tokenni tekshirish 24 | const decoded = jwt.verify(token, process.env.JWT_SECRET); 25 | 26 | // Admin foydalanuvchini topish 27 | const admin = await Admin.findById(decoded.userId).select("-password"); 28 | if (!admin) { 29 | return res.status(401).json({ 30 | success: false, 31 | message: "Noto‘g‘ri token. Foydalanuvchi topilmadi.", 32 | }); 33 | } 34 | 35 | // Foydalanuvchi ma’lumotlarini so‘rovga biriktirish, boshqa funksiyalar foydalanishi uchun 36 | req.user = admin; 37 | req.userId = admin._id; 38 | 39 | // Keyingi funksiyaga o‘tish 40 | next(); 41 | } catch (error) { 42 | console.log("Autentifikatsiya xatosi:", error.message); 43 | 44 | if (error.name === "JsonWebTokenError") { 45 | return res.status(401).json({ 46 | success: false, 47 | message: "Token formati noto‘g‘ri.", 48 | }); 49 | } 50 | 51 | if (error.name === "TokenExpiredError") { 52 | return res.status(401).json({ 53 | success: false, 54 | message: "Token muddati tugagan. Iltimos, qayta tizimga kiring.", 55 | }); 56 | } 57 | 58 | return res.status(401).json({ 59 | success: false, 60 | message: "Autentifikatsiya muvaffaqiyatsiz tugadi.", 61 | }); 62 | } 63 | }; 64 | 65 | export default checkAuth; 66 | -------------------------------------------------------------------------------- /controllers/admin.controller.js: -------------------------------------------------------------------------------- 1 | import bcrypt from "bcrypt"; 2 | import Admin from "../models/admin.js"; 3 | 4 | // Barcha adminlarni olish 5 | export const getAllAdmins = async (_, res) => { 6 | try { 7 | const admins = await Admin.find().select("-password"); 8 | res.json(admins); 9 | } catch (error) { 10 | res.status(500).json({ message: error.message }); 11 | } 12 | }; 13 | 14 | // Bitta adminni ID bo‘yicha olish 15 | export const getAdmin = async (req, res) => { 16 | try { 17 | const admin = await Admin.findById(req.params.id).select("-password"); 18 | if (!admin) 19 | return res.status(404).json({ message: "Administrator topilmadi" }); 20 | 21 | res.json(admin); 22 | } catch (error) { 23 | res.status(500).json({ message: error.message }); 24 | } 25 | }; 26 | 27 | // Admin ma'lumotlarini yangilash 28 | export const updateAdmin = async (req, res) => { 29 | try { 30 | const { fullName, phoneNumber, password } = req.body; 31 | 32 | const existingUser = await Admin.findOne({ phoneNumber }); 33 | if (!existingUser) 34 | return res.status(400).json({ message: "Administrator topilmadi" }); 35 | 36 | const salt = await bcrypt.genSalt(10); 37 | const hashedPassword = await bcrypt.hash(password, salt); 38 | 39 | const updatedAdmin = await Admin.findByIdAndUpdate( 40 | req.params.id, 41 | { fullName, phoneNumber, password: hashedPassword }, 42 | { new: true } 43 | ).select("-password"); 44 | 45 | res.json(updatedAdmin); 46 | } catch (error) { 47 | res.status(500).json({ message: error.message }); 48 | } 49 | }; 50 | 51 | // Adminni o‘chirish 52 | export const deleteAdmin = async (req, res) => { 53 | try { 54 | await Admin.findByIdAndDelete(req.params.id); 55 | res.json({ message: "Administrator o‘chirildi" }); 56 | } catch (error) { 57 | res.status(500).json({ message: error.message }); 58 | } 59 | }; 60 | 61 | // Tizimga kirgan foydalanuvchi (admin) ma'lumotlarini olish 62 | export const getUser = async (req, res) => { 63 | try { 64 | const foundAdmin = await Admin.findById(req.userId); 65 | if (!foundAdmin) 66 | return res.status(404).json({ message: "Administrator topilmadi" }); 67 | 68 | return res.status(200).json(foundAdmin); 69 | } catch (error) { 70 | res.status(500).json({ error: error.message }); 71 | } 72 | }; 73 | -------------------------------------------------------------------------------- /controllers/auth.controller.js: -------------------------------------------------------------------------------- 1 | import bcrypt from "bcrypt"; 2 | import jwt from "jsonwebtoken"; 3 | import Admin from "../models/admin.js"; 4 | 5 | export const register = async (req, res) => { 6 | const { fullName, phoneNumber, password } = req.body; 7 | 8 | try { 9 | if (!phoneNumber || !fullName || !password) { 10 | return res 11 | .status(409) 12 | .json({ message: "Barcha maydonlarni to'ldiring." }); 13 | } 14 | const existingUser = await Admin.findOne({ phoneNumber }); 15 | if (existingUser) 16 | return res.status(400).json({ 17 | message: "Bunday telefon raqam bilan oldin ro'yhatdan o'tilgan.", 18 | }); 19 | 20 | const salt = await bcrypt.genSalt(10); 21 | const hashedPassword = await bcrypt.hash(password, salt); 22 | 23 | const newAdmin = new Admin({ 24 | fullName, 25 | phoneNumber, 26 | password: hashedPassword, 27 | }); 28 | await newAdmin.save(); 29 | 30 | res.status(201).json({ message: "Yangi admin ro'yhatdan o'tdi." }); 31 | } catch (error) { 32 | res.status(500).json({ message: error.message }); 33 | } 34 | }; 35 | 36 | export const login = async (req, res) => { 37 | const { phoneNumber, password } = req.body; 38 | 39 | try { 40 | const admin = await Admin.findOne({ phoneNumber }); 41 | if (!admin) return res.status(404).json({ message: "Admin topilmadi." }); 42 | 43 | const isMatch = await bcrypt.compare(password, admin.password); 44 | if (!isMatch) 45 | return res 46 | .status(400) 47 | .json({ message: "Noto'g'ri parol yoki telefon raqam." }); 48 | 49 | const token = jwt.sign({ userId: admin._id }, process.env.JWT_SECRET, { 50 | expiresIn: "30d", 51 | }); 52 | 53 | res.json({ token, admin }); 54 | } catch (error) { 55 | res.status(500).json({ message: error.message }); 56 | } 57 | }; 58 | 59 | // admin parolini yangilash 60 | export const changePassword = async (req, res) => { 61 | try { 62 | const { currentPassword, newPassword } = req.body; 63 | 64 | // Maydonlar to‘ldirilganligini tekshirish 65 | if (!currentPassword || !newPassword) { 66 | return res.status(400).json({ 67 | success: false, 68 | message: "Iltimos, joriy va yangi parolni kiriting", 69 | }); 70 | } 71 | 72 | if (newPassword.length < 6) { 73 | return res.status(400).json({ 74 | success: false, 75 | message: "Yangi parol kamida 6 ta belgidan iborat bo‘lishi kerak", 76 | }); 77 | } 78 | 79 | // Adminni paroli bilan birga olish 80 | const admin = await Admin.findById(req.userId); 81 | 82 | // Joriy parolni tekshirish 83 | const isCurrentPasswordCorrect = await bcrypt.compare( 84 | currentPassword, 85 | admin.password 86 | ); 87 | if (!isCurrentPasswordCorrect) { 88 | return res.status(400).json({ 89 | success: false, 90 | message: "Joriy parol noto‘g‘ri", 91 | }); 92 | } 93 | 94 | // Yangi parolni hash qilish 95 | const hashedNewPassword = await bcrypt.hash(newPassword, 10); 96 | 97 | // Parolni yangilash 98 | admin.password = hashedNewPassword; 99 | await admin.save(); 100 | 101 | res.json({ 102 | success: true, 103 | message: "Parol muvaffaqiyatli o‘zgartirildi", 104 | }); 105 | } catch (error) { 106 | console.log("Parolni o‘zgartirishda xatolik:", error.message); 107 | res.status(500).json({ 108 | success: false, 109 | message: "Parolni o‘zgartirishda xatolik yuz berdi", 110 | }); 111 | } 112 | }; -------------------------------------------------------------------------------- /controllers/trainer.controller.js: -------------------------------------------------------------------------------- 1 | import Trainer from "../models/trainer.js"; 2 | import { upload } from "../middlewares/Uploader.js"; 3 | import fs from "fs"; 4 | import path from "path"; 5 | import { fileURLToPath } from "url"; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = path.dirname(__filename); 9 | 10 | // Barcha trenerlarni olish 11 | export const getAllTrainers = async (_, res) => { 12 | try { 13 | const trainers = await Trainer.find(); 14 | res.status(200).json(trainers); 15 | } catch (error) { 16 | res.status(500).json({ message: "Server xatosi", error: error.message }); 17 | } 18 | }; 19 | 20 | // Trenerni ID orqali olish 21 | export const getTrainerById = async (req, res) => { 22 | try { 23 | const trainer = await Trainer.findById(req.params.id); 24 | if (!trainer) { 25 | return res.status(404).json({ message: "Trener topilmadi" }); 26 | } 27 | res.status(200).json(trainer); 28 | } catch (error) { 29 | res.status(500).json({ message: "Server xatosi", error: error.message }); 30 | } 31 | }; 32 | 33 | // Yangi trener yaratish 34 | export const createTrainer = async (req, res) => { 35 | try { 36 | upload.single("photo")(req, res, async (err) => { 37 | if (err) return res.status(400).json({ message: err.message }); 38 | 39 | const { fullName, experience, level, students } = req.body; 40 | if (!fullName || !level || !students) { 41 | return res 42 | .status(400) 43 | .json({ message: "Barcha maydonlarni to‘ldirish majburiy" }); 44 | } 45 | 46 | const photo = req.file 47 | ? `${req.protocol}://${req.get("host")}/uploads/${req.file.filename}` 48 | : null; 49 | 50 | const newTrainer = new Trainer({ 51 | fullName, 52 | photo, 53 | experience, 54 | level, 55 | students, 56 | }); 57 | 58 | await newTrainer.save(); 59 | res.status(201).json(newTrainer); 60 | }); 61 | } catch (error) { 62 | res.status(500).json({ 63 | message: "Trenerni yaratishda xatolik yuz berdi", 64 | error: error.message, 65 | }); 66 | } 67 | }; 68 | 69 | // Trenerni yangilash 70 | export const updateTrainer = async (req, res) => { 71 | try { 72 | upload.single("photo")(req, res, async (err) => { 73 | if (err) return res.status(400).json({ message: err.message }); 74 | 75 | const { fullName, experience, level, students } = req.body; 76 | 77 | const updateData = { 78 | fullName, 79 | experience, 80 | level, 81 | students, 82 | }; 83 | 84 | if (req.file) { 85 | updateData.photo = `${req.protocol}://${req.get("host")}/uploads/${ 86 | req.file.filename 87 | }`; 88 | } 89 | 90 | const updatedTrainer = await Trainer.findByIdAndUpdate( 91 | req.params.id, 92 | updateData, 93 | { 94 | new: true, 95 | runValidators: true, 96 | } 97 | ); 98 | 99 | if (!updatedTrainer) { 100 | return res.status(404).json({ message: "Trener topilmadi" }); 101 | } 102 | 103 | res.status(200).json(updatedTrainer); 104 | }); 105 | } catch (error) { 106 | res.status(500).json({ 107 | message: "Trenerni yangilashda xatolik yuz berdi", 108 | error: error.message, 109 | }); 110 | } 111 | }; 112 | 113 | // Trenerni o‘chirish 114 | export const deleteTrainer = async (req, res) => { 115 | try { 116 | const trainer = await Trainer.findById(req.params.id); 117 | if (!trainer) { 118 | return res.status(404).json({ message: "Trener topilmadi" }); 119 | } 120 | 121 | if (trainer.photo) { 122 | const slicedPhoto = trainer.photo.slice(30); 123 | const filePath = path.join(__dirname, "..", "uploads", slicedPhoto); 124 | try { 125 | if (fs.existsSync(filePath)) { 126 | fs.unlinkSync(filePath); 127 | } else { 128 | console.warn(`Fayl topilmadi: ${filePath}`); 129 | } 130 | } catch (err) { 131 | console.error(`Rasmni o‘chirishda xatolik: ${filePath}`, err); 132 | } 133 | } 134 | 135 | const deletedTrainer = await Trainer.findByIdAndDelete(req.params.id); 136 | 137 | res.status(200).json({ message: "Trener o‘chirildi", deletedTrainer }); 138 | } catch (error) { 139 | res.status(500).json({ 140 | message: "Trenerni o‘chirishda xatolik yuz berdi", 141 | error: error.message, 142 | }); 143 | } 144 | }; 145 | -------------------------------------------------------------------------------- /controllers/blog.controller.js: -------------------------------------------------------------------------------- 1 | import Blog from "../models/blog.js"; 2 | import { upload } from "../middlewares/Uploader.js"; 3 | import fs from "fs"; 4 | import path from "path"; 5 | import { fileURLToPath } from "url"; 6 | 7 | const __filename = fileURLToPath(import.meta.url); 8 | const __dirname = path.dirname(__filename); 9 | 10 | // Barcha bloglarni olish 11 | export const getAllBlogs = async (req, res) => { 12 | try { 13 | const { title } = req.query; 14 | const query = {}; 15 | if (title) query.title = { $regex: title, $options: "i" }; 16 | const blogs = await Blog.find(query); 17 | res.status(200).json(blogs); 18 | } catch (error) { 19 | res.status(500).json({ message: "Server xatosi", error: error.message }); 20 | } 21 | }; 22 | 23 | // Blogni ID orqali olish 24 | export const getBlogById = async (req, res) => { 25 | try { 26 | const blog = await Blog.findById(req.params.id); 27 | if (!blog) { 28 | return res.status(404).json({ message: "Blog topilmadi" }); 29 | } 30 | res.status(200).json(blog); 31 | } catch (error) { 32 | res.status(500).json({ message: "Server xatosi", error: error.message }); 33 | } 34 | }; 35 | 36 | // Yangi blog yaratish 37 | export const createBlog = async (req, res) => { 38 | try { 39 | upload.array("photos")(req, res, async (err) => { 40 | if (err) return res.status(400).json({ message: err.message }); 41 | 42 | const { title, description } = req.body; 43 | if (!title || !description) { 44 | return res 45 | .status(400) 46 | .json({ message: "Barcha maydonlar to‘ldirilishi shart" }); 47 | } 48 | 49 | const photos = req.files.map( 50 | (file) => 51 | `${req.protocol}://${req.get("host")}/uploads/${file.filename}` 52 | ); 53 | 54 | const newBlog = new Blog({ 55 | title, 56 | photos, 57 | description, 58 | }); 59 | 60 | await newBlog.save(); 61 | res.status(201).json(newBlog); 62 | }); 63 | } catch (error) { 64 | res.status(500).json({ 65 | message: "Blog yaratishda xatolik yuz berdi", 66 | error: error.message, 67 | }); 68 | } 69 | }; 70 | 71 | // Blogni yangilash 72 | export const updateBlog = async (req, res) => { 73 | try { 74 | upload.array("photos")(req, res, async (err) => { 75 | if (err) return res.status(400).json({ message: err.message }); 76 | 77 | const { title, description } = req.body; 78 | 79 | const updateData = { title, description }; 80 | 81 | if (req.files && req.files.length > 0) { 82 | updateData.photos = req.files.map( 83 | (file) => 84 | `${req.protocol}://${req.get("host")}/uploads/${file.filename}` 85 | ); 86 | } 87 | 88 | const updatedBlog = await Blog.findByIdAndUpdate( 89 | req.params.id, 90 | updateData, 91 | { 92 | new: true, 93 | runValidators: true, 94 | } 95 | ); 96 | 97 | if (!updatedBlog) { 98 | return res.status(404).json({ message: "Blog topilmadi" }); 99 | } 100 | 101 | res.status(200).json(updatedBlog); 102 | }); 103 | } catch (error) { 104 | res.status(500).json({ 105 | message: "Blog yangilashda xatolik yuz berdi", 106 | error: error.message, 107 | }); 108 | } 109 | }; 110 | 111 | // Blogni o‘chirish 112 | export const deleteBlog = async (req, res) => { 113 | try { 114 | const blog = await Blog.findById(req.params.id); 115 | if (!blog) { 116 | return res.status(404).json({ message: "Blog topilmadi" }); 117 | } 118 | 119 | if (blog.photos && blog.photos.length > 0) { 120 | blog.photos.forEach((photo) => { 121 | const slicedImage = photo.slice(30); 122 | const filePath = path.join(__dirname, "..", "uploads", slicedImage); 123 | try { 124 | if (fs.existsSync(filePath)) { 125 | fs.unlinkSync(filePath); 126 | } else { 127 | console.warn(`Fayl topilmadi: ${filePath}`); 128 | } 129 | } catch (err) { 130 | console.error(`Rasmni o‘chirishda xatolik: ${filePath}`, err); 131 | } 132 | }); 133 | } 134 | 135 | const deletedBlog = await Blog.findByIdAndDelete(req.params.id); 136 | 137 | res.status(200).json({ message: "Blog o‘chirildi", deletedBlog }); 138 | } catch (error) { 139 | res.status(500).json({ 140 | message: "Blogni o‘chirishda xatolik yuz berdi", 141 | error: error.message, 142 | }); 143 | } 144 | }; 145 | --------------------------------------------------------------------------------