Skip to content

Drones - e-shop with drones and thermal imagers - Backend

Notifications You must be signed in to change notification settings

JuliaOvcharenko/Drones

Repository files navigation

Project "Drones - e-shop with drones and thermal imagers - Backend" | Проєкт "Drones - онлайн магазин з дронами та тепловізорами - Backend."

Node.js Version TypeScript Version Express Version Backend API Architecture Architecture_BFF Architecture_SRV Architecture_API

Навігація | Navigation on README:

Структура | Structure of the project


Архітектура | Architecture

У проєкті використовуються модульна(module architecture) та шарована(Layered architecture) архітектури.

  • Модульна архітектура — це підхід, за якого складну систему поділяють на невеликі, незалежні та легко замінні модулі. Кожен модуль відповідає за свою окрему частину функціональності, що спрощує розробку, тестування та подальшу підтримку проєкту.

  • Шарована архітектура — це спосіб організації застосунку, коли його логіка розбивається на кілька рівнів (шарів). Кожен шар виконує свою чітку роль, а взаємодія між ними відбувається послідовно. Такий підхід забезпечує структурованість, зрозумілість коду та зручність у масштабуванні.


The project uses both modular architecture and layered architecture.

  • Modular architecture is an approach where a complex system is divided into small, independent, and easily replaceable modules. Each module is responsible for its own part of the functionality, which makes development, testing, and further maintenance simpler.

  • Layered architecture is a way of organizing an application by splitting its logic into several levels (layers). Each layer has its own role, and they interact with each other step by step. This approach makes the code more structured, clear, and easier to scale.


Backend:

  • Node.js.
  • Express.
  • TypeScript.

Database:

  • Prisma ORM — це ORM, що допомагає читати, записувати й змінювати дані без складного SQL.
  • У проєкті використовується реляційна базаданих sqlite.

  • Prisma ORM is a tool that helps read, write, and update data without complex SQL.
  • The project uses the relational database SQLite.

ERD(Entity Relationship Diagram)

Стиль написання коду | Code writing style

Команда дотримується таких правил написання коду:

  • Файли, що належать до шарованої архітектури, іменуються за принципом назва.шар.ts (наприклад: user.service.ts, order.controller.ts).

  • Для відступів використовується один Tab (4 пробіли).

  • У проєкті використовуємо prisma studio.


The team follows these coding rules:

  • Files that belong to the layered architecture are named using the pattern name.layer.ts (for example: user.service.ts, order.controller.ts).

  • One tab (four spaces) is used for indentation.

  • In project we use the prisma studio.

Деталі роботи у команді | Details of teamwork


API Документація | API Documentation

📁 user

Рєєстрація користувача. | User register.

  POST /users/register
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request
409 Conflict конфлікт даних conflict
500 Internal Server Error внутрішня помилка сервера internal server error

Приклад даних для надсилання | Example of data to send
  {
    "name": "user",
    "email": "email@gmail.com",
    "password": "123",
    "passwordConfirm": "123"
  }

Відповідь | Responce
  {
    "message": "User Creared. Please, login"
  }

Логін користувача. | User login. | JWT REQUIRED

  POST /users/login
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request
404 Not Found користувача не знайдено not found
500 Internal Server Error внутрішня помилка сервера internal server error

Приклад даних для надсилання | Example of data to send
  {
    "email": "email@gmail.com",
    "password": "123"
  }

Відповідь | Responce
  {
  "token": "login token (example)"
  }

Особистий кабінет. | Personal account.

  GET /users/me
Code Status Українською English
200 OK успішно success
401 Unauthorized неавторизований unauthorized
404 Not Found користувача не знайдено not found
500 Internal Server Error внутрішня помилка сервера internal server error

Приклад даних для надсилання | Example of data to send
  • Дотримуйтесь інструкцій. | Follow the instructions.
  1. Перейдіть на вкладку Authorization. | Go to the Authorization tab.
  2. У полі Type оберіть Bearer Token. | Type → Bearer Token
  3. У поле Token вставте ваш токен. | In the Token field, paste your JWT token.
  "login token (example)"

Відповідь | Responce
  {
    "id": 1,
    "username": "user",
    "lastname": "",
    "patronymic": "",
    "email": "email@gmail.com",
    "birthDate": "2025-12-22T21:32:43.291Z",
    "phoneNumber": "",
    "addressId": null
  }

Редагування профілю користувача. | User profile update.

  PATCH /users/:userId
