@paris-ias/list 1.0.137 → 1.0.139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/actions/DenseItem.vue +64 -0
  3. package/dist/runtime/components/actions/ExpandedItem.vue +17 -14
  4. package/dist/runtime/components/actions/RowsItem.vue +56 -10
  5. package/dist/runtime/components/actions/View.vue +5 -17
  6. package/dist/runtime/components/affiliation/DenseItem.vue +26 -10
  7. package/dist/runtime/components/affiliation/RowsItem.vue +26 -10
  8. package/dist/runtime/components/apps/DenseItem.vue +26 -10
  9. package/dist/runtime/components/apps/RowsItem.vue +26 -10
  10. package/dist/runtime/components/disciplines/DenseItem.vue +26 -10
  11. package/dist/runtime/components/disciplines/RowsItem.vue +26 -10
  12. package/dist/runtime/components/events/DenseItem.vue +12 -3
  13. package/dist/runtime/components/events/RowsItem.vue +12 -5
  14. package/dist/runtime/components/fellowships/DenseItem.vue +14 -0
  15. package/dist/runtime/components/fellowships/RowsItem.vue +16 -2
  16. package/dist/runtime/components/fellowships/View.vue +2 -2
  17. package/dist/runtime/components/files/DenseItem.vue +25 -10
  18. package/dist/runtime/components/files/RowsItem.vue +26 -10
  19. package/dist/runtime/components/list/atoms/FiltersMenu.vue +9 -0
  20. package/dist/runtime/components/list/atoms/PerPage.vue +3 -2
  21. package/dist/runtime/components/list/atoms/ResetButton.vue +5 -1
  22. package/dist/runtime/components/list/atoms/SearchInput.vue +15 -2
  23. package/dist/runtime/components/list/atoms/SearchString.vue +169 -133
  24. package/dist/runtime/components/list/atoms/SortMenu.vue +22 -18
  25. package/dist/runtime/components/list/atoms/ViewMenu.vue +26 -14
  26. package/dist/runtime/components/list/molecules/Filters.vue +4 -4
  27. package/dist/runtime/components/list/molecules/GlobalSearchInput.vue +12 -14
  28. package/dist/runtime/components/list/molecules/Header.vue +11 -20
  29. package/dist/runtime/components/list/molecules/Pagination.vue +51 -48
  30. package/dist/runtime/components/list/molecules/ResultsContainer.vue +5 -2
  31. package/dist/runtime/components/list/organisms/List.vue +105 -74
  32. package/dist/runtime/components/list/organisms/Results.vue +31 -17
  33. package/dist/runtime/components/mailing/RowsItem.vue +26 -10
  34. package/dist/runtime/components/news/DenseItem.vue +59 -45
  35. package/dist/runtime/components/news/RowsItem.vue +11 -7
  36. package/dist/runtime/components/people/DenseItem.vue +10 -8
  37. package/dist/runtime/components/people/RowsItem.vue +11 -2
  38. package/dist/runtime/components/projects/DenseItem.vue +11 -4
  39. package/dist/runtime/components/projects/RowsItem.vue +10 -3
  40. package/dist/runtime/components/publications/DenseItem.vue +12 -8
  41. package/dist/runtime/components/publications/RowsItem.vue +12 -4
  42. package/dist/runtime/components/tags/RowsItem.vue +23 -10
  43. package/dist/runtime/components/users/DenseItem.vue +24 -10
  44. package/dist/runtime/components/users/RowsItem.vue +24 -10
  45. package/dist/runtime/composables/useUtils.js +1 -1
  46. package/dist/runtime/plugins/pinia.js +5 -2
  47. package/dist/runtime/stores/root.d.ts +10 -9
  48. package/dist/runtime/stores/root.js +82 -117
  49. package/package.json +1 -1
@@ -1,34 +1,30 @@
1
1
  <template>
2
2
  <ListMoleculesHeader :type="type" />
3
- <component :is="view">
3
+ <component
4
+ :is="view"
5
+ :loading="$stores[type] && $stores[type].loading && pending"
6
+ >
4
7
  <component
5
8
  :is="itemTemplate"
6
9
  v-for="(item, index) in items"
7
- :key="index"
8
- :item="item"
9
- :index="index"
10
+ :key="(item.name || item.lastname) + type + index"
11
+ :item
12
+ :index
13
+ :loading="$stores[type] && $stores[type].loading && pending"
10
14
  :pathPrefix="
