# Phase 6: Dashboard API

## Objective
Provide the vendor's Home screen with revenue analytics, checkout metrics, basket stats, risk signals, sales performance charts, best-seller highlights, recent activity feed, and top categories.

---

## Context from Screenshots

The Home screen contains these sections:
1. **Total Revenue** - Big number with period selector (Today, 7D, 30D, Custom) and % change vs previous period
2. **Revenue Chart** - Line chart over the selected period
3. **Checkout Snapshot** (3 tabs):
   - **Checkout**: Completed checkouts count, % vs last week, sparkline
   - **Basket**: Avg basket value, % change, sparkline
   - **Risk**: Refund requests count, change vs last week, sparkline + Failed payments (declined)
4. **Inventory Alerts** - Low-stock items count (links to Phase 7)
5. **Sales Performance** - Bar chart by day of week, tabs: Revenue / Orders / Basket, period selector (7D, 14D, 30D), AI insight text
6. **Best-Seller Highlight** - Top product card with image, name, line, sold count, price, "View Details" button
7. **Recent Activity** - Feed of events (sales, feedback, stock refills) with timestamps
8. **Top Categories** - Category cards with % of sales, trend label (Rising, Stable, Best)

---

## Tasks

### 6.1 Revenue Endpoint

**Controller:** `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/RevenueController.php`

- `GET /v1/places/{place}/shop/dashboard/revenue`
- Query params: `period` (today|7d|30d|custom), `from`, `to`
- Returns:
```json
{
  "total": { "amount": 2256333, "currency": "USD" },
  "percentage_change": 38.1,
  "period": { "from": "2026-03-05", "to": "2026-03-11" },
  "chart": [
    { "date": "2026-03-05", "amount": 280000 },
    { "date": "2026-03-06", "amount": 310000 }
  ]
}
```

**Logic:**
- Sum `OrderItem.money_price` for PAID orders at this place within period
- Compare with previous equivalent period for % change
- Group by day for chart data

### 6.2 Checkout Snapshot Endpoint

**Controller:** `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/CheckoutSnapshotController.php`

- `GET /v1/places/{place}/shop/dashboard/checkout-snapshot`
- Query params: `period` (7d default)
- Returns all 3 tabs in one response:
```json
{
  "checkout": {
    "completed_count": 211,
    "percentage_change": 14.2,
    "label": "Successful paid orders",
    "sparkline": [18, 22, 25, 30, 28, 35, 40, 33]
  },
  "basket": {
    "average_value": { "amount": 11400, "currency": "USD" },
    "percentage_change": 6.0,
    "label": "Revenue per checkout",
    "sparkline": [95, 100, 102, 108, 112, 110, 114]
  },
  "risk": {
    "refund_requests": 9,
    "refund_change": -3,
    "refund_label": "After-payment support cases",
    "failed_payments": 0,
    "failed_label": "Declined transactions",
    "sparkline": [12, 11, 10, 10, 9, 9, 9]
  }
}
```

**Logic:**
- **Checkout**: Count PAID orders in period, compare with previous period
- **Basket**: Average of order totals for PAID orders
- **Risk**: Count refunded orders/items; count failed Stripe payment intents (if tracked)
- **Sparkline**: Daily counts over the last N intervals

### 6.3 Sales Performance Endpoint

**Controller:** `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/SalesPerformanceController.php`

- `GET /v1/places/{place}/shop/dashboard/sales-performance`
- Query params: `period` (7d|14d|30d), `metric` (revenue|orders|basket)
- Returns daily breakdown:
```json
{
  "period": "7d",
  "metric": "revenue",
  "average_line": 4800,
  "data": [
    { "day": "MON", "value": 2800, "is_today": false },
    { "day": "TUE", "value": 3500, "is_today": false },
    { "day": "FRI", "value": 9600, "is_today": true }
  ],
  "insight": "7-day view: Best conversion happens when supplements are featured near checkout."
}
```

**Logic:**
- Group PAID orders by day of week
- Revenue: Sum money_price
- Orders: Count orders
- Basket: Average order total
- Average line: Mean across all days
- Highlight current day

### 6.4 Best-Seller Endpoint

**Controller:** `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/BestSellerController.php`

- `GET /v1/places/{place}/shop/dashboard/best-sellers`
- Query params: `period` (7d default), `limit` (1 for highlight, more for "See All")
- Returns:
```json
{
  "data": [
    {
      "id": "product_public_id",
      "name": "Elite Performance Whey",
      "category": "Supplement Line",
      "sold_this_week": 84,
      "price": { "amount": 6499, "currency": "USD" },
      "badge": "TOP RATED",
      "image_url": "..."
    }
  ]
}
```

