'boolean']; public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Return merged widget config: defaults overlaid with user prefs. * * @return array */ public static function forUser(int $userId): array { $defaults = self::defaults(); $prefs = self::where('user_id', $userId) ->get() ->keyBy('widget_key'); foreach ($defaults as $key => &$widget) { if ($prefs->has($key)) { $widget['visible'] = $prefs[$key]->visible; $widget['sort_order'] = $prefs[$key]->sort_order; } } uasort($defaults, fn ($a, $b) => $a['sort_order'] <=> $b['sort_order']); return $defaults; } /** * All available widgets with their defaults. */ public static function defaults(): array { return [ 'cpu' => ['label' => 'CPU Load', 'visible' => true, 'sort_order' => 1, 'permission' => null], 'ram' => ['label' => 'Memory', 'visible' => true, 'sort_order' => 2, 'permission' => null], 'disk' => ['label' => 'Storage', 'visible' => true, 'sort_order' => 3, 'permission' => null], 'live_users' => ['label' => 'Live Users', 'visible' => true, 'sort_order' => 4, 'permission' => null], 'queues' => ['label' => 'Queue Stats', 'visible' => true, 'sort_order' => 5, 'permission' => null], 'activity_feed' => ['label' => 'Activity Feed', 'visible' => true, 'sort_order' => 6, 'permission' => 'view health and logs'], 'ai_insight' => ['label' => 'AI Security Insight','visible' => true, 'sort_order' => 7, 'permission' => 'view ai log analysis'], ]; } }