11
- localePath({
12
- name: pathPrefix,
13
- params: { slug: item.slug },
14
- })
15
+ localePath({ name: pathPrefix, params: { slug: item.slug } })
15
16
  "
16
17
  />
17
18
  </component>
18
19
  <div class="text-center">
19
- <ListAtomsPerPage
20
- v-if="numberOfPages > 1"
21
- :type="type"
22
- class="float-right"
23
- />
20
+ <ListAtomsPerPage :type="type" class="float-right" />
24
21
 
25
22
  <ListMoleculesPagination
26
- v-if="numberOfPages > 1"
27
- :type="type"
28
- color="black"
23
+ v-if="$stores[type].numberOfPages > 1"
24
+ :type
29
25
  large
30
- :current-page="page"
31
- :total-pages="numberOfPages"
26
+ :current-page="$stores[type].page"
27
+ :total-pages="$stores[type].numberOfPages"
32
28
  :page-padding="1"
33
29
  :page-gap="2"
34
30
  :hide-prev-next="false"
@@ -38,21 +34,20 @@
38
34
  </template>
39
35
 
40
36
  <script setup>
41
- import { nextTick, watch } from "vue"
37
+ import { computed, onUpdated, onMounted, watch } from "vue"
42
38
  import { useRootStore } from "../../../stores/root"
43
39
  import { capitalize } from "../../../composables/useUtils"
44
40
  import {
45
41
  useNuxtApp,
46
42
  resolveComponent,
47
- computed,
48
43
  onBeforeUnmount,
49
- onMounted,
50
44
  useI18n,
51
45
  useRoute,
52
- navigateTo,
53
46
  useLocalePath,
47
+ useAsyncQuery,
54
48
  } from "#imports"
55
- const { $stores } = useNuxtApp()
49
+
50
+ const { $stores, $queries } = useNuxtApp()
56
51
  const { locale } = useI18n()
57
52
  const route = useRoute()
58
53
  const rootStore = useRootStore()
@@ -69,7 +64,7 @@ const props = defineProps({
69
64
  default: "people",
70
65
  required: true,
71
66
  },
72
- layout: {
67
+ /* layout: {
73
68
  type: Object,
74
69
  required: false,
75
70
  default: () => {
@@ -78,94 +73,130 @@ const props = defineProps({
78
73
  xl: 12,
79
74
  }
80
75
  },
81
- },
76
+ }, */
82
77
  pathPrefix: {
83
78
  type: String,
84
79
  required: true,
85
80
  },
86
- pagination: {
87
- type: Object,
88
- required: false,
89
- default: () => {
90
- return {}
91
- },
92
- },
81
+
93
82
  addButton: {
94
83
  type: Boolean,
95
84
  required: false,
96
85
  default: false,
97
86
  },
98
- items: [Object],
99
87
  })
100
88
 
89
+ // Initialize loading state
90
+ console.log("start llocal loading from setup")
91
+ rootStore.setLoading(true, props.type)
92
+
93
+ // Initial route -> store (single source-of-truth on first load)
94
+ rootStore.loadRouteQuery(props.type)
95
+
96
+ // Computed properties for dynamic components
101
97
  const view = computed(() =>
102
98
  props.customView
103
99
  ? resolveComponent("ListViews" + capitalize(props.customView))
104
- : resolveComponent("ListViews" + capitalize($stores[props.type].view.name)),
100
+ : resolveComponent(
101
+ "ListViews" + capitalize($stores[props.type]?.view?.name || "list"),
102
+ ),
105
103
  )
106
104
  const itemTemplate = computed(() =>
107
105
  resolveComponent(
108
106
  (
109
107
  capitalize(props.type) +
110
- capitalize($stores[props.type].view.name) +
108
+ capitalize($stores[props.type]?.view?.name || "list") +
111
109
  "Item"
112
110
  ).toString(),
113
111
  ),
114
112
  )
115
- const numberOfPages = computed(() => $stores[props.type].numberOfPages)
116
113
 
