# 🍴 Hierarchical Menu Management API (v2)

This document describes the complete CRUD API for the **3-level menu hierarchy**:
**Category → Subcategory → Item**

---

## 🚀 Base URLs
- **Categories:**    `http://localhost:4000/api/categories`
- **Subcategories:** `http://localhost:4000/api/subcategories`
- **Items:**         `http://localhost:4000/api/items`

---

## 🔑 Authentication
All admin endpoints require a valid JWT token in the `Authorization` header.

**Header:** `Authorization: Bearer <your_jwt_token>`

Public endpoints (marked 🌐) do **not** require a token.

---

## 📂 1. Categories

### 1.1 Create Category
- **Method:** `POST`
- **URL:** `/api/categories`
- **Auth:** ✅ Required
- **Request Body:**
  ```json
  {
    "category_name": "Fast Food",
    "status": true
  }
  ```
- **Success Response:** `201 Created`
  ```json
  {
    "success": true,
    "message": "Category created successfully.",
    "data": { "id": 1, "category_name": "Fast Food", "status": true }
  }
  ```

---

### 1.2 Get All Categories
- **Method:** `GET`
- **URL:** `/api/categories`
- **Auth:** ✅ Required
- **Description:** Returns **all** categories at once (no pagination), each with their nested subcategories.
- **Response:**
  ```json
  {
    "success": true,
    "count": 5,
    "data": [
      {
        "id": 1,
        "category_name": "Fast Food",
        "status": true,
        "subcategories": [
          { "id": 10, "sub_category_name": "Burgers", "category_id": 1 },
          { "id": 11, "sub_category_name": "Pizzas",  "category_id": 1 }
        ]
      }
    ]
  }
  ```

---

### 1.3 Get Category by ID
- **Method:** `GET`
- **URL:** `/api/categories/:id`
- **Auth:** ✅ Required
- **Description:** Returns a single category with all its subcategories.
- **Response:**
  ```json
  {
    "success": true,
    "data": {
      "id": 1,
      "category_name": "Fast Food",
      "status": true,
      "subcategories": [
        { "id": 10, "sub_category_name": "Burgers", "category_id": 1 },
        { "id": 11, "sub_category_name": "Pizzas",  "category_id": 1 }
      ]
    }
  }
  ```

---

### 1.4 Update Category
- **Method:** `PUT`
- **URL:** `/api/categories/:id`
- **Auth:** ✅ Required
- **Request Body:**
  ```json
  {
    "category_name": "Street Food",
    "status": true
  }
  ```
- **Success Response:** `200 OK`
  ```json
  { "success": true, "message": "Category updated successfully." }
  ```

---

### 1.5 Delete Category
- **Method:** `DELETE`
- **URL:** `/api/categories/:id`
- **Auth:** ✅ Required
- **Note:** Deleting a category will **cascade-delete** all its subcategories (DB constraint).
- **Success Response:** `200 OK`
  ```json
  { "success": true, "message": "Category deleted successfully." }
  ```

---

## 📂 2. Subcategories

### 2.1 Create Subcategory
- **Method:** `POST`
- **URL:** `/api/subcategories`
- **Auth:** ✅ Required
- **Request Body:**
  ```json
  {
    "category_id": 1,
    "sub_category_name": "Burgers",
    "status": true
  }
  ```
- **Success Response:** `201 Created`
  ```json
  {
    "success": true,
    "message": "Subcategory created successfully.",
    "data": { "id": 10, "sub_category_name": "Burgers", "category_id": 1, "status": true }
  }
  ```

---

### 2.2 Get All Subcategories
- **Method:** `GET`
- **URL:** `/api/subcategories`
- **Auth:** ✅ Required
- **Description:** Returns **all** subcategories at once (no pagination) with their parent `category_name` included.
- **Response:**
  ```json
  {
    "success": true,
    "count": 10,
    "data": [
      { "id": 10, "sub_category_name": "Burgers", "category_id": 1, "category_name": "Fast Food" },
      { "id": 11, "sub_category_name": "Pizzas",  "category_id": 1, "category_name": "Fast Food" }
    ]
  }
  ```

---

