@extends('layouts.portal') @section('title', 'Analytics') @section('subtitle', 'Revenue, enrollments, exam results, sales pipeline and attendance for the last '.$span.' months.') @section('actions')
@endsection @section('content') @php $series = fn (array $values) => collect($labels)->map(fn ($l, $i) => ['label' => $l, 'value' => $values[$i] ?? 0])->all(); $periodRevenue = array_sum($revenueSeries); $periodEnrol = array_sum($enrollSeries); $funnelOrder = ['new' => 'New', 'contacted' => 'Contacted', 'qualified' => 'Qualified', 'converted' => 'Converted', 'lost' => 'Lost']; $funnelTotal = max(1, array_sum($leadFunnel)); $methodLabel = fn ($m) => ucwords(str_replace('_', ' ', (string) ($m ?: 'other'))); $attTotal = array_sum($attStatus); $attOverall = $attTotal - ($attStatus['excused'] ?? 0) > 0 ? round((($attStatus['present'] ?? 0) + ($attStatus['late'] ?? 0)) / ($attTotal - ($attStatus['excused'] ?? 0)) * 100, 1) : null; @endphp
Revenue, {{ $span }} months{{ money($periodRevenue) }}{{ money($totals['revenue']) }} collected all time
New enrollments{{ number_format($periodEnrol) }}in the last {{ $span }} months
Learners{{ number_format($totals['learners']) }}{{ number_format(array_sum($learnerSeries)) }} joined in this period
Certificates issued{{ number_format($totals['credentials']) }}{{ number_format($totals['attempts']) }} exam attempts finished

Revenue by month

Confirmed payments
@include('partials.charts.bars', ['data' => $series($revenueSeries), 'height' => 220, 'format' => 'money', 'title' => 'Confirmed revenue per month', 'values' => false])

Enrollments by month

All statuses
@include('partials.charts.line', ['data' => $series($enrollSeries), 'height' => 220, 'format' => 'int', 'title' => 'New enrollments per month'])

New learner accounts

@include('partials.charts.line', ['data' => $series($learnerSeries), 'height' => 170, 'format' => 'int', 'title' => 'New learner accounts per month'])

Certificates issued

@include('partials.charts.bars', ['data' => $series($credSeries), 'height' => 170, 'format' => 'int', 'title' => 'Certificates issued per month', 'values' => false])

Courses by enrollment

All courses
@php $topMax = max(1, (int) $topCourses->max('enrollments_total')); @endphp @forelse($topCourses as $c)
{{ $c->title }}
{{ $c->enrollments_count }} {{ \Illuminate\Support\Str::plural('batch', $c->enrollments_count) }}
{{ $c->enrollments_total }}
@empty @endforelse

Exam pass rates

All exams
@forelse($exams as $e)
{{ $e->title }}
{{ $e->finished }} {{ \Illuminate\Support\Str::plural('attempt', $e->finished) }} · average score {{ $e->avg }}% · pass mark {{ $e->pass_percent }}%
{{ $e->pass_rate }}%
@empty @endforelse

Lead funnel

Open pipeline
@if(array_sum($leadFunnel) === 0) @else @foreach($funnelOrder as $key => $label) @php $c = $leadFunnel[$key] ?? 0; $tone = $key === 'converted' ? 'green' : ($key === 'lost' ? 'red' : ''); @endphp
{{ $label }}
{{ $c }} {{ round($c / $funnelTotal * 100) }}%
@endforeach @endif

Payment methods

By amount collected
@include('partials.charts.donut', ['data' => $methods->map(fn ($m) => ['label' => $methodLabel($m->method), 'note' => $m->c.' '.\Illuminate\Support\Str::plural('payment', $m->c), 'value' => (float) $m->s])->all(), 'format' => 'money', 'size' => 150, 'title' => 'Collected revenue by payment method', 'center' => 'collected', 'empty' => 'No confirmed payments yet.'])

Attendance

Present and late count as attended; excused classes are ignored
{{ $attOverall !== null ? $attOverall.'%' : 'n/a' }}overall attendance across {{ number_format($attTotal) }} register entries
@include('partials.charts.donut', ['data' => [ ['label' => 'Present', 'value' => $attStatus['present'] ?? 0, 'color' => '#12b981'], ['label' => 'Late', 'value' => $attStatus['late'] ?? 0, 'color' => '#f59e0b'], ['label' => 'Absent', 'value' => $attStatus['absent'] ?? 0, 'color' => '#e11d48'], ['label' => 'Excused', 'value' => $attStatus['excused'] ?? 0, 'color' => '#94a3b8'], ], 'size' => 130, 'title' => 'Attendance status split', 'center' => 'entries', 'empty' => 'No registers have been taken yet.'])
@if($attBatches->isEmpty()) @else
@foreach($attBatches as $r) @endforeach
BatchClassesLearnersAverage attendanceBelow min.
{{ $r['batch']->course?->title }}
{{ $r['batch']->batch_code }}
{{ $r['sessions'] }} {{ $r['learners'] }}
{{ rtrim(rtrim(number_format($r['avg'], 1), '0'), '.') }}%
@if($r['low']){{ $r['low'] }}@else0@endif
@endif
@endsection