@cryptotaxi247 / CoPilot / commits / b881e203

feat: add collapsible sections to agent healthcheck views (#652)

Wraps Healthy and Unhealthy agent sections in collapsible components to improve navigation when working with large numbers of agents. Both sections default to expanded state to maintain existing UX.

oliver-oat committed Feb 3, 2026 at 16:59 UTC b881e203ad15cc70e15c698419e90342f0af62d6
1 file changed +45 -33
frontend/src/components/customers/healthcheck/CustomerHealthcheckList.vue
+45 -33
@@ -15,38 +15,50 @@
15 </div>
16 <n-spin :show="loading">
17 <div class="flex min-h-52 flex-col gap-6">
18 - <div v-if="healthyList.length" class="flex flex-col gap-2 not-last:mb-5">
19 - <div class="text-primary mb-2 flex items-center gap-2">
20 - <Icon :name="CheckIcon" :size="16" />
21 - Healthy
22 - <code>{{ healthyList.length }}</code>
23 - </div>
24 - <CustomerHealthcheckItem
25 - v-for="item of healthyList"
26 - :key="item.id"
27 - :health-data="item"
28 - :source="source"
29 - type="healthy"
30 - embedded
31 - class="item-appear item-appear-bottom item-appear-005"
32 - />
33 - </div>
34 - <div v-if="unhealthyList.length" class="flex flex-col gap-2 not-last:mb-5">
35 - <div class="text-warning mb-2 flex items-center gap-2">
36 - <Icon :name="AlertIcon" :size="16" />
37 - Unhealthy
38 - <code>{{ unhealthyList.length }}</code>
39 - </div>
40 - <CustomerHealthcheckItem
41 - v-for="item of unhealthyList"
42 - :key="item.id"
43 - :health-data="item"
44 - :source="source"
45 - type="unhealthy"
46 - embedded
47 - class="item-appear item-appear-bottom item-appear-005"
48 - />
49 - </div>
18 + <n-collapse v-if="healthyList.length" :default-expanded-names="['healthy']">
19 + <n-collapse-item name="healthy">
20 + <template #header>
21 + <div class="text-primary flex items-center gap-2">
22 + <Icon :name="CheckIcon" :size="16" />
23 + Healthy
24 + <code>{{ healthyList.length }}</code>
25 + </div>
26 + </template>
27 + <div class="flex flex-col gap-2">
28 + <CustomerHealthcheckItem
29 + v-for="item of healthyList"
30 + :key="item.id"
31 + :health-data="item"
32 + :source="source"
33 + type="healthy"
34 + embedded
35 + class="item-appear item-appear-bottom item-appear-005"
36 + />
37 + </div>
38 + </n-collapse-item>
39 + </n-collapse>
40 + <n-collapse v-if="unhealthyList.length" :default-expanded-names="['unhealthy']">
41 + <n-collapse-item name="unhealthy">
42 + <template #header>
43 + <div class="text-warning flex items-center gap-2">
44 + <Icon :name="AlertIcon" :size="16" />
45 + Unhealthy
46 + <code>{{ unhealthyList.length }}</code>
47 + </div>
48 + </template>
49 + <div class="flex flex-col gap-2">
50 + <CustomerHealthcheckItem
51 + v-for="item of unhealthyList"
52 + :key="item.id"
53 + :health-data="item"
54 + :source="source"
55 + type="unhealthy"
56 + embedded
57 + class="item-appear item-appear-bottom item-appear-005"
58 + />
59 + </div>
60 + </n-collapse-item>
61 + </n-collapse>
62 <n-empty v-if="!healthyList.length && !unhealthyList.length && !loading" class="h-48 justify-center" />
63 </div>
64 </n-spin>
@@ -57,7 +69,7 @@ import type { CustomerAgentsHealthcheckQuery } from "@/api/endpoints/customers"
69 import type { CustomerAgentHealth, CustomerHealthcheckSource } from "@/types/customers.d"
70 import { watchDebounced } from "@vueuse/core"
71 import _get from "lodash/get"
60 -import { NEmpty, NInputGroup, NInputNumber, NSelect, NSpin, useMessage } from "naive-ui"
72 +import { NCollapse, NCollapseItem, NEmpty, NInputGroup, NInputNumber, NSelect, NSpin, useMessage } from "naive-ui"
73 import { computed, onBeforeMount, ref, watch } from "vue"
74 import Api from "@/api"
75 import Icon from "@/components/common/Icon.vue"