id(); $table->string('type'); // nitro, emulator, sql, config $table->string('action'); // update, build, deploy, fix $table->string('item')->nullable(); // filename, version, etc $table->string('status'); // success, failed, pending $table->text('message')->nullable(); $table->string('user')->nullable(); $table->string('ip')->nullable(); $table->timestamp('created_at')->useCurrent(); $table->index(['type', 'created_at']); $table->index('status'); }); } } public function log(string $type, string $action, ?string $item = null, string $status = 'success', ?string $message = null): void { $this->ensureTableExists(); DB::table(self::TABLE)->insert([ 'type' => $type, 'action' => $action, 'item' => $item, 'status' => $status, 'message' => $message, 'user' => auth()->user()?->name ?? 'System', 'ip' => request()->ip(), 'created_at' => now(), ]); } public function getRecent(int $limit = 50): array { $this->ensureTableExists(); return DB::table(self::TABLE) ->orderBy('created_at', 'desc') ->limit($limit) ->get() ->toArray(); } public function getByType(string $type, int $limit = 50): array { $this->ensureTableExists(); return DB::table(self::TABLE) ->where('type', $type) ->orderBy('created_at', 'desc') ->limit($limit) ->get() ->toArray(); } public function getByStatus(string $status, int $limit = 50): array { $this->ensureTableExists(); return DB::table(self::TABLE) ->where('status', $status) ->orderBy('created_at', 'desc') ->limit($limit) ->get() ->toArray(); } public function getStats(): array { $this->ensureTableExists(); $total = DB::table(self::TABLE)->count(); $success = DB::table(self::TABLE)->where('status', 'success')->count(); $failed = DB::table(self::TABLE)->where('status', 'failed')->count(); $lastUpdate = DB::table(self::TABLE) ->orderBy('created_at', 'desc') ->first(); $byType = DB::table(self::TABLE) ->select('type', DB::raw('count(*) as count')) ->groupBy('type') ->pluck('count', 'type') ->toArray(); return [ 'total' => $total, 'success' => $success, 'failed' => $failed, 'success_rate' => $total > 0 ? round(($success / $total) * 100) : 100, 'last_update' => $lastUpdate, 'by_type' => $byType, ]; } public function getHtml(): string { $this->ensureTableExists(); $updates = $this->getRecent(20); $stats = $this->getStats(); $html = '