diff --git a/app/Services/DiskSpaceService.php b/app/Services/DiskSpaceService.php new file mode 100644 index 0000000..2d39d2e --- /dev/null +++ b/app/Services/DiskSpaceService.php @@ -0,0 +1,75 @@ +path(''); + + /** @var array{total_bytes: int, free_bytes: int, used_bytes: int, used_percent: float, free_percent: float, total_human: string, free_human: string, used_human: string}|null */ + return Cache::remember( + 'disk-space:'.md5($path), + now()->addSeconds(30), + fn () => $this->measure($path), + ); + } + + /** + * @return array{ + * total_bytes: int, + * free_bytes: int, + * used_bytes: int, + * used_percent: float, + * free_percent: float, + * total_human: string, + * free_human: string, + * used_human: string + * }|null + */ + private function measure(string $path): ?array + { + $total = @disk_total_space($path); + $free = @disk_free_space($path); + + if ($total === false || $free === false || $total <= 0) { + return null; + } + + $totalBytes = (int) $total; + $freeBytes = (int) max(0, $free); + $usedBytes = (int) max(0, $totalBytes - $freeBytes); + $usedPercent = round(($usedBytes / $totalBytes) * 100, 1); + $freePercent = round(($freeBytes / $totalBytes) * 100, 1); + + return [ + 'total_bytes' => $totalBytes, + 'free_bytes' => $freeBytes, + 'used_bytes' => $usedBytes, + 'used_percent' => $usedPercent, + 'free_percent' => $freePercent, + 'total_human' => Number::fileSize($totalBytes, precision: 1), + 'free_human' => Number::fileSize($freeBytes, precision: 1), + 'used_human' => Number::fileSize($usedBytes, precision: 1), + ]; + } +} diff --git a/app/View/Components/DiskSpaceBar.php b/app/View/Components/DiskSpaceBar.php new file mode 100644 index 0000000..904aeeb --- /dev/null +++ b/app/View/Components/DiskSpaceBar.php @@ -0,0 +1,61 @@ +disk = $diskSpace->snapshot(); + } + + public function shouldRender(): bool + { + return $this->disk !== null; + } + + /** + * Progress fill color based on remaining free space. + */ + public function barColor(): string + { + $freePercent = $this->disk['free_percent'] ?? 100; + + if ($freePercent <= 5) { + return 'bg-red-600'; + } + + if ($freePercent <= 15) { + return 'bg-amber-500'; + } + + return 'bg-teal-600'; + } + + /** + * Get the view / contents that represent the component. + */ + public function render(): View|Closure|string + { + return view('components.disk-space-bar'); + } +} diff --git a/resources/views/components/disk-space-bar.blade.php b/resources/views/components/disk-space-bar.blade.php new file mode 100644 index 0000000..eb81405 --- /dev/null +++ b/resources/views/components/disk-space-bar.blade.php @@ -0,0 +1,29 @@ +@php + /** @var array{used_percent: float, free_percent: float, free_human: string, total_human: string, used_human: string} $disk */ +@endphp +