**Logic:**
- Count OrderItems where orderable = Product, order is PAID, within period
- Group by product, order by total quantity sold DESC
- Join product data

### 6.5 Recent Activity Endpoint

**Controller:** `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/RecentActivityController.php`

- `GET /v1/places/{place}/shop/dashboard/recent-activity`
- Query params: `limit` (default 10)
- Returns unified feed from multiple sources:
```json
{
  "updates_count": 3,
  "data": [
    {
      "type": "sale",
      "icon": "S",
      "color": "green",
      "title": "Premium Membership Sold",
      "subtitle": "to Alex Johnson",
      "amount": { "amount": 12000, "currency": "USD" },
      "time_ago": "2 mins ago",
      "navigable": false
    },
    {
      "type": "feedback",
      "icon": "F",
      "color": "yellow",
      "title": "New Feedback Received",
      "subtitle": "\"Great facility and equipment\"",
      "time_ago": "1h ago",
      "navigable": true
    },
    {
      "type": "inventory",
      "icon": "I",
      "color": "blue",
      "title": "Stock Refill Logged",
      "subtitle": "Protein bars +12 units",
      "time_ago": "3h ago",
      "navigable": true
    }
  ]
}
```

**Logic:**
- Merge recent events from:
  - PAID orders (sales)
  - Feedback/reports (if model exists)
  - Stock changes (ProductVariationStock updates)
  - Membership purchases
- Sort by timestamp DESC
- Limit to N items

### 6.6 Top Categories Endpoint

**Controller:** `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/TopCategoriesController.php`

- `GET /v1/places/{place}/shop/dashboard/top-categories`
- Query params: `period` (30d default)
- Returns:
```json
{
  "data": [
    {
      "id": "category_public_id",
      "name": "Gear",
      "short_name": "G",
      "sales_percentage": 24,
      "trend": "rising"
    },
    {
      "id": "category_public_id",
      "name": "Supps",
      "short_name": "S",
      "sales_percentage": 19,
      "trend": "stable"
    },
    {
      "id": "category_public_id",
      "name": "Training",
      "short_name": "T",
      "sales_percentage": 57,
      "trend": "best"
    }
  ]
}
```

**Logic:**
- Join OrderItems → Product → Category for PAID orders in period
- Calculate % of total revenue per category
- Compare with previous period to determine trend:
  - "best" = highest % of sales
  - "rising" = % increased vs previous period
  - "stable" = % roughly same
  - "declining" = % decreased

### 6.7 Dashboard Service

**File:** `app/Services/ShopManager/DashboardService.php`

Shared query logic for dashboard controllers:
- Period resolution (today, 7d, 30d, custom → Carbon dates)
- Previous period calculation for comparisons
- Base query scopes (place, status = PAID, date range)
- Sparkline generation helper

### 6.8 Tests

**File:** `tests/Feature/Controllers/ShopManager/DashboardTest.php`

Test cases:
- [ ] Revenue endpoint returns correct total for period
- [ ] Revenue percentage change is calculated correctly
- [ ] Revenue chart has one entry per day
- [ ] Custom date range works
- [ ] Checkout snapshot returns all 3 sections
- [ ] Basket average is calculated correctly
- [ ] Sales performance groups by day of week
- [ ] Sales performance highlights current day
- [ ] Best-seller returns the most sold product
- [ ] Recent activity merges multiple event types
- [ ] Top categories calculates correct percentages
- [ ] All endpoints return empty data gracefully (new place with no orders)
- [ ] Period defaults work when no params provided
- [ ] Non-shop-manager gets 403

---

## Files Created/Modified

| Action | File |
|---|---|
| Create | `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/RevenueController.php` |
| Create | `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/CheckoutSnapshotController.php` |
| Create | `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/SalesPerformanceController.php` |
| Create | `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/BestSellerController.php` |
| Create | `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/RecentActivityController.php` |
| Create | `app/Http/Controllers/Api/Employee/ShopManager/Dashboard/TopCategoriesController.php` |
| Create | `app/Services/ShopManager/DashboardService.php` |
| Modify | `routes/api.php` |
| Create | `tests/Feature/Controllers/ShopManager/DashboardTest.php` |

---

## Acceptance Criteria

- [ ] All dashboard endpoints return data matching the screenshot structure
- [ ] Period filtering works (today, 7D, 30D, custom range)
- [ ] Percentage changes are calculated against previous equivalent period
- [ ] Sparklines have correct number of data points
- [ ] Empty state handled gracefully (zeros, not errors)
- [ ] Queries are optimized (avoid N+1, use aggregates)
- [ ] Swagger annotations on all controllers
- [ ] All tests pass
- [ ] `./gitCheck.sh` passes