### 2.3 Get Subcategory by ID
- **Method:** `GET`
- **URL:** `/api/subcategories/:id`
- **Auth:** ✅ Required
- **Description:** Returns a single subcategory with its parent `category_name` and all its **items** embedded.
- **Response:**
  ```json
  {
    "success": true,
    "data": {
      "id": 10,
      "sub_category_name": "Burgers",
      "category_id": 1,
      "category_name": "Fast Food",
      "items": [
        { "id": 101, "item_name": "Veg Burger", "base_price": 80, "diet_type": "veg" },
        { "id": 102, "item_name": "Chicken Burger", "base_price": 120, "diet_type": "non-veg" }
      ]
    }
  }
  ```

---

### 2.4 Get Subcategories by Category ID
- **Method:** `GET`
- **URL:** `/api/subcategories/by-category/:category_id`
- **Auth:** ✅ Required
- **Description:** Returns all subcategories that belong to a given category (find by parent FK).
- **Response:**
  ```json
  {
    "success": true,
    "category": { "id": 1, "category_name": "Fast Food" },
    "data": [
      { "id": 10, "sub_category_name": "Burgers", "category_id": 1 },
      { "id": 11, "sub_category_name": "Pizzas",  "category_id": 1 }
    ]
  }
  ```

---

### 2.5 Update Subcategory
- **Method:** `PUT`
- **URL:** `/api/subcategories/:id`
- **Auth:** ✅ Required
- **Request Body:**
  ```json
  {
    "sub_category_name": "Gourmet Burgers",
    "status": true
  }
  ```
- **Success Response:** `200 OK`
  ```json
  { "success": true, "message": "Subcategory updated successfully." }
  ```

---

### 2.6 Delete Subcategory
- **Method:** `DELETE`
- **URL:** `/api/subcategories/:id`
- **Auth:** ✅ Required
- **Note:** Deleting a subcategory sets `sub_category_id = NULL` on associated items (items are **NOT** deleted).
- **Success Response:** `200 OK`
  ```json
  { "success": true, "message": "Subcategory deleted. Associated items have been unlinked." }
  ```

---

## 🍱 3. Menu Items

### 3.1 Create Item
- **Method:** `POST`
- **URL:** `/api/items`
- **Auth:** ✅ Required
- **Request Body:**
  ```json
  {
    "category_id": 1,
    "sub_category_id": 10,
    "item_name": "Veg Cheese Burger",
    "item_code": "VB_001",
    "short_code": "vcb",
    "portion": "Regular",
    "price": 120.00,
    "image_url": "https://example.com/burger.jpg",
    "diet_type": "veg",
    "is_available": true,
    "is_featured": false,
    "rating": 4.2,
    "modifiers": [
      {
        "name": "Size",
        "type": "single",
        "required": true,
        "options": [
          { "name": "Medium", "price": 0 },
          { "name": "Large",  "price": 50 }
        ]
      }
    ]
  }
  ```
- **Diet Types:** `veg` | `non-veg` | `egg`
- **Success Response:** `201 Created`
  ```json
  { "success": true, "message": "Menu item created successfully.", "item_id": 101 }
  ```

---

### 3.2 Get All Items — Admin List
- **Method:** `GET`
- **URL:** `/api/items/admin/list`
- **Auth:** ✅ Required
- **Description:** Returns **all** items at once (no pagination) with `category_name` and `sub_category_name` included.
- **Response:**
  ```json
  {
    "success": true,
    "count": 45,
    "data": [
      {
        "id": 101,
        "item_name": "Veg Burger",
        "category_id": 1, "category_name": "Fast Food",
        "sub_category_id": 10, "sub_category_name": "Burgers",
        "price": 80, "diet_type": "veg"
      }
    ]
  }
  ```

---

### 3.3 Get Single Item by ID
- **Method:** `GET`
- **URL:** `/api/items/:id`
- **Auth:** ✅ Required
- **Description:** Returns a single item by its primary key with full category and subcategory names.
- **Response:**
  ```json
  {
    "success": true,
    "data": {
      "id": 101,
      "item_name": "Veg Burger",
      "category_id": 1, "category_name": "Fast Food",
      "sub_category_id": 10, "sub_category_name": "Burgers",
      "price": 80, "diet_type": "veg",
      "modifiers": [{ "name": "Size", "type": "single", "options": [...] }]
    }
  }
  ```