117
- const page = computed(() => {
118
- const p = parseInt(route.query.page, 10)
119
- return !isNaN(p) && p > 0 ? p : 1
114
+ // Apollo: reactive query using variables computed from store
115
+ const variables = computed(() => {
116
+ console.log("computed variables loop")
117
+ return rootStore.buildListVariables(props.type, locale.value)
120
118
  })
119
+ console.log("Starting query for type: ", props.type)
120
+ console.log("Using variables: ", variables.value)
121
121
 
122
- const items = computed(() => $stores[props.type].items)
123
- console.log("setup list")
124
-
125
- // On mounted: load filters and data
126
- onMounted(async () => {
127
- // Load any route filters
128
- rootStore.loadRouteQuery(props.type)
129
- // Initialize store page from URL
130
- const pageParam = parseInt(route.query.page, 10)
131
- if (!isNaN(pageParam) && pageParam > 1) {
132
- await rootStore.updatePage({
133
- page: pageParam,
134
- type: props.type,
135
- lang: locale.value,
136
- })
137
- }
138
- // Fetch initial items
139
- try {
140
- await rootStore.update(props.type, locale.value)
141
- } catch (e) {
142
- console.error("Error fetching list:", e)
143
- }
144
- })
122
+ // Apollo GraphQL query with proper reactivity
123
+ const { data, pending, error, refresh } = await useAsyncQuery(
124
+ $queries[props.type]?.list,
125
+ variables, // Pass the reactive computed, not its value
126
+ {
127
+ key: `list-${props.type}`, // Unique key for caching
128
+ server: true, // Enable SSR
129
+ },
130
+ )
131
+ if (error.value) {
132
+ console.error("GraphQL query error: ", error.value)
133
+ } else {
134
+ console.log("Query result data: ", data.value.items?.length)
135
+ }
145
136
 
137
+ // Apply data to store immediately if available
138
+ if (data.value) {
139
+ console.log("Applying data to store directly [first load scenario]")
140
+ rootStore.applyListResult(props.type, data.value)
141
+ }
142
+
143
+ // Watch for variable changes to refresh and apply new data
146
144
  watch(
147
- () => page.value,
148
- async (newPage) => {
149
- const query = {
150
- ...route.query,
151
- page: newPage > 1 ? String(newPage) : undefined,
145
+ variables,
146
+ async (newVars, oldVars) => {
147
+ if (newVars && JSON.stringify(newVars) !== JSON.stringify(oldVars)) {
148
+ console.log("Variables changed, refreshing query, newVars: ", newVars)
149
+ console.log("start local loading from computed")
150
+ rootStore.setLoading(true, props.type)
151
+ await refresh()
152
+ if (data.value) {
153
+ console.log("Applying refreshed data to store")
154
+ rootStore.applyListResult(props.type, data.value)
155
+ }
156
+ rootStore.setLoading(false, props.type)
152
157
  }
153
- navigateTo({ query }, { replace: true })
154
- await nextTick()
155
- window.scrollTo({ top: 0, behavior: "smooth" })
156
158
  },
159
+ { deep: true },
157
160
  )
161
+
162
+ // Reactive items computed from the store (single source of truth)
163
+ const items = computed(() => $stores[props.type]?.items || [])
164
+
165
+ onMounted(() => {
166
+ // On initial mount: clear loading state
167
+ console.log("STOP local loading from mounted")
168
+ rootStore.setLoading(false, props.type)
169
+ })
170
+
158
171
  onBeforeUnmount(() => {
159
172
  rootStore.resetState(props.type, locale.value)
160
173
  })
161
-
162
174
  async function onPageChange(newPage) {
163
- await rootStore.updatePage({
175
+ console.log("onPageChange: ", newPage)
176
+
177
+ // Set loading state first
178
+ rootStore.setLoading(true, props.type)
179
+
180
+ // Update the page in the store
181
+ rootStore.updatePage({
164
182
  page: newPage,
165
183
  type: props.type,
166
184
  lang: locale.value,
167
185
  })
168
- }
169
186
 
170
- console.log("pathPrefix", itemTemplate.value)
187
+ // Wait for the next tick to ensure DOM updates
188
+ await nextTick()
189
+
190
+ // Use setTimeout to ensure the scroll happens after route transition completes
191
+ setTimeout(() => {
192
+ if (typeof window !== "undefined") {
193
+ window.scrollTo({ top: 0, behavior: "smooth" })
194
+ }
195
+ }, 0)
196
+ }
197
+ /*
198
+ onUpdated(() => {
199
+ console.log("STOP local loading from updated")
200
+ rootStore.setLoading(false, props.type)
201
+ }) */
171
202
  </script>
@@ -4,6 +4,7 @@
4
4
  :placeholder="$t('search')"
5
5
  variant="outlined"
6
6
  :categories="selectedCategories"
7
+ @change="updateSearch($event)"
7
8
  @filter-change="handleFilterChange"
8
9
  />
9
10
  <ListMoleculesResultsContainer
@@ -31,8 +32,9 @@ import {
31
32
  useAppConfig,
32
33
  ref,
33
34
  computed,
35
+ watch,
34
36
  } from "#imports"
35
-
37
+ import SEARCH from "../../../graphql/list/search.gql"
36
38
  // Component name for linting
37
39
  defineOptions({
38
40
  name: "SearchResults",
@@ -70,24 +72,36 @@ const filteredSortedModules = computed(() => {
70
72
  )
71
73
  })
72
74
 
73
- onMounted(async () => {
74
- // Initialize the page from the route
75
- console.log("mounted list")
76
-
77
- try {
78
- await $rootStore.update("all", locale.value)
75
+ // Apollo GraphQL query with proper reactivity
76
+ const { data, pending, error, refresh } = await useAsyncQuery(
77
+ SEARCH,
78
+ { search: $rootStore.search, appId: "iea", locale: locale.value },
79
+ {
80
+ key: `search-${$rootStore.search}`, // Unique key for caching
81
+ server: true, // Enable SSR
82
+ },
83
+ )
84
+ if (error.value) {
85
+ console.error("GraphQL query error: ", error.value)
86
+ } else {
87
+ console.log("Query result data: ", data.value.items?.length)
88
+ }
79
89
 
80
- // Set all types to be expanded by default when they have results
81
- appConfig.list.modules.forEach((type) => {
82
- if ($rootStore.results[type]?.total > 0) {
83
- open.value[type] = true
84
- }
85
- })
86
- } catch (error) {
87
- console.log("error fetching update list: ", error)
90
+ // Apply data to store immediately if available
91
+ if (data.value) {
92
+ console.log("Applying data to store directly [first load scenario]")
93
+ $rootStore.applyListResult("all", data.value)
94
+ }
95
+ const updateSearch = async (newSearch) => {
96
+ console.log("update search")
97
+ if (newSearch !== $rootStore.search) {
98
+ await refresh()
99
+ if (data.value) {
100
+ console.log("Applying data to store directly [first load scenario]")
101
+ $rootStore.applyListResult("all", data.value)
102
+ }
88
103
  }
89
- })
90
-
104
+ }
91
105
  onBeforeUnmount(() => {
92
106
  /* rootStore.resetState("all", locale.value) */
93
107
  })
@@ -1,18 +1,34 @@
1
1
  <template>
2
- {{ item }}
2
+ <v-row
3
+ class="highlight-on-hover pa-3"
4
+ no-gutters
5
+ @click="$router.push(pathPrefix)"
6
+ >
7
+ <v-col cols="12" class="px-6">
8
+ <v-skeleton-loader v-if="isLoading" type="heading, text@8, button" />
9
+ <template v-else>
10
+ <div class="text-h5">{{ item.name }}</div>
11
+ <div v-if="item.summary" class="mt-2">
12
+ <MDC :value="item.summary" />
13
+ </div>
14
+ </template>
15
+ </v-col>
16
+ </v-row>
17
+ <v-divider />
3
18
  </template>
4
19
 
5
20
  <script setup>
6
- defineProps({
7
- item: {
8
- type: Object,
9
- required: true,
10
- },
11
- pathPrefix: {
12
- type: String,
13
- required: true,
14
- },
21
+ import { computed } from "#imports"
22
+ import { useRootStore } from "../../stores/root"
23
+
24
+ const rootStore = useRootStore()
25
+ const props = defineProps({
26
+ item: { type: Object, required: true },
27
+ pathPrefix: { type: String, required: true },
28
+ loading: { type: Boolean, default: false },
15
29
  })
30
+
31
+ const isLoading = computed(() => rootStore.loading || props.loading)
16
32
  </script>
17
33
 
18
34
  <style></style>
@@ -1,53 +1,60 @@
1
1
  <template>
2
- <v-row v-ripple no-gutters class="cursor-pointer highlight-on-hover my-2">
3
- <v-col v-if="mdAndUp" align-self="center" cols="1">
4
- <MiscAtomsImageContainer
5
- cover
6
- :loading="$stores.news.loading"
7
- :src="
8
- item && item.image && item.image.url ? item.image.url : '/default.png'
9
- "
10
- :ratio="1 / 1"
11
- width="80px"
12
- />
13
- </v-col>
14
- <v-col align-self="start" class="text-h5 dense px-2 paragraph">
15
- <v-skeleton-loader v-if="rootStore.loading" type="heading" />
16
- <template v-else>
17
- <v-skeleton-loader
18
- v-if="rootStore.loading"
19
- :type="
20
- ['chip', 'chip@2', 'chip@3', 'chip@4', 'chip@4', 'chip@4'][
21
- ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].indexOf(name || 'md')
22
- ]
2
+ <NuxtLink
3
+ v-if="pathPrefix"
4
+ :to="pathPrefix"
5
+ class="text-decoration-none text-black"
6
+ >
7
+ <v-row v-ripple no-gutters class="cursor-pointer highlight-on-hover my-2">
8
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
9
+ <MiscAtomsImageContainer
10
+ cover
11
+ :loading="isLoading"
12
+ :src="
13
+ item && item.image && item.image.url
14
+ ? item.image.url
15
+ : '/default.png'
23
16
  "
17
+ :ratio="1 / 1"
18
+ width="80px"
24
19
  />
25
-
20
+ </v-col>
21
+ <v-col align-self="start" class="text-h5 dense px-2 paragraph">
22
+ <v-skeleton-loader v-if="isLoading" type="heading" />
26
23
  <template v-else>
27
- <v-chip
28
- class="ma-2"
29
- style="background-color: white; color: black"
30
- size="small"
31
- variant="outlined"
32
- >
33
- {{ $t(eventCategory) }}
34
- </v-chip>
35
- <MiscMoleculesChipContainer :items="item.tags" size="small" />
24
+ <v-skeleton-loader
25
+ v-if="isLoading"
26
+ :type="
27
+ ['chip', 'chip@2', 'chip@3', 'chip@4', 'chip@4', 'chip@4'][
28
+ ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'].indexOf(name || 'md')
29
+ ]
30
+ "
31
+ />
32
+
33
+ <template v-else>
34
+ <v-chip
35
+ class="ma-2"
36
+ style="background-color: white; color: black"
37
+ size="small"
38
+ variant="outlined"
39
+ >
40
+ {{ $t(eventCategory) }}
41
+ </v-chip>
42
+ <MiscMoleculesChipContainer :items="item.tags || []" size="small" />
43
+ </template>
44
+ <div
45
+ v-html="
46
+ $rootStore.search.length
47
+ ? highlightAndTruncate(
48
+ 300,
49
+ item.name,
50
+ $rootStore.search.split(' '),
51
+ )
52
+ : item.name
53
+ "
54
+ />
36
55
  </template>
37
- <div
38
- v-html="
39
- $rootStore.search.length
40
- ? highlightAndTruncate(
41
- 300,
42
- item.name,
43
- $rootStore.search.split(' '),
44
- )
45
- : item.name
46
- "
47
- />
48
- </template>
49
- </v-col>
50
- </v-row>
56
+ </v-col> </v-row
57
+ ></NuxtLink>
51
58
  </template>
52
59
 
53
60
  <script setup>
@@ -73,6 +80,11 @@ const props = defineProps({
73
80
  type: String,
74
81
  required: true,
75
82
  },
83
+ loading: {
84
+ type: Boolean,
85
+ required: false,
86
+ default: false,
87
+ },
76
88
  })
77
89
  const eventCategory = computed(() => {
78
90
  if (props.item.category) {
@@ -81,4 +93,6 @@ const eventCategory = computed(() => {
81
93
  return "list.filters.news.category.others"
82
94
  }
83
95
  })
96
+
97
+ const isLoading = computed(() => props.loading)
84
98
  </script>
@@ -6,7 +6,7 @@
6
6
  cover
7
7
  :src="item.image.url ? item.image : '/default.png'"
8
8
  :ratio="1 / 1"
9
- :loading="$stores.news.loading"
9
+ :loading="isLoading"
10
10
  >
11
11
  <v-chip class="ma-2" style="background-color: white; color: black">
12
12
  {{ $t(eventCategory) }}
@@ -15,7 +15,7 @@
15
15
  </v-col>
16
16
  <v-col cols="12" md="8" lg="4" class="pl-md-6">
17
17
  <v-skeleton-loader
18
- v-if="rootStore.loading || $stores['news'].loading"
18
+ v-if="isLoading"
19
19
  :type="
20
20
  [
21
21
  'heading, subtitle, text@5, ossein, button',
@@ -44,7 +44,7 @@
44
44
  </div>
45
45
  <MiscMoleculesChipContainer
46
46
  v-if="item.tags && item.tags.length"
47
- :items="item.tags"
47
+ :items="item.tags || []"
48
48
  class="mt-4"
49
49
  />
50
50
  <template v-if="mdAndDown">
@@ -74,10 +74,7 @@
74
74
  </v-col>
75
75
 
76
76
  <v-col v-if="lgAndUp" cols="12" lg="5">
77
- <v-skeleton-loader
78
- v-if="rootStore.loading || $stores.news.loading"
79
- type="text@8, ossein, button"
80
- />
77
+ <v-skeleton-loader v-if="isLoading" type="text@8, ossein, button" />
81
78
 
82
79
  <template v-else>
83
80
  <div
@@ -140,6 +137,11 @@ const props = defineProps({
140
137
  type: String,
141
138
  required: true,
142
139
  },
140
+ loading: {
141
+ type: Boolean,
142
+ required: false,
143
+ default: false,
144
+ },
143
145
  })
144
146
 
145
147
  const processedSummary = computed(() => {
@@ -155,6 +157,8 @@ function replaceMarkdownLinksWithSlug(markdownText, slugPath) {
155
157
  return `[${text}](${slugPath}?redirect=${encodedUrl})`
156
158
  })
157
159
  }
160
+
161
+ const isLoading = computed(() => rootStore.loading || props.loading)
158
162
  </script>
159
163
 
160
164
  <style></style>
@@ -1,14 +1,9 @@
1
1
  <template>
2
- <v-row
3
- v-ripple
4
- no-gutters
5
- class="cursor-pointer highlight-on-hover my-2"
6
- @click="$router.push(pathPrefix)"
7
- >
2
+ <v-row v-ripple no-gutters class="cursor-pointer highlight-on-hover my-2">
8
3
  <v-col v-if="mdAndUp" cols="1">
9
4
  <MiscAtomsImageContainer
10
5
  cover
11
- :loading="$stores.people.loading"
6
+ :loading="isLoading"
12
7
  :src="
13
8
  item && item.image && item.image.url ? item.image.url : '/default.png'
14
9
  "
@@ -17,7 +12,7 @@
17
12
  />
18
13
  </v-col>
19
14
  <v-col align-self="start" class="text-h6 dense px-2">
20
- <v-skeleton-loader v-if="rootStore.loading" type="heading" />
15
+ <v-skeleton-loader v-if="isLoading" type="heading" />
21
16
  <div v-else class="d-flex text-h5 align-center">
22
17
  <span
23
18
  v-html="
@@ -72,7 +67,14 @@ const props = defineProps({
72
67
  type: String,
73
68
  required: true,
74
69
  },
70
+ loading: {
71
+ type: Boolean,
72
+ required: false,
73
+ default: false,
74
+ },
75
75
  })
76
+
77
+ const isLoading = computed(() => props.loading)
76
78
  </script>
77
79
  <style>
78
80
  .paragraph{max-width:83ch!important}
@@ -7,7 +7,7 @@
7
7
  <v-col v-if="mdAndUp" cols="12" md="3">
8
8
  <MiscAtomsImageContainer
9
9
  cover
10
- :loading="$stores.people.loading"
10
+ :loading="isLoading"
11
11
  :src="item.image.url ? item.image : '/default.png'"
12
12
  :ratio="1 / 1"
13
13
  />
@@ -15,7 +15,7 @@
15
15
 
16
16
  <v-col cols="12" md="8">
17
17
  <v-skeleton-loader
18
- v-if="$stores.people.loading"
18
+ v-if="isLoading"
19
19
  :type="
20
20
  [
21
21
  'heading, subtitle, text@5',
@@ -53,9 +53,11 @@
53
53
  <script setup>
54
54
  import { useDisplay } from "vuetify"
55
55
  import { useLocalePath, computed } from "#imports"
56
+ import { useRootStore } from "../../stores/root"
56
57
 
57
58
  const { name, mdAndUp } = useDisplay()
58
59
  const localePath = useLocalePath()
60
+ const rootStore = useRootStore()
59
61
  const props = defineProps({
60
62
  item: {
61
63
  type: Object,
@@ -65,6 +67,11 @@ const props = defineProps({
65
67
  type: Number,
66
68
  required: true,
67
69
  },
70
+ loading: {
71
+ type: Boolean,
72
+ required: false,
73
+ default: false,
74
+ },
68
75
  })
69
76
  const lineClamp = computed(() => {
70
77
  let base = [5, 6, 3, 6, 8, 10][
@@ -80,4 +87,6 @@ const lineClamp = computed(() => {
80
87
 
81
88
  return base
82
89
  })
90
+
91
+ const isLoading = computed(() => rootStore.loading || props.loading)
83
92
  </script>