From c8ddbfd130b2745a23779c76cabd238ee38ee0a0 Mon Sep 17 00:00:00 2001 From: hskwon Date: Mon, 1 Dec 2025 14:57:53 +0900 Subject: [PATCH] =?UTF-8?q?=ED=85=8C=EB=84=8C=ED=8A=B8=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D/=EB=AA=A8=EB=8B=AC=20UI=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 저장소 사용량 표시 추가 (테이블 + 모달) - 이메일/전화번호 컬럼 병합 (연락처) - 전화번호 하이픈 포맷 적용 - 생성일 yymmdd 형식 변경 및 ID 뒤로 이동 - 테이블 헤더 가운데 정렬 - 액션 컬럼을 관리(colspan)로 변경 --- app/Models/Tenants/Tenant.php | 110 ++++++++++++++++++ .../tenants/partials/modal-info.blade.php | 23 ++++ .../views/tenants/partials/table.blade.php | 97 ++++++++------- 3 files changed, 191 insertions(+), 39 deletions(-) diff --git a/app/Models/Tenants/Tenant.php b/app/Models/Tenants/Tenant.php index db04a72a..75cd556a 100644 --- a/app/Models/Tenants/Tenant.php +++ b/app/Models/Tenants/Tenant.php @@ -44,9 +44,13 @@ class Tenant extends Model protected $casts = [ 'max_users' => 'integer', + 'storage_limit' => 'integer', + 'storage_used' => 'integer', 'trial_ends_at' => 'datetime', 'expires_at' => 'datetime', 'last_paid_at' => 'datetime', + 'storage_warning_sent_at' => 'datetime', + 'storage_grace_period_until' => 'datetime', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', @@ -143,4 +147,110 @@ public function getBillingTypeLabelAttribute(): ?string default => $this->billing_tp_code, }; } + + /** + * 저장소 사용률 (%) - Blade 뷰에서 사용 + */ + public function getStorageUsagePercentAttribute(): float + { + $limit = $this->storage_limit ?? 10737418240; // 기본 10GB + if ($limit <= 0) { + return 0; + } + + return round(($this->storage_used ?? 0) / $limit * 100, 1); + } + + /** + * 저장소 사용량 포맷 (예: "2.5 GB / 10 GB") + */ + public function getStorageUsageFormattedAttribute(): string + { + $used = $this->formatBytes($this->storage_used ?? 0); + $limit = $this->formatBytes($this->storage_limit ?? 10737418240); + + return "{$used} / {$limit}"; + } + + /** + * 저장소 사용량만 포맷 (예: "2.5 GB") + */ + public function getStorageUsedFormattedAttribute(): string + { + return $this->formatBytes($this->storage_used ?? 0); + } + + /** + * 저장소 한도만 포맷 (예: "10 GB") + */ + public function getStorageLimitFormattedAttribute(): string + { + return $this->formatBytes($this->storage_limit ?? 10737418240); + } + + /** + * 저장소 상태 배지 색상 (Blade 뷰에서 사용) + */ + public function getStorageBadgeColorAttribute(): string + { + $percent = $this->storage_usage_percent; + + return match (true) { + $percent >= 90 => 'error', + $percent >= 70 => 'warning', + default => 'success', + }; + } + + /** + * 바이트를 읽기 쉬운 형식으로 변환 + */ + protected function formatBytes(int $bytes): string + { + if ($bytes <= 0) { + return '0 B'; + } + + $units = ['B', 'KB', 'MB', 'GB', 'TB']; + $factor = floor(log($bytes, 1024)); + $factor = min($factor, count($units) - 1); + + return round($bytes / pow(1024, $factor), 1).' '.$units[$factor]; + } + + /** + * 전화번호 포맷 (하이픈 추가) + */ + public function getPhoneFormattedAttribute(): ?string + { + if (! $this->phone) { + return null; + } + + // 숫자만 추출 + $numbers = preg_replace('/[^0-9]/', '', $this->phone); + + // 휴대폰 (010, 011, 016, 017, 018, 019) + if (preg_match('/^(01[0-9])(\d{3,4})(\d{4})$/', $numbers, $matches)) { + return $matches[1].'-'.$matches[2].'-'.$matches[3]; + } + + // 서울 (02) + if (preg_match('/^(02)(\d{3,4})(\d{4})$/', $numbers, $matches)) { + return $matches[1].'-'.$matches[2].'-'.$matches[3]; + } + + // 지역번호 (031, 032, ...) + if (preg_match('/^(0\d{2})(\d{3,4})(\d{4})$/', $numbers, $matches)) { + return $matches[1].'-'.$matches[2].'-'.$matches[3]; + } + + // 대표번호 (1588, 1544, ...) + if (preg_match('/^(1\d{3})(\d{4})$/', $numbers, $matches)) { + return $matches[1].'-'.$matches[2]; + } + + // 포맷 불가 시 원본 반환 + return $this->phone; + } } diff --git a/resources/views/tenants/partials/modal-info.blade.php b/resources/views/tenants/partials/modal-info.blade.php index 2ba09421..3886bfc6 100644 --- a/resources/views/tenants/partials/modal-info.blade.php +++ b/resources/views/tenants/partials/modal-info.blade.php @@ -93,6 +93,29 @@ class="px-3 py-1.5 text-sm font-medium text-white bg-green-600 rounded-lg hover: + + {{-- 저장소 사용량 --}} +
+
+ 저장소 사용량 + {{ $tenant->storage_usage_formatted }} +
+
+
+
+
+ {{ $tenant->storage_usage_percent }}% 사용 + @if($tenant->storage_usage_percent >= 90) + 용량 부족 경고 + @elseif($tenant->storage_usage_percent >= 70) + 용량 주의 + @endif +
+
diff --git a/resources/views/tenants/partials/table.blade.php b/resources/views/tenants/partials/table.blade.php index b5fcf06c..8a5d0382 100644 --- a/resources/views/tenants/partials/table.blade.php +++ b/resources/views/tenants/partials/table.blade.php @@ -2,19 +2,19 @@ - - - - + + + + + - - + - - + + @@ -25,6 +25,9 @@ + - - - - + + @else + {{-- 활성 항목 --}} + + + @endif @empty -
ID회사명코드상태ID생성일회사명코드상태 유형이메일전화번호연락처 사용자 부서 메뉴 역할생성일액션사용량관리
{{ $tenant->id }} + {{ $tenant->created_at?->format('ymd') ?? '-' }} +
- {{ $tenant->email ?? '-' }} - - {{ $tenant->phone ?? '-' }} + +
{{ $tenant->email ?? '-' }}
+ @if($tenant->phone) +
{{ $tenant->phone_formatted }}
+ @endif
{{ $tenant->users_count ?? 0 }} @@ -79,39 +82,55 @@ {{ $tenant->roles_count ?? 0 }} - {{ $tenant->created_at?->format('Y-m-d') ?? '-' }} + +
+
+
+
+ {{ $tenant->storage_used_formatted }} +
- @if($tenant->deleted_at) - - - @if(auth()->user()?->is_super_admin) - - @endif + @if($tenant->deleted_at) + {{-- 삭제된 항목 --}} + + + + @if(auth()->user()?->is_super_admin) + @else - - - 수정 - - + - @endif + + 수정 + + + +
+ 등록된 테넌트가 없습니다.