Code Status Українською English
200 OK успішно success
404 Not Found користувача не знайдено not found
422 Unprocessable Content сутність не підлягає обробці unprocessable сontent
500 Internal Server Error внутрішня помилка сервера internal server error

Приклад даних для надсилання | Example of data to send
  {
    "username": "user2",
    "patronymic": "UserIser",
    "email": "email2@gmail.com",
    "phoneNumber": "+000 000 000",
  }

Відповідь | Responce
  {
    "id": 12,
    "username": "user2",
    "lastname": "",
    "patronymic": "UserIser",
    "email": "email5hhvjhvy67@gmail.com",
    "birthDate": "2025-12-23T19:27:32.368Z",
    "phoneNumber": "+000 000 000",
    "addressId": null
  }

Створення власної адреси. | Creating your own address.

  POST /users/address
Code Status Українською English
201 Created створено created
422 Unprocessable Content сутність не підлягає обробці unprocessable сontent
500 Internal Server Error внутрішня помилка сервера internal server error

Приклад даних для надсилання | Example of data to send
  {
    "city": "Dnipro",
    "entrance": "second entrance",
    "flat": "12777",
    "house": "435",
    "street": "Pr.Catovsky 4"
  }

Відповідь | Responce
  {
    "id": 1,
    "city": "Dnipro",
    "street": "Pr.Catovsky 4",
    "house": "435",
    "flat": "12777",
    "entrance": "second entrance"
  }

Редагування адреси. | Address update.

  PATCH /users/address/:addressId
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request
404 Not Found адреси не знайдено not found
422 Unprocessable Content сутність не підлягає обробці unprocessable сontent
500 Internal Server Error внутрішня помилка сервера internal server error

Приклад даних для надсилання | Example of data to send
  {
    "city": "Dnipro",
    "entrance": "1",
    "flat": "6",
    "house": "5",
    "street": "Pr.Catovsky"
  }

Відповідь | Responce
  "Address updated successfully"

Видалення адреси. | Address delete.

  DELETE /users/address/:addressId
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request
404 Not Found адреси не знайдено not found
500 Internal Server Error внутрішня помилка сервера internal server error

Відповідь | Responce
  "Address deleted successfully"

Отримати усі адреси. | Get all addresses.

  GET /users/addresses
Code Error Українською English
200 OK адреси отримано items received
500 Internal Server Error помилка сервера server error

Відповідь | Responce
  [
    {
        "id": 3,
        "city": "Dnipro",
        "street": "Pr.Catovsky",
        "house": "1",
        "flat": "12",
        "entrance": "7"
    },
    {
        "id": 17,
        "city": "Dnipro",
        "street": "Pr.Catovsky 4",
        "house": "435",
        "flat": "12777",
        "entrance": "second entrance"
    },
    {
        "id": 18,
        "city": "Dnipro",
        "street": "Pr.Catovsky 4",
        "house": "435",
        "flat": "12777",
        "entrance": "second entrance"
    }
  ]

Редагування паролю - відправка коду на email. | Password editing - sending code to email.

  POST /users/password/recover
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request

Приклад даних для надсилання | Example of data to send
  {
    "email": "email@gmail.com",
  }

Відповідь | Responce
  "Email was sended"

Редагування паролю - змінення за допомогою коду. | Edit password - change using code.

  POST /users/password/reset
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request

Приклад даних для надсилання | Example of data to send
  {
    "email": "email@gmail.com",
    "code": "1213",
    "newPassword": "12345678"
  }

Відповідь | Responce
  "Password successfully changed"

📁 product

Отримати усі продукти. | Get all products.

  GET /products
Code Error Українською English
200 OK товари отримано items received
500 Internal Server Error помилка сервера server error

Відповідь | Responce
  [
    {
        "id": 1,
        "name": "Drone1",
        "price": 1000,
        "discount": 10,
        "countOfProduct": 2,
        "categoryId": 1,
        "infoBlocks": [
            {
                "id": 1,
                "blockOrder": 1,
                "align": "center",
                "title": "drone 1",
                "content": "drone max super",
                "productId": 1
            }
        ]
    },
    {
        "id": 2,
        "name": "thermal imager 1",
        "price": 100000,
        "discount": 100,
        "countOfProduct": 6,
        "categoryId": 2,
        "infoBlocks": [
            {
                "id": 2,
                "blockOrder": 3,
                "align": "start",
                "title": "imager",
                "content": "imager thermal",
                "productId": 2
            }
        ]
    }
]

