126 lines
4.2 KiB
PHP
126 lines
4.2 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Dashboard;
|
|
|
|
use App\Models\ActivityLog;
|
|
use App\Models\ServiceRequest;
|
|
use App\Models\Status;
|
|
use App\Models\User;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Component;
|
|
|
|
#[Layout('layouts.app')]
|
|
class DashboardPage extends Component
|
|
{
|
|
public int $openToday = 0;
|
|
|
|
public int $overdue = 0;
|
|
|
|
public float $avgResolutionHours = 0;
|
|
|
|
public array $statusChart = [];
|
|
|
|
public array $priorityChart = [];
|
|
|
|
public array $topTechnicians = [];
|
|
|
|
public array $recentActivities = [];
|
|
|
|
public array $upcomingTasks = [];
|
|
|
|
public function mount(): void
|
|
{
|
|
abort_unless(auth()->user()->isAdmin() || auth()->user()->isManager(), 403);
|
|
$this->refreshData();
|
|
}
|
|
|
|
public function refreshData(): void
|
|
{
|
|
$this->openToday = ServiceRequest::query()
|
|
->open()
|
|
->whereDate('created_at', now()->toDateString())
|
|
->count();
|
|
|
|
$this->overdue = ServiceRequest::query()->overdue()->count();
|
|
|
|
$this->avgResolutionHours = (float) (ServiceRequest::query()
|
|
->whereNotNull('completed_at')
|
|
->whereDate('completed_at', '>=', now()->subDays(30))
|
|
->selectRaw('AVG(TIMESTAMPDIFF(HOUR, created_at, completed_at)) as avg_hours')
|
|
->value('avg_hours') ?? 0);
|
|
|
|
$this->statusChart = Status::query()
|
|
->orderBy('sort_order')
|
|
->get()
|
|
->map(fn (Status $status) => [
|
|
'label' => $status->name,
|
|
'value' => ServiceRequest::query()->where('status_id', $status->id)->count(),
|
|
'color' => $status->color_hex,
|
|
])
|
|
->toArray();
|
|
|
|
$this->priorityChart = ServiceRequest::query()
|
|
->join('priorities', 'priorities.id', '=', 'requests.priority_id')
|
|
->selectRaw('priorities.name as label, priorities.color_hex as color, COUNT(requests.id) as value')
|
|
->groupBy('priorities.id', 'priorities.name', 'priorities.color_hex')
|
|
->orderByRaw('MIN(priorities.level)')
|
|
->get()
|
|
->map(fn ($row) => [
|
|
'label' => $row->label,
|
|
'value' => (int) $row->value,
|
|
'color' => $row->color,
|
|
])
|
|
->toArray();
|
|
|
|
$this->topTechnicians = User::query()
|
|
->where('role', 'technician')
|
|
->withCount([
|
|
'assignedRequests as closed_requests_count' => fn (Builder $query) => $query->whereHas('status', fn (Builder $status) => $status->where('slug', 'closed')),
|
|
])
|
|
->orderByDesc('closed_requests_count')
|
|
->limit(5)
|
|
->get()
|
|
->map(fn (User $user) => [
|
|
'name' => $user->name,
|
|
'closed_requests_count' => (int) $user->closed_requests_count,
|
|
])
|
|
->toArray();
|
|
|
|
$this->recentActivities = ActivityLog::query()
|
|
->with('user')
|
|
->latest('created_at')
|
|
->limit(10)
|
|
->get()
|
|
->map(fn (ActivityLog $log) => [
|
|
'user' => $log->user?->name ?? 'Система',
|
|
'action' => $log->action,
|
|
'description' => $log->description,
|
|
'created_at' => $log->created_at?->format('d.m.Y H:i'),
|
|
])
|
|
->toArray();
|
|
|
|
$this->upcomingTasks = ServiceRequest::query()
|
|
->with(['assignee', 'status'])
|
|
->whereNotNull('planned_at')
|
|
->whereBetween('planned_at', [now(), now()->addDays(7)])
|
|
->orderBy('planned_at')
|
|
->limit(8)
|
|
->get()
|
|
->map(fn (ServiceRequest $request) => [
|
|
'ticket' => $request->ticket_number,
|
|
'title' => $request->title,
|
|
'planned_at' => $request->planned_at?->format('d.m.Y H:i'),
|
|
'assignee' => $request->assignee?->name ?? 'Не назначен',
|
|
])
|
|
->toArray();
|
|
|
|
$this->dispatch('dashboard-charts-updated', status: $this->statusChart, priority: $this->priorityChart);
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.dashboard.dashboard-page')->title('Дашборд');
|
|
}
|
|
}
|