@extends('layouts.admin') @section('title', 'Reports') @section('content') @php $tabs = ['growth' => 'Growth', 'marketplace' => 'Marketplace', 'transport' => 'Transport', 'revenue' => 'Revenue', 'quality' => 'Quality', 'content' => 'Content', 'health' => 'Data health']; $range = ['from' => $from->toDateString(), 'to' => $to->toDateString()]; $pct = fn ($v) => $v === null ? '—' : $v.'%'; $hours = fn ($v) => $v === null ? '—' : round($v, 1).' h'; $empty = 'No data in this period.'; @endphp
Session and screen analytics come from the separate analytics tool (Firebase), not from here.
@switch($tab) @case('growth')
New users
{{ indian_number($growth['newUsers']) }}
Users by role (all time)
@foreach ($growth['byRole'] as $r)@endforeach
RoleActivePending
{{ $r->name }}{{ $r->active }}{{ $r->pending }}
New users by district
@forelse ($growth['byDistrict'] as $r)@empty{!! $empty !!}@endforelse
{{ $r->district }}{{ $r->n }}
App language (O7)
@forelse ($growth['byLanguage'] as $r)@empty{!! $empty !!}@endforelse
{{ $r->language }}{{ $r->n }}
@break @case('marketplace')
Published in period
{{ indian_number($marketplace['stats']['published']) }}
Enquiry rate (O2, target ≥ 40%)
{{ $pct($marketplace['stats']['enquiry_rate']) }}
Average time to first enquiry
{{ $hours($marketplace['firstEnquiryHours']) }}
Listings created in period, by marketplace
@forelse ($marketplace['byType'] as $r)@empty{!! $empty !!}@endforelse
MarketplaceCreatedLiveSoldExpiredEnquiries
{{ $r->name }}{{ $r->total }}{{ $r->published }}{{ $r->sold }}{{ $r->expired }}{{ $r->enquiries }}
Top categories
@forelse ($marketplace['topCategories'] as $r)@empty{!! $empty !!}@endforelse
CategoryListingsEnquiries
{{ $r->name }}{{ $r->n }}{{ $r->enquiries }}
@break @case('transport')
Confirmed
{{ $transport['stats']['confirmed'] }}
Completed
{{ $transport['stats']['completed'] }}
Completion (≥ 90%)
{{ $pct($transport['stats']['completion_rate']) }}
On-time pickup (≥ 85%)
{{ $pct($transport['stats']['on_time_rate']) }}
Bookings by status
@forelse ($transport['byStatus'] as $sid => $n)@empty{!! $empty !!}@endforelse
@include('partials.status', ['status' => $sid]){{ $n }}
By vehicle type
@forelse ($transport['byVehicle'] as $r)@empty{!! $empty !!}@endforelse
VehicleBookingsAvg ₹/km
{{ $r->vehicle }}{{ $r->n }}{{ $r->per_km ? inr($r->per_km, true) : '—' }}
Top routes
@forelse ($transport['routes'] as $r)@empty{!! $empty !!}@endforelse
{{ $r->route }}{{ $r->n }}
Cancellation reasons
@forelse ($transport['cancelReasons'] as $r)@empty{!! $empty !!}@endforelse
{{ $r->label }}{{ $r->n }}
@break @case('revenue')
Transport service fees (O6)
{{ inr($revenue['serviceFees']) }}
completed bookings in period
Cash still to collect
{{ inr($revenue['outstanding']->amount) }}
{{ $revenue['outstanding']->n }} delivered bookings unpaid (all time)
Payments collected by method
@forelse ($revenue['byMethod'] as $r)@empty{!! $empty !!}@endforelse
MethodPaymentsAmount
{{ $r->name }}{{ $r->n }}{{ inr($r->amount) }}
@break @case('quality')
Average rating (O5, ≥ 4.2)
{{ $quality['trust']['rating'] ?? '—' }}
{{ $quality['trust']['ratings'] }} ratings
Complaints per 100 bookings (≤ 2)
{{ $quality['trust']['complaints_per_100'] ?? '—' }}
Listing moderation turnaround
{{ $hours($quality['moderationHours']) }}
Ratings by type
@forelse ($quality['ratings'] as $r)@empty{!! $empty !!}@endforelse
{{ humanize($r->reviewable_type) }}{{ round($r->avg, 2) }} ★ ({{ $r->n }})
Reports by reason
@forelse ($quality['reports'] as $r)@empty{!! $empty !!}@endforelse
{{ $r->label }}{{ $r->n }}
Support tickets
@forelse ($quality['tickets'] as $r)@empty{!! $empty !!}@endforelse
CategoryTickets1st reply
{{ $r->label }}{{ $r->n }}{{ $hours($r->first_response_h) }}
@break @case('content')
Crop alerts in period
{{ $content['alerts'] }}
Articles
@forelse ($content['articles'] as $r)@empty{!! $empty !!}@endforelse
TypeLanguagePublishedTotal
{{ $r->type }}{{ $r->language }}{{ $r->published }}{{ $r->total }}
Crop Guide views need app analytics events; the database does not record article views.
@break @case('health')

Each check should read 0. Anything else points to a bug in the app or an import; ask engineering to look.

@foreach ($health as [$label, $n]) @endforeach
{{ $label }}@if ($n === 0)0@else{{ $n }}@endif
@break @endswitch @endsection