Query Params:

  • categoryName

      GET /products?categoryName=Drones
    Відповідь | Responce
      [
        {
            "id": 1,
            "name": "Drone1",
            "price": 1000,
            "discount": 10,
            "countOfProduct": 2,
            "categoryId": 1,
            "infoBlocks": [
                {
                    "id": 1,
                    "blockOrder": 1,
                    "align": "center",
                    "title": "drone 1",
                    "content": "drone max super",
                    "productId": 1
                }
            ]
        },
        {
            "id": 4,
            "name": "Drone2",
            "price": 29543330,
            "discount": 10,
            "countOfProduct": 1,
            "categoryId": 1,
            "infoBlocks": [
                {
                    "id": 1,
                    "blockOrder": 1,
                    "align": "center",
                    "title": "drone 1",
                    "content": "drone max super",
                    "productId": 4
                }
            ]
        }
    ]

Отримати конкретний продукт. | Get product by id.

  GET /products/:id
Code Error Українською English
200 OK товар знайдено і отримано item found and received
400 Bad Request неправильний формат id wrong ID format
404 Not Found товар з таким id не знайдено item with this ID not found
Відповідь | Responce
  [
    {
    "id": 1,
    "name": "Drone1",
    "price": 1000,
    "discount": 10,
    "countOfProduct": 2,
    "categoryId": 1,
    "infoBlocks": [
      {
        "id": 1,
        "blockOrder": 1,
        "align": "center",
        "title": "drone 1",
        "content": "drone max super",
        "productId": 1
      }
    ],
    "mainImage": {
      "id": 1,
      "image": "image 1",
      "productId": 1
      }
    }
  ]

Отримати пропозиційні продукти. Працює тільки з query-params | Get suggestion products. Work only with query-params

  GET /products/suggestions/isNew=true
  GET /products/suggestions/popularity=true
  GET /products/suggestions/sameAs=product_id
  GET /products/suggestions?sameAs=product_id&limit=limit_number
Code Error Українською English
200 OK товари знайдено і отримано items found and received
400 Bad Request неправильний формат wrong format
Відповідь | Responce
Відповідь - isNew | Responce - isNew
  [
      {
          "id": 2,
          "name": "Apple",
          "price": 10,
          "discount": 0,
          "countOfProduct": 200,
          "categoryId": 2,
          "createdAt": "2026-11-30T16:33:08.000Z",
          "mainImage": null
      },
      {
          "id": 5,
          "name": "Orange",
          "price": 10,
          "discount": 0,
          "countOfProduct": 5,
          "categoryId": 2,
          "createdAt": "2026-01-19T14:16:38.529Z",
          "mainImage": {
              "id": 1,
              "image": "image 1",
              "productId": 5
          }
      },
      {
          "id": 3,
          "name": "thermal imager 1",
          "price": 100000,
          "discount": 100,
          "countOfProduct": 6,
          "categoryId": 3,
          "createdAt": "2025-04-18T20:41:19.000Z",
          "mainImage": {
              "id": 2,
              "image": "image 2",
              "productId": 3
          }
      }
    ]
Відповідь - popularity | Responce - popularity
  [
    {
        "id": 4,
        "name": "Drone2",
        "price": 29543330,
        "discount": 10,
        "countOfProduct": 1,
        "categoryId": 1,
        "createdAt": "2024-09-01T06:50:00.000Z",
        "category": {
            "id": 1,
            "name": "Drones",
            "image": "DronesImage",
            "orderId": 4
        },
        "mainImage": null
    },
    {
        "id": 1,
        "name": "Drone1",
        "price": 1000,
        "discount": 10,
        "countOfProduct": 2,
        "categoryId": 1,
        "createdAt": "2023-01-15T10:24:00.000Z",
        "category": {
            "id": 1,
            "name": "Drones",
            "image": "DronesImage",
            "orderId": 4
        },
        "mainImage": {
            "id": 1,
            "image": "image 1",
            "productId": 1
        }
    }
  ]
