137 lines
6.4 KiB
PHP
137 lines
6.4 KiB
PHP
@extends('layouts.app')
|
|
@section('title', __('crm::lang.supervisor_dashboard'))
|
|
@section('content')
|
|
@include('crm::layouts.nav')
|
|
@include('crm::telemarketing.partials.workspace_styles')
|
|
|
|
<div class="crm-page tm-workspace">
|
|
<div class="crm-page-header">
|
|
<div>
|
|
<h1><i class="fas fa-chart-line"></i> @lang('crm::lang.supervisor_dashboard')</h1>
|
|
<p class="crm-subtitle">@lang('crm::lang.dashboard_live_hint')</p>
|
|
</div>
|
|
<div>
|
|
<a href="{{ action([\Modules\Crm\Http\Controllers\CallWorkspaceController::class, 'index']) }}" class="crm-btn crm-btn-primary"><i class="fas fa-headset"></i> @lang('crm::lang.call_workspace')</a>
|
|
<a href="{{ action([\Modules\Crm\Http\Controllers\TelemarketingReportController::class, 'index']) }}" class="crm-btn crm-btn-ghost"><i class="fas fa-file-alt"></i> @lang('crm::lang.reports')</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tm-stat-grid" id="tm_dashboard_stats">
|
|
<div class="tm-stat tm-stat-indigo">
|
|
<div class="tm-stat-label">@lang('crm::lang.active_calls')</div>
|
|
<div class="tm-stat-value" id="stat_active">0</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-teal">
|
|
<div class="tm-stat-label">@lang('crm::lang.today_calls')</div>
|
|
<div class="tm-stat-value"><span id="stat_today_total">0</span> / <span id="stat_today_answered">0</span> @lang('crm::lang.answered')</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-amber">
|
|
<div class="tm-stat-label">@lang('crm::lang.answer_rate')</div>
|
|
<div class="tm-stat-value" id="stat_rate">0%</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-rose">
|
|
<div class="tm-stat-label">@lang('crm::lang.lead_score')</div>
|
|
<div class="tm-stat-value" id="stat_avg_score">0</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-indigo">
|
|
<div class="tm-stat-label">@lang('crm::lang.queue_remaining')</div>
|
|
<div class="tm-stat-value" id="stat_queue">0</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-teal">
|
|
<div class="tm-stat-label">@lang('crm::lang.phone_status_interested')</div>
|
|
<div class="tm-stat-value" id="stat_interested">0</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-amber">
|
|
<div class="tm-stat-label">@lang('crm::lang.companies')</div>
|
|
<div class="tm-stat-value" id="stat_companies">0</div>
|
|
</div>
|
|
<div class="tm-stat tm-stat-rose">
|
|
<div class="tm-stat-label">@lang('crm::lang.reception_score')</div>
|
|
<div class="tm-stat-value" id="stat_reception">0</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tm-layout" style="margin-top:18px">
|
|
<div>
|
|
<div class="tm-card">
|
|
<div class="tm-card-head"><i class="fas fa-broadcast-tower"></i> @lang('crm::lang.live_calls')</div>
|
|
<div class="tm-card-body" id="live_calls_body">
|
|
<p class="text-muted">@lang('crm::lang.no_active_calls')</p>
|
|
</div>
|
|
</div>
|
|
<div class="tm-card" style="margin-top:16px">
|
|
<div class="tm-card-head"><i class="fas fa-chart-pie"></i> @lang('crm::lang.outcome_breakdown')</div>
|
|
<div class="tm-card-body" id="outcome_chart"></div>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<div class="tm-card">
|
|
<div class="tm-card-head"><i class="fas fa-users"></i> @lang('crm::lang.agent_performance')</div>
|
|
<div class="tm-card-body" style="padding:0">
|
|
<table class="table table-striped" style="margin:0" id="top_agents_table">
|
|
<thead><tr><th>@lang('user.name')</th><th>@lang('crm::lang.follow_up_count')</th><th>@lang('crm::lang.lead_score')</th></tr></thead>
|
|
<tbody></tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
@section('javascript')
|
|
<script>
|
|
var outcomeLabels = {
|
|
answered: '@lang("crm::lang.outcome_answered")',
|
|
no_answer: '@lang("crm::lang.outcome_no_answer")',
|
|
busy: '@lang("crm::lang.outcome_busy")',
|
|
callback: '@lang("crm::lang.outcome_callback")',
|
|
wrong_number: '@lang("crm::lang.outcome_wrong_number")',
|
|
not_interested: '@lang("crm::lang.outcome_not_interested")'
|
|
};
|
|
|
|
function loadStats() {
|
|
$.get('{{ action([\Modules\Crm\Http\Controllers\TelemarketingDashboardController::class, "stats"]) }}', function(d) {
|
|
$('#stat_active').text(d.active_calls);
|
|
$('#stat_queue').text(d.queue_remaining);
|
|
$('#stat_rate').text(d.answer_rate + '%');
|
|
$('#stat_companies').text(d.companies_count);
|
|
$('#stat_today_total').text(d.today_total);
|
|
$('#stat_today_answered').text(d.today_answered);
|
|
$('#stat_interested').text(d.interested_today);
|
|
$('#stat_avg_score').text(d.avg_lead_score || '0');
|
|
$('#stat_reception').text(d.avg_assessment || '0');
|
|
|
|
var live = '';
|
|
if ((d.live_sessions || []).length) {
|
|
d.live_sessions.forEach(function(s) {
|
|
live += '<div class="tm-timeline-item"><strong>' + (s.agent_name || '') + '</strong> — ' + (s.mobile_number || '') +
|
|
'<br><small>' + (s.company_name || '') + ' · ' + (s.started_at || '') + '</small></div>';
|
|
});
|
|
} else {
|
|
live = '<p class="text-muted">@lang("crm::lang.no_active_calls")</p>';
|
|
}
|
|
$('#live_calls_body').html(live);
|
|
|
|
var oc = '';
|
|
var outcomes = d.outcomes || {};
|
|
var max = Math.max.apply(null, Object.values(outcomes).concat([1]));
|
|
Object.keys(outcomes).forEach(function(k) {
|
|
var pct = Math.round((outcomes[k] / max) * 100);
|
|
oc += '<div style="margin-bottom:10px"><div class="tm-stat-label">' + (outcomeLabels[k] || k) + ' (' + outcomes[k] + ')</div>' +
|
|
'<div class="tm-progress"><div class="tm-progress-bar" style="width:' + pct + '%"></div></div></div>';
|
|
});
|
|
$('#outcome_chart').html(oc || '<p class="text-muted">—</p>');
|
|
|
|
var tbody = '';
|
|
(d.top_agents || []).forEach(function(a) {
|
|
tbody += '<tr><td>' + a.name + '</td><td>' + a.call_count + '</td><td>' + (parseFloat(a.avg_lead_score) || 0).toFixed(1) + '</td></tr>';
|
|
});
|
|
$('#top_agents_table tbody').html(tbody || '<tr><td colspan="3" class="text-center text-muted">—</td></tr>');
|
|
});
|
|
}
|
|
loadStats();
|
|
setInterval(loadStats, 15000);
|
|
</script>
|
|
@endsection
|