@paris-ias/list 1.0.136 → 1.0.138

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 (78) 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 -10
  4. package/dist/runtime/components/actions/RowsItem.vue +57 -7
  5. package/dist/runtime/components/actions/View.vue +5 -17
  6. package/dist/runtime/components/affiliation/DenseItem.vue +26 -6
  7. package/dist/runtime/components/affiliation/ExpandedItem.vue +4 -0
  8. package/dist/runtime/components/affiliation/RowsItem.vue +27 -7
  9. package/dist/runtime/components/affiliation/View.vue +4 -4
  10. package/dist/runtime/components/apps/DenseItem.vue +26 -6
  11. package/dist/runtime/components/apps/ExpandedItem.vue +5 -1
  12. package/dist/runtime/components/apps/RowsItem.vue +27 -7
  13. package/dist/runtime/components/apps/View.vue +4 -4
  14. package/dist/runtime/components/disciplines/DenseItem.vue +26 -6
  15. package/dist/runtime/components/disciplines/ExpandedItem.vue +4 -0
  16. package/dist/runtime/components/disciplines/RowsItem.vue +27 -7
  17. package/dist/runtime/components/disciplines/View.vue +4 -4
  18. package/dist/runtime/components/events/Badges.vue +8 -12
  19. package/dist/runtime/components/events/DenseItem.vue +26 -16
  20. package/dist/runtime/components/events/ExpandedItem.vue +4 -0
  21. package/dist/runtime/components/events/RelatedItem.vue +4 -13
  22. package/dist/runtime/components/events/RowsItem.vue +20 -20
  23. package/dist/runtime/components/events/SlidingItem.vue +39 -47
  24. package/dist/runtime/components/events/View.vue +1 -1
  25. package/dist/runtime/components/fellowships/Badges.vue +15 -11
  26. package/dist/runtime/components/fellowships/DenseItem.vue +22 -11
  27. package/dist/runtime/components/fellowships/ExpandedItem.vue +8 -1
  28. package/dist/runtime/components/fellowships/RowsItem.vue +22 -15
  29. package/dist/runtime/components/fellowships/View.vue +2 -2
  30. package/dist/runtime/components/files/DenseItem.vue +26 -6
  31. package/dist/runtime/components/files/ExpandedItem.vue +4 -0
  32. package/dist/runtime/components/files/RowsItem.vue +27 -7
  33. package/dist/runtime/components/files/View.vue +4 -4
  34. package/dist/runtime/components/list/atoms/FiltersMenu.vue +9 -0
  35. package/dist/runtime/components/list/atoms/PerPage.vue +3 -2
  36. package/dist/runtime/components/list/atoms/ResetButton.vue +5 -1
  37. package/dist/runtime/components/list/atoms/SearchInput.vue +15 -2
  38. package/dist/runtime/components/list/atoms/SearchString.vue +169 -133
  39. package/dist/runtime/components/list/atoms/SortMenu.vue +22 -18
  40. package/dist/runtime/components/list/atoms/ViewMenu.vue +26 -14
  41. package/dist/runtime/components/list/molecules/Filters.vue +8 -8
  42. package/dist/runtime/components/list/molecules/Header.vue +10 -19
  43. package/dist/runtime/components/list/molecules/Pagination.vue +51 -48
  44. package/dist/runtime/components/list/organisms/List.vue +104 -69
  45. package/dist/runtime/components/mailing/DenseItem.vue +4 -0
  46. package/dist/runtime/components/mailing/ExpandedItem.vue +4 -0
  47. package/dist/runtime/components/mailing/RowsItem.vue +27 -7
  48. package/dist/runtime/components/mailing/View.vue +4 -4
  49. package/dist/runtime/components/misc/atoms/ImageContainer.vue +3 -45
  50. package/dist/runtime/components/misc/molecules/Related.vue +1 -1
  51. package/dist/runtime/components/news/DenseItem.vue +63 -54
  52. package/dist/runtime/components/news/ExpandedItem.vue +11 -17
  53. package/dist/runtime/components/news/RelatedItem.vue +4 -13
  54. package/dist/runtime/components/news/RowsItem.vue +21 -42
  55. package/dist/runtime/components/news/View.vue +7 -7
  56. package/dist/runtime/components/people/DenseItem.vue +16 -20
  57. package/dist/runtime/components/people/RelatedItem.vue +4 -14
  58. package/dist/runtime/components/people/RowsItem.vue +14 -23
  59. package/dist/runtime/components/projects/DenseItem.vue +17 -17
  60. package/dist/runtime/components/projects/RelatedItem.vue +4 -13
  61. package/dist/runtime/components/projects/RowsItem.vue +16 -16
  62. package/dist/runtime/components/projects/View.vue +6 -6
  63. package/dist/runtime/components/publications/DenseItem.vue +17 -15
  64. package/dist/runtime/components/publications/RelatedItem.vue +4 -13
  65. package/dist/runtime/components/publications/RowsItem.vue +18 -18
  66. package/dist/runtime/components/tags/DenseItem.vue +4 -0
  67. package/dist/runtime/components/tags/ExpandedItem.vue +4 -0
  68. package/dist/runtime/components/tags/RowsItem.vue +24 -7
  69. package/dist/runtime/components/tags/View.vue +4 -4
  70. package/dist/runtime/components/users/DenseItem.vue +24 -6
  71. package/dist/runtime/components/users/ExpandedItem.vue +5 -1
  72. package/dist/runtime/components/users/RowsItem.vue +25 -7
  73. package/dist/runtime/components/users/View.vue +4 -4
  74. package/dist/runtime/composables/useUtils.js +1 -1
  75. package/dist/runtime/plugins/pinia.js +5 -2
  76. package/dist/runtime/stores/root.d.ts +10 -9
  77. package/dist/runtime/stores/root.js +83 -119
  78. package/package.json +3 -4