Відповідь - sameAs | Responce - sameAs
  [
  {
      "id": 1,
      "name": "DJI Mini 4K",
      "price": 299,
      "discount": 0,
      "description": "Compact drone for beginners",
      "countOfProduct": 50,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.009Z",
      "mainImage": {
          "id": 1,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 1
      },
      "infoBlocks": []
  },
  {
      "id": 2,
      "name": "DJI Air 3",
      "price": 1099,
      "discount": 100,
      "description": "Dual camera power",
      "countOfProduct": 20,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.013Z",
      "mainImage": {
          "id": 2,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 2
      },
      "infoBlocks": []
  },
  {
      "id": 3,
      "name": "DJI Mavic 3",
      "price": 2199,
      "discount": 0,
      "description": "Flagship camera drone",
      "countOfProduct": 10,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.017Z",
      "mainImage": {
          "id": 3,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 3
      },
      "infoBlocks": []
  },
  {
      "id": 1,
      "name": "DJI Mini 4K",
      "price": 299,
      "discount": 0,
      "description": "Compact drone for beginners",
      "countOfProduct": 50,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.009Z",
      "mainImage": {
          "id": 1,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 1
      },
      "infoBlocks": []
  },
  {
      "id": 3,
      "name": "DJI Mavic 3",
      "price": 2199,
      "discount": 0,
      "description": "Flagship camera drone",
      "countOfProduct": 10,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.017Z",
      "mainImage": {
          "id": 3,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 3
      },
      "infoBlocks": []
  },
  {
      "id": 6,
      "name": "Test Drone Model #3",
      "price": 130,
      "discount": 0,
      "description": "This is a generated test drone number 3 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.028Z",
      "mainImage": {
          "id": 6,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 6
      },
      "infoBlocks": []
  },
  {
      "id": 9,
      "name": "Test Drone Model #6",
      "price": 160,
      "discount": 0,
      "description": "This is a generated test drone number 6 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.039Z",
      "mainImage": {
          "id": 9,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 9
      },
      "infoBlocks": []
  },
  {
      "id": 12,
      "name": "Test Drone Model #9",
      "price": 190,
      "discount": 0,
      "description": "This is a generated test drone number 9 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.048Z",
      "mainImage": {
          "id": 12,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 12
      },
      "infoBlocks": []
  },
  {
      "id": 15,
      "name": "Test Drone Model #12",
      "price": 220,
      "discount": 0,
      "description": "This is a generated test drone number 12 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.056Z",
      "mainImage": {
          "id": 15,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 15
      },
      "infoBlocks": []
  },
  {
      "id": 18,
      "name": "Test Drone Model #15",
      "price": 250,
      "discount": 50,
      "description": "This is a generated test drone number 15 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.065Z",
      "mainImage": {
          "id": 18,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 18
      },
      "infoBlocks": []
  },
  {
      "id": 21,
      "name": "Test Drone Model #18",
      "price": 280,
      "discount": 0,
      "description": "This is a generated test drone number 18 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.074Z",
      "mainImage": {
          "id": 21,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 21
      },
      "infoBlocks": []
  },
  {
      "id": 24,
      "name": "Test Drone Model #21",
      "price": 310,
      "discount": 0,
      "description": "This is a generated test drone number 21 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.082Z",
      "mainImage": {
          "id": 24,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 24
      },
      "infoBlocks": []
  },
  {
      "id": 27,
      "name": "Test Drone Model #24",
      "price": 340,
      "discount": 0,
      "description": "This is a generated test drone number 24 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.088Z",
      "mainImage": {
          "id": 27,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 27
      },
      "infoBlocks": []
  },
  {
      "id": 30,
      "name": "Test Drone Model #27",
      "price": 370,
      "discount": 0,
      "description": "This is a generated test drone number 27 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.097Z",
      "mainImage": {
          "id": 30,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 30
      },
      "infoBlocks": []
  },
  {
      "id": 33,
      "name": "Test Drone Model #30",
      "price": 400,
      "discount": 50,
      "description": "This is a generated test drone number 30 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 1,
      "createdAt": "2026-02-04T13:07:23.107Z",
      "mainImage": {
          "id": 33,
          "image": "http://localhost:8000/uploads/drone1.png",
          "productId": 33
      },
      "infoBlocks": []
  },
  {
      "id": 13,
      "name": "Test Drone Model #10",
      "price": 200,
      "discount": 50,
      "description": "This is a generated test drone number 10 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.050Z",
      "mainImage": {
          "id": 13,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 13
      },
      "infoBlocks": []
  },
  {
      "id": 14,
      "name": "Test Drone Model #11",
      "price": 210,
      "discount": 0,
      "description": "This is a generated test drone number 11 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.053Z",
      "mainImage": {
          "id": 14,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 14
      },
      "infoBlocks": []
  },
  {
      "id": 16,
      "name": "Test Drone Model #13",
      "price": 230,
      "discount": 0,
      "description": "This is a generated test drone number 13 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.059Z",
      "mainImage": {
          "id": 16,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 16
      },
      "infoBlocks": []
  },
  {
      "id": 17,
      "name": "Test Drone Model #14",
      "price": 240,
      "discount": 0,
      "description": "This is a generated test drone number 14 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.062Z",
      "mainImage": {
          "id": 17,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 17
      },
      "infoBlocks": []
  },
  {
      "id": 19,
      "name": "Test Drone Model #16",
      "price": 260,
      "discount": 0,
      "description": "This is a generated test drone number 16 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.068Z",
      "mainImage": {
          "id": 19,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 19
      },
      "infoBlocks": []
  },
  {
      "id": 20,
      "name": "Test Drone Model #17",
      "price": 270,
      "discount": 0,
      "description": "This is a generated test drone number 17 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.071Z",
      "mainImage": {
          "id": 20,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 20
      },
      "infoBlocks": []
  },
  {
      "id": 22,
      "name": "Test Drone Model #19",
      "price": 290,
      "discount": 0,
      "description": "This is a generated test drone number 19 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.077Z",
      "mainImage": {
          "id": 22,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 22
      },
      "infoBlocks": []
  },
  {
      "id": 23,
      "name": "Test Drone Model #20",
      "price": 300,
      "discount": 50,
      "description": "This is a generated test drone number 20 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.079Z",
      "mainImage": {
          "id": 23,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 23
      },
      "infoBlocks": []
  },
  {
      "id": 25,
      "name": "Test Drone Model #22",
      "price": 320,
      "discount": 0,
      "description": "This is a generated test drone number 22 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.084Z",
      "mainImage": {
          "id": 25,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 25
      },
      "infoBlocks": []
  },
  {
      "id": 26,
      "name": "Test Drone Model #23",
      "price": 330,
      "discount": 0,
      "description": "This is a generated test drone number 23 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.086Z",
      "mainImage": {
          "id": 26,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 26
      },
      "infoBlocks": []
  },
  {
      "id": 28,
      "name": "Test Drone Model #25",
      "price": 350,
      "discount": 50,
      "description": "This is a generated test drone number 25 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.091Z",
      "mainImage": {
          "id": 28,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 28
      },
      "infoBlocks": []
  },
  {
      "id": 29,
      "name": "Test Drone Model #26",
      "price": 360,
      "discount": 0,
      "description": "This is a generated test drone number 26 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.094Z",
      "mainImage": {
          "id": 29,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 29
      },
      "infoBlocks": []
  },
  {
      "id": 31,
      "name": "Test Drone Model #28",
      "price": 380,
      "discount": 0,
      "description": "This is a generated test drone number 28 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 2,
      "createdAt": "2026-02-04T13:07:23.100Z",
      "mainImage": {
          "id": 31,
          "image": "http://localhost:8000/uploads/drone2.png",
          "productId": 31
      },
      "infoBlocks": []
  },
  {
      "id": 32,
      "name": "Test Drone Model #29",
      "price": 390,
      "discount": 0,
      "description": "This is a generated test drone number 29 for pagination testing.",
      "countOfProduct": 100,
      "categoryId": 3,
      "createdAt": "2026-02-04T13:07:23.104Z",
      "mainImage": {
          "id": 32,
          "image": "http://localhost:8000/uploads/drone3.png",
          "productId": 32
      },
      "infoBlocks": []
  }
]

