swiftops-backend / docs /agent /frontend /PROJECT_DASHBOARD_API.md
kamau1's picture
feat: field agent dashboard and work queue
b797b14

Field Agent Project Dashboard API

Endpoint

GET /api/v1/projects/{project_id}/dashboard

Authorization

Field agents can only access projects they're assigned to (via ProjectTeam).


Field Agent Response

{
  "project_info": {
    "id": "uuid",
    "title": "Nairobi Fiber Rollout",
    "project_type": "infrastructure",
    "status": "active"
  },
  "my_stats": {
    "tickets": {
      "total_assigned": 15,
      "pending": 4,
      "in_progress": 2,
      "completed_this_week": 9
    },
    "expenses": {
      "total_amount": 12500.00,
      "pending_amount": 4500.00,
      "pending_count": 3
    },
    "inventory": {
      "items_on_hand": 8
    },
    "notifications": {
      "unread": 5,
      "total": 20
    }
  },
  "work_queue": {
    "pending_assignments": [
      {
        "assignment_id": "uuid",
        "ticket_id": "uuid",
        "ticket_title": "Install fiber at Westlands",
        "ticket_number": "TKT-2024-001",
        "status": "PENDING",
        "priority": "high",
        "due_date": "2025-11-28T00:00:00Z",
        "execution_order": 1,
        "assigned_at": "2025-11-27T08:00:00Z"
      }
    ],
    "total_pending": 4,
    "high_priority": 1,
    "due_today": 2
  },
  "cached_at": "2025-11-27T10:30:00Z",
  "cache_expires_in_seconds": 300
}

Usage

Fetch Project Dashboard

const response = await fetch(
  `/api/v1/projects/${projectId}/dashboard`,
  { headers: { 'Authorization': `Bearer ${token}` } }
);
const data = await response.json();

Display Stats Cards

const { my_stats } = data;

<Card title="Pending">
  {my_stats.tickets.pending}
</Card>

<Card title="In Progress">
  {my_stats.tickets.in_progress}
</Card>

<Card title="Completed This Week">
  {my_stats.tickets.completed_this_week}
</Card>

<Card title="Pending Expenses">
  KES {my_stats.expenses.pending_amount.toLocaleString()}
</Card>

Display Work Queue

const { work_queue } = data;

<WorkQueue>
  {work_queue.pending_assignments.map(assignment => (
    <WorkItem key={assignment.assignment_id}>
      <Badge>{assignment.execution_order || '—'}</Badge>
      <Title>{assignment.ticket_title}</Title>
      <Priority>{assignment.priority}</Priority>
      <Status>{assignment.status}</Status>
    </WorkItem>
  ))}
</WorkQueue>

Status Values

Assignment status (computed from timeline):

  • PENDING - Assigned, not responded
  • ACCEPTED - Responded, not started journey
  • IN_TRANSIT - Started journey, not arrived
  • ON_SITE - Arrived at site, working
  • CLOSED - Work completed

Cache

  • Cached for 5 minutes
  • Use ?refresh=true to force refresh
  • Cache is per-user (field agent sees their own data)

Manager Response

Managers get full project stats (different structure):

{
  "project_info": {...},
  "summary_stats": {
    "tickets": {...},
    "sales_orders": {...},
    "expenses": {...},
    "team": {...},
    "finances": {...},
    "regions": {...},
    "inventory": {...}
  }
}