@@ -34,25 +34,6 @@ import { ref, computed } from "vue"
34
34
  import { useNuxtApp } from "#imports"
35
35
  const { $stores } = useNuxtApp()
36
36
 
37
- const filtersOpen = ref(false)
38
- const visible = computed(() => {
39
- console.log(
40
- "$stores[props.type]?.filtersCount > 0: ",
41
- $stores[props.type]?.filtersCount > 0
42
- )
43
- console.log(
44
- "$stores[props.type]?.filtersCount: ",
45
- $stores[props.type]?.filtersCount
46
- )
47
- console.log(
48
- !!(
49
- $stores[props.type]?.filtersCount && $stores[props.type]?.filtersCount > 0
50
- )
51
- )
52
- return !!(
53
- $stores[props.type]?.filtersCount && $stores[props.type]?.filtersCount > 0
54
- )
55
- })
56
37
  const props = defineProps({
57
38
  type: {
58
39
  type: String,
@@ -60,4 +41,14 @@ const props = defineProps({
60
41
  default: "",
61
42
  },
62
43
  })
44
+ const visible = computed(() => {
45
+ console.log(
46
+ "SHOULD DISPLAY FILTERS:",
47
+ $stores[props.type]?.filtersCount && $stores[props.type]?.filtersCount > 0,
48
+ )
49
+ return !!(
50
+ $stores[props.type]?.filtersCount && $stores[props.type]?.filtersCount > 0
51
+ )
52
+ })
53
+ const filtersOpen = ref(unref(visible))
63
54
  </script>
@@ -9,9 +9,10 @@
9
9
  <v-btn
10
10
  v-if="!(hidePrevNext && isFirstPage)"
11
11
  :disabled="isFirstPage"
12
- min-width="35"
13
- height="35"
14
- width="35"
12
+ min-width="40"
13
+ height="40"
14
+ width="40"
15
+ class="prev-btn"
15
16
  :tabindex="isFirstPage && hidePrevNext ? -1 : 0"
16
17
  aria-label="Previous Page"
17
18
  @click="onChange(currentPage - 1)"
@@ -19,16 +20,16 @@
19
20
  >
20
21
  <v-icon>mdi-chevron-left</v-icon>
21
22
  </v-btn>
22
-
23
23
  <!-- Page buttons and gaps -->
24
24
  <template v-for="(page, index) in renderPages" :key="page.key">
25
25
  <!-- Ellipsis gap -->
26
26
  <v-btn
27
+ class="ellipsis-btn"
27
28
  v-if="page.isGap"
28
- icon
29
- min-width="35"
30
- height="35"
31
- width="35"
29
+ min-width="40"
30
+ tile
31
+ height="40"
32
+ width="40"
32
33
  @click="onChange(getGapPage(index))"
33
34
  @keyup.enter="onChange(getGapPage(index))"
34
35
  >
@@ -40,10 +41,10 @@
40
41
  v-else
41
42
  :class="['page-button', { 'active-page': page.current }]"
42
43
  tabindex="0"
43
- min-width="35"
44
- height="35"
44
+ min-width="40"
45
+ height="40"
45
46
  tile
46
- width="35"
47
+ width="40"
47
48
  :aria-current="page.current ? 'page' : undefined"
48
49
  :aria-label="
49
50
  page.current
@@ -63,9 +64,11 @@
63
64
  :disabled="isLastPage"
64
65
  :tabindex="isLastPage && hidePrevNext ? -1 : 0"
65
66
  aria-label="Next Page"
66
- min-width="35"
67
- height="35"
68
- width="35"
67
+ min-width="40"
68
+ tile
69
+ class="next-btn"
70
+ height="40"
71
+ width="40"
69
72
  @click="onChange(currentPage + 1)"
70
73
  @keyup.enter="onChange(currentPage + 1)"
71
74
  >
@@ -75,7 +78,7 @@
75
78
  </template>
76
79
 
77
80
  <script setup>
78
- import { computed } from "vue";
81
+ import { computed } from "vue"
79
82
 
80
83
  const props = defineProps({
81
84
  currentPage: { type: Number, required: true },
@@ -83,15 +86,15 @@ const props = defineProps({
83
86
  pagePadding: { type: Number, default: 1, validator: (v) => v > 0 },
84
87
  pageGap: { type: Number, default: 2, validator: (v) => v > 0 },
85
88
  hidePrevNext: { type: Boolean, default: false },
86
- });
89
+ })
87
90
 
88
- const emit = defineEmits(["update"]);
91
+ const emit = defineEmits(["update"])
89
92
 
90
93
  // Computed state for prev/next disabled
91
- const isFirstPage = computed(() => props.currentPage === 1);
94
+ const isFirstPage = computed(() => props.currentPage === 1)
92
95
  const isLastPage = computed(
93
- () => props.currentPage === props.totalPages || props.totalPages === 0
94
- );
96
+ () => props.currentPage === props.totalPages || props.totalPages === 0,
97
+ )
95
98
 
96
99
  // Generate pages and gap positions
97
100
  const renderPages = computed(() => {
@@ -99,41 +102,41 @@ const renderPages = computed(() => {
99
102
  key: `page-${pageIndex}`,
100
103
  value: pageIndex,
101
104
  current: pageIndex === props.currentPage,
102
- });
103
- const createGap = (pageIndex) => ({ key: `gap-${pageIndex}`, isGap: true });
105
+ })
106
+ const createGap = (pageIndex) => ({ key: `gap-${pageIndex}`, isGap: true })
104
107
 
105
- const pages = [];
108
+ const pages = []
106
109
  for (let i = 1; i <= props.totalPages; i++) {
107
110
  if (
108
111
  i === props.currentPage ||
109
112
  i < props.pageGap ||
110
113
  i > props.totalPages - props.pageGap + 1
111
114
  ) {
112
- pages.push(createPage(i));
113
- continue;
115
+ pages.push(createPage(i))
116
+ continue
114
117
  }
115
118
 
116
- let min, max;
119
+ let min, max
117
120
  if (props.currentPage <= props.pageGap + props.pagePadding) {
118
- min = props.pageGap + 1;
119
- max = min + props.pagePadding * 2;
121
+ min = props.pageGap + 1
122
+ max = min + props.pagePadding * 2
120
123
  } else if (
121
124
  props.currentPage >=
122
125
  props.totalPages - props.pageGap - props.pagePadding
123
126
  ) {
124
- max = props.totalPages - props.pageGap;
125
- min = max - props.pagePadding * 2;
127
+ max = props.totalPages - props.pageGap
128
+ min = max - props.pagePadding * 2
126
129
  } else {
127
- min = props.currentPage - props.pagePadding;
128
- max = props.currentPage + props.pagePadding;
130
+ min = props.currentPage - props.pagePadding
131
+ max = props.currentPage + props.pagePadding
129
132
  }
130
133
 
131
134
  if (
132
135
  (i >= min && i <= props.currentPage) ||
133
136
  (i <= max && i >= props.currentPage)
134
137
  ) {
135
- pages.push(createPage(i));
136
- continue;
138
+ pages.push(createPage(i))
139
+ continue
137
140
  }
138
141
 
139
142
  if (i === props.pageGap) {
@@ -141,11 +144,11 @@ const renderPages = computed(() => {
141
144
  min > props.pageGap + 1 &&
142
145
  props.currentPage > props.pageGap + props.pagePadding + 1
143
146
  ) {
144
- pages.push(createGap(i));
147
+ pages.push(createGap(i))
145
148
  } else {
146
- pages.push(createPage(i));
149
+ pages.push(createPage(i))
147
150
  }
148
- continue;
151
+ continue
149
152
  }
150
153
 
151
154
  if (i === props.totalPages - props.pageGap + 1) {
@@ -153,28 +156,28 @@ const renderPages = computed(() => {
153
156
  max < props.totalPages - props.pageGap &&
154
157
  props.currentPage < props.totalPages - props.pageGap - props.pagePadding
155
158
  ) {
156
- pages.push(createGap(i));
159
+ pages.push(createGap(i))
157
160
  } else {
158
- pages.push(createPage(i));
161
+ pages.push(createPage(i))
159
162
  }
160
- continue;
163
+ continue
161
164
  }
162
165
  }
163
- return pages;
164
- });
166
+ return pages
167
+ })
165
168
 