📁 category

Отримати усі категорії. | Get all categories.

  GET /categories
Code Error Українською English
200 OK категорії отримано items received
500 Internal Server Error помилка сервера server error

Відповідь | Responce
  ```sh
    [
      {
      "id": 1,
      "name": "Drone1",
      "price": 1000,
      "discount": 10,
      "countOfProduct": 2,
      "categoryId": 1,
      "infoBlocks": [
          {
              "id": 1,
              "blockOrder": 1,
              "align": "center",
              "title": "drone 1",
              "content": "drone max super",
              "productId": 1
          }
      ],
      "mainImage": {
          "id": 1,
          "image": "image 1",
          "productId": 1
      }
    }
  ]
  ```
  [
      {
          "id": 1,
          "name": "Drones",
          "image": "DronesImage"
      },
      {
          "id": 2,
          "name": "thermalImager",
          "image": "thermalImagerImage"
      }
  ]

📁 order

Отримати усі замовлення користувача. | Get all user orders.

  GET /orders/
Code Error Українською English
200 OK замовлення отримано items received
500 Internal Server Error помилка сервера server error

Відповідь | Responce
  [
    {
        "id": 1,
        "username": "user1",
        "lastname": "lasname",
        "patronymic": "patro",
        "totalDiscount": 2,
        "payment": "own",
        "trackingNumber": 22,
        "totalPrice": 11,
        "countOfProducts": 8,
        "orderDate": "1970-01-01T00:00:00.000Z",
        "user": {
            "id": 11,
            "username": "user",
            "email": "email4@gmail.com",
            "lastname": "",
            "patronymic": "",
            "birthDate": "2025-12-22T21:32:43.291Z",
            "phoneNumber": ""
        },
        "products": [
            {
                "count_of_product": 78,
                "price": 90,
                "discount": 20,
                "Product": {
                    "category": {
                        "id": 3,
                        "name": "thermalImager",
                        "image": "",
                        "orderId": 3
                    }
                }
            }
        ]
    },
    {
        "id": 2,
        "username": "user2",
        "lastname": "jj",
        "patronymic": "hhhhhhh",
        "totalDiscount": 77777,
        "payment": "hhhhh",
        "trackingNumber": 666,
        "totalPrice": 777,
        "countOfProducts": 7,
        "orderDate": "1970-01-01T00:00:00.000Z",
        "user": {
            "id": 12,
            "username": "user6",
            "email": "email5hhvjhvy67@gmail.com",
            "lastname": "",
            "patronymic": "UserIser",
            "birthDate": "2025-12-23T19:27:32.368Z",
            "phoneNumber": "+000 000 000"
        },
        "products": []
    },
    {
        "id": 3,
        "username": "Анастасія",
        "lastname": "Павлівна",
        "patronymic": "Оленівна",
        "totalDiscount": 70,
        "payment": "Накладений Платіж",
        "trackingNumber": 9270351,
        "totalPrice": 103853,
        "countOfProducts": 3,
        "orderDate": "1970-01-01T00:00:00.000Z",
        "user": {
            "id": 15,
            "username": "password test 3",
            "email": "julia.ovcharenko2000@gmail.com",
            "lastname": "",
            "patronymic": "",
            "birthDate": "2025-12-25T20:55:33.588Z",
            "phoneNumber": ""
        },
        "products": [
            {
                "count_of_product": 2,
                "price": 1000,
                "discount": 290,
                "Product": {
                    "category": {
                        "id": 1,
                        "name": "Drones",
                        "image": "DronesImage",
                        "orderId": 1
                    }
                }
            }
        ]
    }
]

