check() && auth()->user()->can('viewAny', \Paymenter\Extensions\Servers\ManualServers\ManualServers::class); } public function table(Table $table): Table { return $table ->query( Service::query() ->whereHas('product.server', function ($query) { $query->where('extension', 'ManualServers'); }) ->with(['user', 'product', 'product.server', 'properties']) ->orderBy('created_at', 'desc') ) ->columns([ TextColumn::make('id') ->label('Service ID') ->prefix('#') ->sortable(), TextColumn::make('user.name') ->label('Client') ->description(fn (Service $record) => $record->user->email) ->searchable(), TextColumn::make('product.name') ->label('Product') ->sortable() ->searchable(), TextColumn::make('deploy_status') ->label('Server Status') ->state(fn (Service $record): string => $record->properties->where('key', 'deploy_status')->first()?->value ?? 'pending') ->badge() ->formatStateUsing(fn (string $state): string => ucfirst($state)) ->color(fn (string $state): string => match ($state) { 'deployed' => 'success', 'suspended' => 'danger', 'terminated' => 'gray', default => 'warning', }), TextColumn::make('progress') ->label('Setup Progress') ->state(function (Service $record): string { $processesJson = $record->properties->where('key', 'processes_data')->first()?->value ?? '[]'; $processes = json_decode($processesJson, true) ?? []; $total = count($processes); $completed = collect($processes)->where('completed', true)->count(); return "{$completed} / {$total} steps"; }) ->description(function (Service $record): string { $processesJson = $record->properties->where('key', 'processes_data')->first()?->value ?? '[]'; $processes = json_decode($processesJson, true) ?? []; $lastCompleted = collect($processes)->where('completed', true)->last(); return $lastCompleted ? 'Last completed: ' . $lastCompleted['name'] : 'Setup not started'; }), TextColumn::make('sla_elapsed') ->label('Elapsed') ->state(fn (Service $record): string => $record->created_at->diffForHumans(now(), true)) ->description(function (Service $record): string { $deadline = $record->created_at->copy()->addHours($this->getSlaHours($record)); return 'SLA deadline: ' . $deadline->format('M d, Y H:i'); }), TextColumn::make('sla_status') ->label('SLA') ->badge() ->state(function (Service $record): string { $status = $record->properties->where('key', 'deploy_status')->first()?->value ?? 'pending'; if ($status === 'deployed') { return 'met'; } $deadline = $record->created_at->copy()->addHours($this->getSlaHours($record)); return now()->gt($deadline) ? 'overdue' : 'on-time'; }) ->color(fn (string $state): string => match ($state) { 'met' => 'success', 'overdue' => 'danger', default => 'warning', }) ->formatStateUsing(fn (string $state): string => match ($state) { 'met' => 'Met', 'overdue' => 'Overdue', default => 'On time', }), TextColumn::make('created_at') ->label('Order Date') ->dateTime() ->sortable(), ]) ->recordUrl(fn (Service $record): string => ManualServersManage::getUrl(['service' => $record->id])) ->defaultSort('created_at', 'desc'); } protected function getSlaHours(Service $service): int { $value = $service->product->settings->where('key', 'sla_hours')->first()?->value; return max(1, (int) ($value ?: 24)); } }