diff --git a/Procfile b/Procfile deleted file mode 100644 index ff2e296..0000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: php artisan migrate --force && php artisan db:seed --force && frankenphp run --config /Caddyfile diff --git a/app/Http/Controllers/Api/DoorAccessController.php b/app/Http/Controllers/Api/DoorAccessController.php index d347d50..ec9cd6c 100644 --- a/app/Http/Controllers/Api/DoorAccessController.php +++ b/app/Http/Controllers/Api/DoorAccessController.php @@ -102,6 +102,9 @@ public function receiveData(Request $request): JsonResponse 'recorded_at' => $recordedAt ]); + // Tandai device sebagai online + Device::markOnline($data['device_id']); + // Jika akses mencurigakan atau tidak sah, buat alert dan kirim notifikasi $alertSent = false; if ($isSuspicious || !$isAuthorizedAccess || $accessType === 'forced_entry') { diff --git a/app/Http/Controllers/Api/PirController.php b/app/Http/Controllers/Api/PirController.php index 711d8a3..8ee250a 100644 --- a/app/Http/Controllers/Api/PirController.php +++ b/app/Http/Controllers/Api/PirController.php @@ -91,6 +91,9 @@ public function receiveData(Request $request): JsonResponse 'recorded_at' => $recordedAt ]); + // Tandai device sebagai online + Device::markOnline($data['device_id']); + // Jika gerakan mencurigakan, buat alert dan kirim notifikasi $alertSent = false; if ($isSuspicious || $motionType === 'unauthorized') { diff --git a/app/Http/Controllers/Api/ReedSwitchController.php b/app/Http/Controllers/Api/ReedSwitchController.php index 70e6b37..8f0776c 100644 --- a/app/Http/Controllers/Api/ReedSwitchController.php +++ b/app/Http/Controllers/Api/ReedSwitchController.php @@ -112,6 +112,9 @@ public function receiveData(Request $request): JsonResponse 'recorded_at' => $recordedAt ]); + // Tandai device sebagai online + Device::markOnline($data['device_id']); + // Jika akses tidak sah atau pembukaan paksa, buat alert dan kirim notifikasi $alertSent = false; if ($isUnauthorized || $isForcedEntry || $accessLevel !== 'normal') { diff --git a/app/Http/Controllers/Api/VibrationController.php b/app/Http/Controllers/Api/VibrationController.php index 3a60f21..c341108 100644 --- a/app/Http/Controllers/Api/VibrationController.php +++ b/app/Http/Controllers/Api/VibrationController.php @@ -68,6 +68,9 @@ public function receiveData(Request $request): JsonResponse 'recorded_at' => now() ]); + // Tandai device sebagai online + Device::markOnline($data['device_id']); + // Jika getaran abnormal, buat alert dan kirim notifikasi if ($isAbnormal) { $this->handleAbnormalVibration($vibrationReading); diff --git a/app/Models/Device.php b/app/Models/Device.php index d246c36..3c02a5c 100644 --- a/app/Models/Device.php +++ b/app/Models/Device.php @@ -65,6 +65,28 @@ public function scopeActive($query) return $query->where('is_active', true); } + /** + * Cek apakah device benar-benar online berdasarkan last_seen (dalam 2 menit terakhir) + */ + public function getIsOnlineAttribute(): bool + { + if (!$this->last_seen) { + return false; + } + return $this->last_seen->diffInMinutes(now()) <= 2; + } + + /** + * Update status device ke online dan catat last_seen + */ + public static function markOnline(int $deviceId): void + { + static::where('id', $deviceId)->update([ + 'status' => 'online', + 'last_seen' => now(), + ]); + } + // Accessor untuk status badge color public function getStatusColorAttribute() { diff --git a/app/Models/User.php b/app/Models/User.php index 749c7b7..bfbd5d6 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -21,8 +21,32 @@ class User extends Authenticatable 'name', 'email', 'password', + 'profile_photo', ]; + /** + * URL foto profil — fallback ke null jika tidak ada + */ + public function getProfilePhotoUrlAttribute(): ?string + { + if ($this->profile_photo) { + return asset('storage/' . $this->profile_photo); + } + return null; + } + + /** + * Inisial nama untuk avatar fallback + */ + public function getInitialsAttribute(): string + { + $words = explode(' ', trim($this->name)); + if (count($words) >= 2) { + return strtoupper(substr($words[0], 0, 1) . substr($words[1], 0, 1)); + } + return strtoupper(substr($this->name, 0, 2)); + } + /** * The attributes that should be hidden for serialization. * diff --git a/database/migrations/2026_05_22_000001_add_profile_photo_to_users_table.php b/database/migrations/2026_05_22_000001_add_profile_photo_to_users_table.php new file mode 100644 index 0000000..0d54b5d --- /dev/null +++ b/database/migrations/2026_05_22_000001_add_profile_photo_to_users_table.php @@ -0,0 +1,22 @@ +string('profile_photo')->nullable()->after('email'); + }); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('profile_photo'); + }); + } +}; diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 4b15a0c..7cd11ff 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -118,13 +118,19 @@
Admin
+{{ auth()->user()->name }}
System Operator
Online