main
vue 69 lines 1.79 KB
Raw
1 <template>
2 <div class="services-list">
3 <div v-if="!hideTotals" class="header mb-4 flex items-center justify-between gap-2">
4 <div>
5 Total:
6 <strong class="font-mono">{{ total }}</strong>
7 </div>
8 </div>
9 <n-spin :show="loading">
10 <div class="min-h-52">
11 <template v-if="list.length">
12 <ServiceItem
13 v-for="item of list"
14 :key="item.id"
15 :type
16 :data="item"
17 :embedded
18 :selectable="isSelectable(item)"
19 :disabled="isDisabled(item)"
20 :checked="selected?.id === item.id"
21 class="item-appear item-appear-bottom item-appear-005 mb-2"
22 @click="setItem(item)"
23 />
24 </template>
25 <template v-else>
26 <n-empty v-if="!loading" description="No items found" class="h-48 justify-center" />
27 </template>
28 </div>
29 </n-spin>
30 </div>
31 </template>
32
33 <script setup lang="ts">
34 import type { ServiceItemData, ServiceItemType } from "./types"
35 import { NEmpty, NSpin } from "naive-ui"
36 import { computed, toRefs } from "vue"
37 import ServiceItem from "./Item.vue"
38
39 const props = defineProps<{
40 type: ServiceItemType
41 list: ServiceItemData[]
42 embedded?: boolean
43 loading?: boolean
44 hideTotals?: boolean
45 selectable?: boolean
46 disabledIdsList?: (string | number)[]
47 }>()
48 const { type, list, embedded, hideTotals, selectable, disabledIdsList } = toRefs(props)
49
50 const selected = defineModel<ServiceItemData | null>("selected", { default: null })
51
52 const total = computed<number>(() => {
53 return list.value.length || 0
54 })
55
56 function isDisabled(item: ServiceItemData) {
57 return (disabledIdsList.value || []).includes(item.id)
58 }
59
60 function isSelectable(item: ServiceItemData) {
61 return selectable.value && !isDisabled(item)
62 }
63
64 function setItem(item: ServiceItemData) {
65 if (!isDisabled(item)) {
66 selected.value = selected.value?.id === item.id ? null : item
67 }
68 }
69 </script>