Скасувати замовлення. | Cancel order.

  DELETE /orders/:orderId
Code Status Українською English
200 OK успішно success
400 Bad Request некоректний запит bad request
404 Not Found замовлення не знайдено not found
500 Internal Server Error внутрішня помилка сервера internal server error

Відповідь | Responce
  "Order deleted successfully"

Як встановити та запустити проєкт? | How to install and run the project?

For any OS

[!NOTE] У проєкті для надсилання email-листів використовується nodemailer. Google потребує app password для роботи з листами. Будь ласка, на пункті 3 перейдіть у .env.example і виконайте дії, прописані там.

The project uses nodemailer to send emails. Google requires an app password to work with emails. Please go to .env.example in step 3 and follow the steps there.

  1. Встановити Node.js | Install Node.js


    • Go to the official website
    • Download the LTS version.

  2. Склонуйте репозиторій з GitHub. | Clone the repository from GitHub:

    git clone https://github.com/JuliaOvcharenko/Drones
  3. Перейдіть в папку проєкту | Go to the project folder:.

    cd Drones
  4. Встановіть залежності. | Install dependencies.

    npm i
  5. Створити .env файл. | Create an .env file:

    cp .env.example .env

    Впишіть всі ключі, які потрібні.


    Then fill in all the required keys.

  6. Виконати міграції. | Run migrations.

     npx prisma migrate dev
  7. Запуск проєкту | Start the project:

      npm start
  8. Вітаємо! Ви локально запустили проєкт!


    Done! You have successfully run the project locally.


Висновок | Conclusion

About

Drones - e-shop with drones and thermal imagers - Backend

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •