@extends('layouts.manager') @section('title','Тімліди') @section('page_title','Тімліди') @section('page_actions') Додати тімліда @endsection @push('head') @endpush @section('content') @php $tz = config('app.timezone', 'Europe/Kyiv'); $selectedMonth = $selectedMonth ?? \Carbon\Carbon::now($tz)->format('Y-m'); $currentMonthKey = $currentMonthKey ?? \Carbon\Carbon::now($tz)->format('Y-m'); $prevMonthKey = $prevMonthKey ?? \Carbon\Carbon::now($tz)->subMonthNoOverflow()->format('Y-m'); $totalTL = $teamLeads->count(); // ✔ Скільки тімлідів виконали норму по балансах (умовно: balance_score >= 90) $completedNorms = $teamLeads->filter(function ($u) use ($teamLeadRatings) { $rating = $teamLeadRatings[$u->id] ?? null; if (!$rating) return false; $balanceScore = $rating['balance_score'] ?? null; return $balanceScore !== null && $balanceScore >= 90; })->count(); // ✔ Скільки мають високий рейтинг по статистиці (умовно: stats_score >= 70) $highStats = $teamLeads->filter(function ($u) use ($teamLeadRatings) { $rating = $teamLeadRatings[$u->id] ?? null; if (!$rating) return false; $statsScore = $rating['stats_score'] ?? null; return $statsScore !== null && $statsScore >= 70; })->count(); $enriched = $teamLeads->map(function ($u) use ($teamLeadRatings) { $rating = $teamLeadRatings[$u->id] ?? null; $balanceRank = $rating['balance_rank'] ?? null; $statsRank = $rating['stats_rank'] ?? null; $balanceScore = $rating['balance_score'] ?? null; $statsScore = $rating['stats_score'] ?? null; $avgBalanceAmount = $rating['avg_balance_amount'] ?? null; $bestRank = null; if ($balanceRank) $bestRank = $balanceRank; if ($statsRank && ($bestRank === null || $statsRank < $bestRank)) $bestRank = $statsRank; // ✅ Комбінований рейтинг: 40% баланс + 60% статистика $combined = null; if ($balanceScore !== null && $statsScore !== null) { $combined = round(($balanceScore * 0.4) + ($statsScore * 0.6), 2); } return [ 'model' => $u, 'balance_rank' => $balanceRank, 'stats_rank' => $statsRank, 'balance_score' => $balanceScore, 'stats_score' => $statsScore, 'avg_balance' => $avgBalanceAmount, 'best_rank' => $bestRank, 'combined_score' => $combined, ]; }); // ✅ ТОП-3 "по всьому разом" (тільки ті, у кого є і баланс, і статистика) $topThree = $enriched ->filter(fn($row) => $row['combined_score'] !== null) ->sortByDesc('combined_score') ->take(3) ->values(); $ratedCount = $enriched->filter(fn($r) => $r['balance_score'] !== null || $r['stats_score'] !== null)->count(); @endphp {{-- Full width wrapper --}}
{{-- HERO --}}
Рейтинг тімлідів
Хто тягне зміну вгору
Порівнюємо тімлідів по середніх балансах і статистиці за обраний місяць. Загальний рейтинг: 40% баланс + 60% статистика.
{{-- KPI --}}
Всього тімлідів
{{ $totalTL }}
У списку за період
Норма по балансах
{{ $completedNorms }} / {{ $totalTL }}
Balance score ≥ 90
Висока статистика
{{ $highStats }} / {{ $totalTL }}
Stats score ≥ 70
Є рейтинги
{{ $ratedCount }}
З будь-яким score
@if(isset($monthStart, $monthEnd))
{{ $monthStart }} — {{ $monthEnd }}
@endif
Місяць
{{-- TOP 3 --}} @if($topThree->count())
Топ-3 за загальним рейтингом (40% баланс + 60% статистика)
@foreach($topThree as $index => $row) @php /** @var \App\Models\User $uModel */ $uModel = $row['model']; $rank = $index + 1; $balanceScore = $row['balance_score']; $statsScore = $row['stats_score']; $combined = $row['combined_score'] ?? null; $initial = mb_substr($uModel->name, 0, 1, 'UTF-8'); $badgeClass = 'tl-rank-badge'; if ($index === 0) $badgeClass .= ' tl-rank-badge--gold'; if ($index === 1) $badgeClass .= ' tl-rank-badge--silver'; if ($index === 2) $badgeClass .= ' tl-rank-badge--bronze'; @endphp
#{{ $rank }}
Очима
{{ $initial }}
{{ $uModel->name }}
{{ $uModel->email }}
Загальний
{{ $combined !== null ? ($combined.'/100') : '—' }}
Баланс
{{ $balanceScore !== null ? ($balanceScore.'/100') : '—' }}
Статистика
{{ $statsScore !== null ? ($statsScore.'/100') : '—' }}
@endforeach
@endif {{-- DESKTOP TABLE --}}
Повний список тімлідів
Пороги: >70 зелений, >50 жовтий, ≤50 червоний. На вузьких екранах таблиця скролиться по горизонталі
Сортувати
@forelse($teamLeads as $u) @php /** @var \App\Models\User $u */ $cabCount = $u->cabinets->count(); $rating = $teamLeadRatings[$u->id] ?? null; $balanceScore = $rating['balance_score'] ?? null; $statsScore = $rating['stats_score'] ?? null; $balanceRank = $rating['balance_rank'] ?? null; $statsRank = $rating['stats_rank'] ?? null; $avgBalanceAmount = $rating['avg_balance_amount'] ?? null; $combinedScore = null; if ($balanceScore !== null && $statsScore !== null) { $combinedScore = round(($balanceScore * 0.4) + ($statsScore * 0.6), 2); } $balanceClass = 'tl-b-empty'; if ($balanceScore !== null) { if ($balanceScore >= 90) $balanceClass = 'tl-b-good'; elseif ($balanceScore < 60) $balanceClass = 'tl-b-bad'; else $balanceClass = 'tl-b-mid'; } $statsClass = 'tl-b-empty'; if ($statsScore !== null) { if ($statsScore >= 90) $statsClass = 'tl-b-good'; elseif ($statsScore < 60) $statsClass = 'tl-b-bad'; else $statsClass = 'tl-b-mid'; } $bestRank = null; if ($balanceRank) $bestRank = $balanceRank; if ($statsRank && ($bestRank === null || $statsRank < $bestRank)) $bestRank = $statsRank; $topLabel = null; if ($bestRank === 1) $topLabel = 'Топ-1'; elseif ($bestRank === 2) $topLabel = 'Топ-2'; elseif ($bestRank === 3) $topLabel = 'Топ-3'; $initial = mb_substr($u->name, 0, 1, 'UTF-8'); $balancePct = ($balanceScore !== null) ? max(0, min(100, (int)$balanceScore)) : 0; $statsPct = ($statsScore !== null) ? max(0, min(100, (int)$statsScore)) : 0; $balanceProgClass = 'tl-progress--empty'; $balanceHint = 'немає даних'; if ($balanceScore !== null) { if ($balanceScore > 70) { $balanceProgClass = 'tl-progress--good'; $balanceHint = 'високий'; } elseif ($balanceScore > 50) { $balanceProgClass = 'tl-progress--mid'; $balanceHint = 'середній'; } else { $balanceProgClass = 'tl-progress--bad'; $balanceHint = 'низький'; } } $statsProgClass = 'tl-progress--empty'; $statsHint = 'немає даних'; if ($statsScore !== null) { if ($statsScore > 70) { $statsProgClass = 'tl-progress--good'; $statsHint = 'високий'; } elseif ($statsScore > 50) { $statsProgClass = 'tl-progress--mid'; $statsHint = 'середній'; } else { $statsProgClass = 'tl-progress--bad'; $statsHint = 'низький'; } } @endphp @empty @endforelse
Тімлід Email / Очима тімліда Кабінети Рейтинг (баланси) Рейтинг (статистика) Дії
{{ $initial }}
{{ $u->name }}
@php $parts = []; if ($balanceRank) $parts[] = "Баланси: #{$balanceRank} із {$totalTL}"; if ($statsRank) $parts[] = "Статистика: #{$statsRank} із {$totalTL}"; @endphp {!! implode(' ', $parts) !!}
@if($cabCount)
@foreach($u->cabinets as $c) {{ $c->slug }} @endforeach
Всього: {{ $cabCount }}
@else @endif
@if($balanceScore !== null) {{ $balanceScore }} / 100 @else немає даних @endif @if($avgBalanceAmount !== null) {{ number_format($avgBalanceAmount, 2) }} $ @endif
Середній рейтинг по всіх кабінетах (баланси змін). @if($balanceRank)  Місце: #{{ $balanceRank }} @endif
@if($statsScore !== null) {{ $statsScore }} / 100 @else немає даних @endif
New / Young / Old / Spend (середній рейтинг). @if($statsRank)  Місце: #{{ $statsRank }} @endif
Редагувати
Поки немає тімлідів
{{-- MOBILE CARDS --}}
Список тімлідів
@forelse($enriched as $row) @php /** @var \App\Models\User $uModel */ $uModel = $row['model']; $balanceRank = $row['balance_rank']; $statsRank = $row['stats_rank']; $balanceScore = $row['balance_score']; $statsScore = $row['stats_score']; $avgBalance = $row['avg_balance']; $bestRank = $row['best_rank']; $combinedScore = $row['combined_score']; $cabCount = $uModel->cabinets->count(); $balanceClass = 'tl-b-empty'; if ($balanceScore !== null) { if ($balanceScore >= 90) $balanceClass = 'tl-b-good'; elseif ($balanceScore < 60) $balanceClass = 'tl-b-bad'; else $balanceClass = 'tl-b-mid'; } $statsClass = 'tl-b-empty'; if ($statsScore !== null) { if ($statsScore >= 90) $statsClass = 'tl-b-good'; elseif ($statsScore < 60) $statsClass = 'tl-b-bad'; else $statsClass = 'tl-b-mid'; } $initial = mb_substr($uModel->name, 0, 1, 'UTF-8'); $balancePct = ($balanceScore !== null) ? max(0, min(100, (int)$balanceScore)) : 0; $statsPct = ($statsScore !== null) ? max(0, min(100, (int)$statsScore)) : 0; $balanceProgClass = 'tl-progress--empty'; if ($balanceScore !== null) { if ($balanceScore > 70) $balanceProgClass = 'tl-progress--good'; elseif ($balanceScore > 50) $balanceProgClass = 'tl-progress--mid'; else $balanceProgClass = 'tl-progress--bad'; } $statsProgClass = 'tl-progress--empty'; if ($statsScore !== null) { if ($statsScore > 70) $statsProgClass = 'tl-progress--good'; elseif ($statsScore > 50) $statsProgClass = 'tl-progress--mid'; else $statsProgClass = 'tl-progress--bad'; } @endphp
{{ $initial }}
{{ $uModel->name }} @if($topLabel) {{ $topLabel }} @endif
{{ $uModel->email }}
@php $parts = []; if ($balanceRank) $parts[] = "Баланси: #{$balanceRank}/{$totalTL}"; if ($statsRank) $parts[] = "Статистика: #{$statsRank}/{$totalTL}"; @endphp @if(count($parts))
{!! implode(' ', $parts) !!}
@endif
Баланси
@if($balanceScore !== null)
{{ $balanceScore }}/100 @if($avgBalance !== null) {{ number_format($avgBalance, 2) }} $ @endif
@else немає даних @endif
Статистика
@if($statsScore !== null) {{ $statsScore }}/100
@else немає даних @endif
Кабінети
@if($cabCount)
@foreach($uModel->cabinets as $c) {{ $c->slug }} @endforeach
Всього: {{ $cabCount }}
@else Тімлід ще не привʼязаний до кабінетів @endif
@empty
Поки немає тімлідів
@endforelse
@endsection @push('scripts') @endpush