---

### 3.4 Get Items by Category ID
- **Method:** `GET`
- **URL:** `/api/items/ /:category_id`
- **Auth:** ✅ Required
- **Description:** Returns all items belonging to a specific category (find by `category_id` FK). Subcategory name included per item.
- **Response:**
  ```json
  {
    "success": true,
    "category": { "id": 1, "category_name": "Fast Food" },
    "count": 12,
    "data": [
      { "id": 101, "item_name": "Veg Burger", "sub_category_id": 10, "sub_category_name": "Burgers" },
      { "id": 103, "item_name": "Pepperoni Pizza", "sub_category_id": 11, "sub_category_name": "Pizzas" }
    ]
  }
  ```

---

### 3.5 Get Items by Subcategory ID
- **Method:** `GET`
- **URL:** `/api/items/by-subcategory/:sub_category_id`
- **Auth:** ✅ Required
- **Description:** Returns all items belonging to a specific subcategory (find by `sub_category_id` FK). Includes parent category info.
- **Response:**
  ```json
  {
    "success": true,
    "subcategory": {
      "id": 10,
      "sub_category_name": "Burgers",
      "category_id": 1,
      "category_name": "Fast Food"
    },
    "count": 5,
    "data": [
      { "id": 101, "item_name": "Veg Burger",     "price": 80,  "diet_type": "veg" },
      { "id": 102, "item_name": "Chicken Burger", "price": 120, "diet_type": "non-veg" }
    ]
  }
  ```

---

### 3.6 Get Public Menu (Nested View) 🌐
- **Method:** `GET`
- **URL:** `/api/items/public/menu`
- **Auth:** ❌ Not Required (Public Access)
- **Description:** Returns the entire available menu grouped as **Category → Subcategory → Items**. Only `is_available = true` and `status = true` categories are included.
- **Response:**
  ```json
  {
    "success": true,
    "count": 25,
    "data": [
      {
        "category_name": "Fast Food",
        "subcategories": [
          {
            "sub_category_name": "Burgers",
            "items": [
              { "id": 101, "item_name": "Veg Burger",     "price": 80,  "diet_type": "veg" },
              { "id": 102, "item_name": "Chicken Burger", "price": 120, "diet_type": "non-veg" }
            ]
          },
          {
            "sub_category_name": "Pizzas",
            "items": [
              { "id": 103, "item_name": "Margherita", "price": 150, "diet_type": "veg" }
            ]
          }
        ]
      }
    ]
  }
  ```

---

### 3.7 Update Item
- **Method:** `PUT`
- **URL:** `/api/items/:id`
- **Auth:** ✅ Required
- **Request Body:** Same structure as **Create Item** (3.1).
- **Success Response:** `200 OK`
  ```json
  { "success": true, "message": "Menu item updated successfully." }
  ```

---

### 3.8 Delete Item
- **Method:** `DELETE`
- **URL:** `/api/items/:id`
- **Auth:** ✅ Required
- **Success Response:** `200 OK`
  ```json
  { "success": true, "message": "Menu item deleted successfully." }
  ```

---

## 🔗 Relationship Summary

```
menu_categories (id)
    └── menu_subcategories (id, category_id FK)
            └── menu_items (id, category_id FK, sub_category_id FK)
```

| Lookup Need | Endpoint |
|-------------|----------|
| All subcats inside a category | `GET /api/subcategories/by-category/:category_id` |
| All items inside a category | `GET /api/items/by-category/:category_id` |
| All items inside a subcategory | `GET /api/items/by-subcategory/:sub_category_id` |
| Full nested menu for frontend | `GET /api/items/public/menu` |

---

## ⚠️ Cascade & Deletion Rules

| Action | Effect |
|--------|--------|
| Delete **Category** | **Cascade-deletes** all its subcategories (DB `ON DELETE CASCADE`) |
| Delete **Subcategory** | Sets `sub_category_id = NULL` on items (**items preserved**, `ON DELETE SET NULL`) |
| Delete **Item** | Permanently removes the item only |
