# Project Overview Endpoint ## Purpose Single endpoint that replaces 4 separate calls to get complete project structure. Returns project details, regions, roles, subcontractors, and team info based on user permissions. **Replaces:** - `GET /projects/{id}` - `GET /projects/{id}/regions` - `GET /projects/{id}/project-roles` - `GET /projects/{id}/subcontractors` ## Endpoint ``` GET /api/v1/projects/{project_id}/overview ``` **Query Params:** - `refresh` (optional): `true` to force cache refresh **Cache:** 12 hours ## Response Structure ### For Managers/Admins ```json { "project": { "id": "uuid", "title": "Project Name", "project_type": "customer_service", "status": "active", "client_id": "uuid", "client_name": "Client Name", "contractor_id": "uuid", "contractor_name": "Contractor Name", "primary_manager_id": "uuid", "primary_manager_name": "Manager Name", "service_type": "ftth", "planned_start_date": "2025-01-01", "planned_end_date": "2025-12-31", "activation_requirements": [...], "photo_requirements": [...], "budget": {...}, "is_closed": false, "created_at": "2025-01-01T00:00:00Z" }, "regions": [ { "id": "uuid", "region_name": "Nairobi West", "region_code": "NRB-W", "manager_id": "uuid", "manager_name": "Regional Manager", "is_active": true, "city": "Nairobi", "latitude": -1.2921, "longitude": 36.8219 } ], "roles": [ { "id": "uuid", "role_name": "Technician", "compensation_type": "commission", "commission_percentage": 15.0, "base_amount": 500.0, "is_active": true } ], "subcontractors": [ { "id": "uuid", "subcontractor_id": "uuid", "subcontractor_name": "SubCo Ltd", "scope_description": "Installation work", "project_region_id": "uuid", "region_name": "Nairobi West", "contract_value": 50000.0, "is_active": true } ], "team_summary": { "total_members": 25, "by_role": { "field_agent": 15, "dispatcher": 3, "sales_agent": 5, "project_manager": 2 }, "by_region": { "Nairobi West": 10, "Mombasa": 8, "Project-wide": 7 } }, "my_involvement": null, "cached_at": "2025-12-02T10:00:00Z", "cache_expires_in_seconds": 43200 } ``` ### For Field Agents/Sales Agents ```json { "project": { "id": "uuid", "title": "Project Name", "project_type": "customer_service", "status": "active", "client_name": "Client Name", "contractor_name": "Contractor Name", "service_type": "ftth", "activation_requirements": [...], "photo_requirements": [...] }, "regions": [ { "id": "uuid", "region_name": "Nairobi West", "is_active": true, "city": "Nairobi" } ], "roles": null, "subcontractors": null, "team_summary": null, "my_involvement": { "user_id": "uuid", "user_name": "John Doe", "user_email": "john@example.com", "user_role": "field_agent", "team_role": "technician", "project_role_id": "uuid", "project_role_name": "Senior Technician", "assigned_region_id": "uuid", "assigned_region_name": "Nairobi West", "is_lead": false, "assigned_at": "2025-01-15T08:00:00Z", "subcontractor_id": null, "subcontractor_name": null }, "cached_at": "2025-12-02T10:00:00Z", "cache_expires_in_seconds": 43200 } ``` ## Frontend Usage ### Display Project Overview Page ```typescript // Fetch overview const response = await fetch(`/api/v1/projects/${projectId}/overview`); const data = await response.json(); // Show project header showProjectHeader({ title: data.project.title, status: data.project.status, client: data.project.client_name, contractor: data.project.contractor_name }); // Show regions (all users see all regions) data.regions.forEach(region => { const isMyRegion = data.my_involvement?.assigned_region_id === region.id; renderRegionCard(region, isMyRegion); // Highlight user's region }); // Role-specific rendering if (data.my_involvement) { // Field agent/sales agent view showMyInvolvement({ role: data.my_involvement.team_role, region: data.my_involvement.assigned_region_name, projectRole: data.my_involvement.project_role_name }); } else { // Manager/admin view showRoles(data.roles); showSubcontractors(data.subcontractors); showTeamSummary(data.team_summary); } ``` ### Check User's Region Assignment ```typescript // Highlight user's assigned region in UI const myRegionId = data.my_involvement?.assigned_region_id; data.regions.forEach(region => { const card = createRegionCard(region); if (region.id === myRegionId) { card.classList.add('my-region', 'highlighted'); } }); ``` ### Display Requirements (Field Agents) ```typescript // Show what photos are required data.project.photo_requirements.forEach(req => { console.log(`${req.type}: ${req.min_photos}-${req.max_photos} photos`); }); // Show activation form fields data.project.activation_requirements.forEach(field => { renderFormField({ name: field.field, label: field.label, type: field.type, required: field.required, options: field.options }); }); ``` ## Key Points 1. **Single call** - Replaces 4 separate API calls 2. **Role-based** - Response adapts to user permissions automatically 3. **Long cache** - 12 hours (structure rarely changes) 4. **All see regions** - Everyone sees all regions, UI highlights user's assigned region 5. **Field agents** - See their involvement only, not other team members 6. **Managers** - See complete project structure and team composition ## Error Responses - `404` - Project not found - `403` - User not authorized to access project - `500` - Server error