166
169
  // Calculate page to jump when clicking gap
167
170
  const getGapPage = (index) => {
168
- const before = renderPages.value[index - 1];
169
- const after = renderPages.value[index + 1] || { value: props.totalPages };
170
- return Math.floor((before.value + after.value) / 2);
171
- };
171
+ const before = renderPages.value[index - 1]
172
+ const after = renderPages.value[index + 1] || { value: props.totalPages }
173
+ return Math.floor((before.value + after.value) / 2)
174
+ }
172
175
 
173
176
  function onChange(page) {
174
- emit("update", page);
177
+ emit("update", page)
175
178
  }
176
179
  </script>
177
180
 
178
181
  <style scoped>
179
- .page-button{background-color:transparent;border:1px solid rgba(0,0,0,.2);color:#000;transition:background-color .3s ease,color .3s ease,transform .2s ease}.page-button:hover{background-color:#f0f0f0}.page-button.active-page{background-color:#000!important;color:#fff!important;transform:scale(1.05)}.page-button:focus{box-shadow:0 0 0 2px rgba(0,0,0,.3);outline:none}
182
+ .ellipsis-btn,.next-btn,.page-button,.prev-btn{background-color:transparent;border:1px solid rgba(0,0,0,.2);font-size:16px;transition:background-color .3s ease,color .3s ease,transform .2s ease}.page-button:hover{background-color:#f0f0f0}.page-button.active-page{background-color:#000!important;color:#fff!important;transform:scale(1.05)}.page-button:focus{box-shadow:0 0 0 2px rgba(0,0,0,.3);outline:none}
180
183
  </style>
@@ -1,28 +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"
14
+ :pathPrefix="
15
+ localePath({ name: pathPrefix, params: { slug: item.slug } })
16
+ "
10
17
  />
11
18
  </component>
12
19
  <div class="text-center">
13
- <ListAtomsPerPage
14
- v-if="numberOfPages > 1"
15
- :type="type"
16
- class="float-right"
17
- />
20
+ <ListAtomsPerPage :type="type" class="float-right" />
18
21
 
19
22
  <ListMoleculesPagination
20
- v-if="numberOfPages > 1"
21
- :type="type"
22
- color="black"
23
+ v-if="$stores[type].numberOfPages > 1"
24
+ :type
23
25
  large
24
- :current-page="page"
25
- :total-pages="numberOfPages"
26
+ :current-page="$stores[type].page"
27
+ :total-pages="$stores[type].numberOfPages"
26
28
  :page-padding="1"
27
29
  :page-gap="2"
28
30
  :hide-prev-next="false"
@@ -32,23 +34,25 @@
32
34
  </template>
33
35
 
34
36
  <script setup>
35
- import { nextTick, watch } from "vue"
37
+ import { computed, onUpdated, onMounted, watch } from "vue"
36
38
  import { useRootStore } from "../../../stores/root"
37
39
  import { capitalize } from "../../../composables/useUtils"
38
40
  import {
39
41
  useNuxtApp,
40
42
  resolveComponent,
41
- computed,
42
43
  onBeforeUnmount,
43
- onMounted,
44
44
  useI18n,
45
45
  useRoute,
46
- navigateTo,
46
+ useLocalePath,
47
+ useAsyncQuery,
47
48
  } from "#imports"
48
- const { $stores } = useNuxtApp()
49
+
50
+ const { $stores, $queries } = useNuxtApp()
49
51
  const { locale } = useI18n()
50
52
  const route = useRoute()
51
53
  const rootStore = useRootStore()
54
+ const localePath = useLocalePath()
55
+
52
56
  const props = defineProps({
53
57
  addBtn: {
54
58
  type: Boolean,
@@ -60,7 +64,7 @@ const props = defineProps({
60
64
  default: "people",
61
65
  required: true,
62
66
  },
63
- layout: {
67
+ /* layout: {
64
68
  type: Object,
65
69
  required: false,
66
70
  default: () => {
@@ -69,88 +73,119 @@ const props = defineProps({
69
73
  xl: 12,
70
74
  }
71
75
  },
76
+ }, */
77
+ pathPrefix: {
78
+ type: String,
79
+ required: true,
72
80
  },
73
- pagination: {
74
- type: Object,
75
- required: false,
76
- default: () => {
77
- return {}
78
- },
79
- },
81
+
80
82
  addButton: {
81
83
  type: Boolean,
82
84
  required: false,
83
85
  default: false,
84
86
  },
85
- items: [Object],
86
87
  })
87
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
88
97
  const view = computed(() =>
89
98
  props.customView
90
99
  ? resolveComponent("ListViews" + capitalize(props.customView))
91
- : resolveComponent("ListViews" + capitalize($stores[props.type].view.name))
100
+ : resolveComponent(
101
+ "ListViews" + capitalize($stores[props.type]?.view?.name || "list"),
102
+ ),
92
103
  )
93
104
  const itemTemplate = computed(() =>
94
105
  resolveComponent(
95
106
  (
96
107
  capitalize(props.type) +
97
- capitalize($stores[props.type].view.name) +
108
+ capitalize($stores[props.type]?.view?.name || "list") +
98
109
  "Item"
99
- ).toString()
100
- )
110
+ ).toString(),
111
+ ),
101
112
  )
102
- const numberOfPages = computed(() => $stores[props.type].numberOfPages)
103
113
 
104
- const page = computed(() => {
105
- const p = parseInt(route.query.page, 10)
106
- 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)
107
118
  })
119
+ console.log("Starting query for type: ", props.type)
120
+ console.log("Using variables: ", variables.value)
108
121
 
109
- const items = computed(() => $stores[props.type].items)
110
- console.log("setup list")
111
-
112
- // On mounted: load filters and data
113
- onMounted(async () => {
114
- // Load any route filters
115
- rootStore.loadRouteQuery(props.type)
116
- // Initialize store page from URL
117
- const pageParam = parseInt(route.query.page, 10)
118
- if (!isNaN(pageParam) && pageParam > 1) {
119
- await rootStore.updatePage({
120
- page: pageParam,
121
- type: props.type,
122
- lang: locale.value,
123
- })
124
- }
125
- // Fetch initial items
126
- try {
127
- await rootStore.update(props.type, locale.value)
128
- } catch (e) {
129
- console.error("Error fetching list:", e)
130
- }
131
- })
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
+ }
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
+ }
132
142
 
143
+ // Watch for variable changes to refresh and apply new data
133
144
  watch(
134
- () => page.value,
135
- async (newPage) => {
136
- const query = {
137
- ...route.query,
138
- 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)
139
157
  }
140
- navigateTo({ query }, { replace: true })
141
- await nextTick()
142
- window.scrollTo({ top: 0, behavior: "smooth" })
143
- }
158
+ },
159
+ { deep: true },
144
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
+
145
171
  onBeforeUnmount(() => {
146
172
  rootStore.resetState(props.type, locale.value)
147
173
  })
148
174
 
149
175
  async function onPageChange(newPage) {
150
- await rootStore.updatePage({
176
+ console.log("onPageChange: ", newPage)
177
+ rootStore.updatePage({
151
178
  page: newPage,
152
179
  type: props.type,
153
180
  lang: locale.value,
154
181
  })
182
+ if (typeof window !== "undefined") {
183
+ window.scrollTo({ top: 0, behavior: "smooth" })
184
+ }
155
185
  }
186
+ /*
187
+ onUpdated(() => {
188
+ console.log("STOP local loading from updated")
189
+ rootStore.setLoading(false, props.type)
190
+ }) */
156
191
  </script>
@@ -8,6 +8,10 @@ defineProps({
8
8
  type: Object,
9
9
  required: true,
10
10
  },
11
+ pathPrefix: {
12
+ type: String,
13
+ required: true,
14
+ },
11
15
  })
12
16
  </script>
13
17
 
@@ -10,6 +10,10 @@ const props = defineProps({
10
10
  type: Object,
11
11
  required: true,
12
12
  },
13
+ pathPrefix: {
14
+ type: String,
15
+ required: true,
16
+ },
13
17
  })
14
18
  </script>
15
19
 
@@ -1,14 +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
- });
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 },
29
+ })
30
+
31
+ const isLoading = computed(() => rootStore.loading || props.loading)
12
32
  </script>
13
33
 
14
34
  <style></style>
@@ -3,9 +3,9 @@
3
3
  </template>
4
4
 
5
5
  <script setup>
6
- import { useNuxtApp } from "#imports";
6
+ import { useNuxtApp } from "#imports"
7
7
 
8
- const { $stores } = useNuxtApp();
8
+ const { $stores } = useNuxtApp()
9
9
  defineProps({
10
10
  item: {
11
11
  type: Object,
@@ -16,7 +16,7 @@ defineProps({
16
16
  required: false,
17
17
  default: false,
18
18
  },
19
- });
19
+ })
20
20
 
21
- $stores.mailing.loading = false;
21
+ $stores.mailing.loading = false
22
22
  </script>
@@ -8,46 +8,7 @@
8
8
  <v-skeleton-loader v-if="loading" height="100%" type="image" />
9
9
 
10
10
  <template v-else>
11
- <nuxt-link
12
- v-if="link"
13
- v-slot="{ navigate, isActive }"
14
- :to="
15
- localePath({
16
- name: link,
17
- params: { slug },
18
- })
19
- "
20
- custom
21
- >
22
- <div class="overflow-hidden mw-100">
23
- <!-- TODO debug why the picture is not displaying/sizing properly -->
24
- <v-img
25
- v-if="src"
26
- :aspect-ratio="ratio"
27
- :active="isActive"
28
- :class="{ 'img-animation': animate }"
29
- :lazy-src="
30
- img(computedSrc, {
31
- width,
32
- quality: 70,
33
- })
34
- "
35
- :src="
36
- img(computedSrc, {
37
- width,
38
- quality: 70,
39
- })
40
- "
41
- :srcset="_srcset.srcset"
42
- :sizes="_srcset.sizes"
43
- :title="caption"
44
- v-bind="$attrs"
45
- @click="navigate"
46
- >
47
- <slot />
48
- </v-img></div
49
- ></nuxt-link>
50
- <div v-else class="overflow-hidden mw-100">
11
+ <div class="overflow-hidden mw-100">
51
12
  <!-- TODO debug why the picture is not displaying/sizing properly -->
52
13
  <v-img
53
14
  v-if="src"
@@ -78,8 +39,7 @@
78
39
  </template>
79
40
 
80
41
  <script setup>
81
- import { computed, useImage, useLocalePath } from "#imports"
82
- const localePath = useLocalePath()
42
+ import { computed, useImage } from "#imports"
83
43
  const img = useImage()
84
44
 
85
45
  const computedSrc = computed(() => {
@@ -105,8 +65,6 @@ const props = defineProps({
105
65
  width: { type: Number, default: 0 },
106
66
  ratio: { type: Number, required: true, default: 1 },
107
67
  caption: { type: String, default: "" },
108
- slug: { type: [Object, String], default: "" },
109
- link: { type: String, default: "" },
110
68
  animate: { type: Boolean, default: true },
111
69
  })
112
70
  const _srcset = computed(() => {
@@ -119,7 +77,7 @@ const _srcset = computed(() => {
119
77
  quality: 70,
120
78
  ...(props.width && { width: props.width }),
121
79
  },
122
- }
80
+ },
123
81
  )
124
82
  })
125
83
  </script>
@@ -24,5 +24,5 @@ const props = defineProps({
24
24
  type: Object,
25
25
  required: true,
26
26
  },
27
- });
27
+ })
28
28
  </script>