@paris-ias/list 1.0.106 → 1.0.107

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.
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@paris-ias/list",
3
3
  "configKey": "list",
4
- "version": "1.0.106",
4
+ "version": "1.0.107",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.0",
7
7
  "unbuild": "3.5.0"
@@ -1,32 +1,50 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="$router.push(localePath('/activities/events/' + item.slug[locale]))"
6
7
  >
7
- <v-col align-self="center" cols="auto">
8
- {{
9
- new Date(item.start).toLocaleDateString(locale, {
10
- year: "numeric",
11
- month: "numeric",
12
- day: "numeric",
13
- })
14
- }}
8
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
9
+ <MiscAtomsImageContainer
10
+ cover
11
+ :loading="$stores.events.loading"
12
+ :src="item.image.url ? item.image : '/default.png'"
13
+ :ratio="1 / 1"
14
+ :name="item.name"
15
+ :slug="item.slug"
16
+ link="events-slug"
17
+ width="80px"
18
+ />
15
19
  </v-col>
16
- <v-col align-self="center" class="text-h6 dense">
17
- <div class="mt-2 text-h6 text-overline font-weight-black">
18
- {{ $t("list.filters.events.category." + item.category) }}
20
+
21
+ <v-col align-self="center" class="pl-2">
22
+ <div class="text-h5 dense text-overline font-weight-black">
23
+ {{
24
+ $t("list.filters.events.category." + item.category) +
25
+ " / " +
26
+ new Date(item.start).toLocaleDateString(locale, {
27
+ year: "numeric",
28
+ month: "numeric",
29
+ day: "numeric",
30
+ })
31
+ }}
32
+ </div>
33
+ <div class="text-h5 dense">
34
+ {{ item.name }}
19
35
  </div>
20
- {{ item.name }}
21
36
  </v-col>
22
- <v-col align-self="center">
23
- <!-- <EventsBadges :item /> -->
37
+
38
+ <v-col align-self="center" cols="auto">
39
+ <EventsBadges :item />
24
40
  </v-col>
25
41
  </v-row>
26
42
  </template>
27
43
 
28
44
  <script setup>
29
45
  import { useLocalePath, useI18n } from "#imports";
46
+ import { useDisplay } from "vuetify";
47
+ const { mdAndUp } = useDisplay();
30
48
  const { locale } = useI18n();
31
49
  const localePath = useLocalePath();
32
50
  const props = defineProps({
@@ -1,12 +1,13 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="
6
7
  $router.push(localePath('/activities/fellowships' + item.slug[locale]))
7
8
  "
8
9
  >
9
- <v-col align-self="center" cols="8" class="text-h6">
10
+ <v-col align-self="center" cols="8" class="text-h5 dense">
10
11
  {{ item.name }}
11
12
  <FellowshipsBadges :item="item" />
12
13
  </v-col>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <component
3
+ :is="itemTemplate"
4
+ v-for="(item, index) in $rootStore.results[type].items"
5
+ :key="index"
6
+ :item="item"
7
+ :index="index"
8
+ />
9
+ </template>
10
+
11
+ <script setup>
12
+ import { capitalize } from "../../../composables/useUtils";
13
+ import { useNuxtApp, resolveComponent, computed } from "#imports";
14
+ const { $stores, $rootStore } = useNuxtApp();
15
+ console.log("rootStore: ", $rootStore);
16
+ const props = defineProps({
17
+ type: {
18
+ type: String,
19
+ default: "people"
20
+ }
21
+ });
22
+ const itemTemplate = computed(
23
+ () => resolveComponent(
24
+ (capitalize(props.type) + capitalize($stores[props.type].view.name) + "Item").toString()
25
+ )
26
+ );
27
+ </script>
@@ -1,80 +1,83 @@
1
1
  <template>
2
2
  <div class="d-flex flex-grow-1 flex-column">
3
- <v-text-field
4
- v-model.trim="search"
5
- :placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
6
- prepend-inner-icon="mdi-magnify"
7
- single-line
8
- class="transition-swing"
9
- variant="outlined"
10
- hide-details
11
- clearable
12
- tile
13
- type="search"
14
- :loading="rootStore.loading"
15
- >
16
- <!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
17
- $store.state.scrolled }" -->
18
- <template v-if="!search" #label>
19
- <div class="searchLabel">
20
- {{
21
- type === "all"
22
- ? $t("search")
23
- : $t("list.search-type", [$t("items." + type, 2)])
24
- }}
25
- </div>
26
- </template>
27
- </v-text-field>
28
- <v-expand-transition v-if="type === 'all'">
29
- <v-list
30
- v-show="search.length"
31
- lines="three"
32
- item-props
33
- style="max-height: 300px"
34
- class="overflow-y-auto"
3
+ <div class="d-flex align-center">
4
+ <v-text-field
5
+ v-model.trim="search"
6
+ :placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
7
+ prepend-inner-icon="mdi-magnify"
8
+ single-line
9
+ class="transition-swing flex-grow-1"
10
+ variant="outlined"
11
+ hide-details
12
+ clearable
13
+ tile
14
+ type="search"
15
+ :loading="rootStore.loading"
35
16
  >
36
- <div v-if="rootStore.loading" class="d-flex justify-center py-6">
37
- <v-progress-circular color="black" size="64" indeterminate />
38
- </div>
39
- <template v-for="(item, index) in results">
40
- <v-list-subheader
41
- v-if="item.type && item.type === 'subheader'"
42
- :key="'subheader-' + index"
43
- >
44
- {{ $t(item.name) }}
45
- </v-list-subheader>
46
- <div
47
- v-else-if="item.type && item.type === 'no-result'"
48
- :key="'no-result-' + index"
49
- class="mx-6"
50
- >
51
- {{ $t("no-result") }}
17
+ <!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
18
+ $store.state.scrolled }" -->
19
+ <template v-if="!search" #label>
20
+ <div class="searchLabel">
21
+ {{
22
+ type === "all"
23
+ ? $t("search")
24
+ : $t("list.search-type", [$t("items." + type, 2)])
25
+ }}
52
26
  </div>
53
- <v-divider
54
- v-else-if="item.type && item.type === 'divider'"
55
- :key="'divider-' + index"
56
- inset
57
- />
58
- <ListAtomsSearchItem
59
- v-else
60
- :key="'item- ' + index"
61
- :index
62
- :item
63
- :type="item.type"
64
- />
65
27
  </template>
66
- </v-list>
67
- </v-expand-transition>
28
+ </v-text-field>
29
+
30
+ <v-menu
31
+ v-model="filterMenuOpen"
32
+ :close-on-content-click="false"
33
+ location="bottom end"
34
+ offset="4"
35
+ >
36
+ <template #activator="{ props: menuProps }">
37
+ <v-btn
38
+ v-bind="menuProps"
39
+ :rounded="0"
40
+ variant="outlined"
41
+ size="large"
42
+ height="56"
43
+ >
44
+ <v-icon>mdi-filter</v-icon>
45
+ <v-icon class="ml-1" size="small">
46
+ {{ filterMenuOpen ? "mdi-chevron-up" : "mdi-chevron-down" }}
47
+ </v-icon>
48
+ </v-btn>
49
+ </template>
50
+
51
+ <v-card min-width="200">
52
+ <v-list>
53
+ <v-list-item
54
+ v-for="option in filterOptions"
55
+ :key="option.value"
56
+ @click="toggleFilter(option)"
57
+ >
58
+ <template #prepend>
59
+ <v-checkbox
60
+ hide-details
61
+ :model-value="selectedFilters.includes(option.value)"
62
+ @update:model-value="toggleFilter(option)"
63
+ />
64
+ </template>
65
+ <v-list-item-title>{{ option.label }}</v-list-item-title>
66
+ </v-list-item>
67
+ </v-list>
68
+ </v-card>
69
+ </v-menu>
70
+ </div>
68
71
  </div>
69
72
  </template>
70
73
 
71
74
  <script setup>
72
75
  import { useDebounceFn } from "@vueuse/core";
73
76
  import { useRootStore } from "../../../stores/root";
74
- import { useNuxtApp, computed, useI18n } from "#imports";
77
+ import { computed, useI18n, ref } from "#imports";
75
78
  const { locale, t } = useI18n();
76
79
  const rootStore = useRootStore();
77
- const { $stores } = useNuxtApp();
80
+ const emit = defineEmits(["filter-change"]);
78
81
  const props = defineProps({
79
82
  type: {
80
83
  type: String,
@@ -85,34 +88,29 @@ const props = defineProps({
85
88
  default: false
86
89
  }
87
90
  });
88
- const results = computed(() => {
89
- const storeRst = rootStore.results;
90
- const rst = Object.keys(storeRst).length && Object.keys(storeRst).sort((a, b) => {
91
- return storeRst[b]?.items?.length - storeRst[a]?.items?.length;
92
- }).reduce((acc, key, index) => {
93
- const items = storeRst[key]?.items;
94
- const total = storeRst[key]?.total;
95
- if (total === 0 && index === 0) {
96
- acc.push({ type: "no-result" });
97
- return acc;
98
- }
99
- if (items?.length) {
100
- acc.push({ type: "subheader", name: t("items." + key, 2) });
101
- acc.push(
102
- ...items.map((item) => ({
103
- prependAvatar: item?.image?.url || "mdi-square",
104
- title: item.name || item.firstname + " " + item.lastname,
105
- subtitle: item.summary || item.biography,
106
- id: item.id,
107
- type: key
108
- }))
109
- );
110
- }
111
- acc.push({ type: "divider" });
112
- return acc;
113
- }, []) || {};
114
- return rst;
115
- });
91
+ const filterMenuOpen = ref(false);
92
+ const selectedFilters = ref([]);
93
+ const filterOptions = [
94
+ { value: "people", label: capitalize(t("items.people", 2)) },
95
+ { value: "events", label: capitalize(t("items.events", 2)) },
96
+ { value: "news", label: capitalize(t("items.news", 2)) },
97
+ { value: "publications", label: capitalize(t("items.publications", 2)) },
98
+ { value: "fellowships", label: capitalize(t("items.fellowships", 2)) },
99
+ { value: "projects", label: capitalize(t("items.projects", 2)) }
100
+ ];
101
+ const toggleFilter = (option) => {
102
+ const index = selectedFilters.value.indexOf(option.value);
103
+ if (index > -1) {
104
+ selectedFilters.value.splice(index, 1);
105
+ } else {
106
+ selectedFilters.value.push(option.value);
107
+ }
108
+ emit("filter-change", {
109
+ name: option.value,
110
+ value: selectedFilters.value.includes(option.value),
111
+ allSelected: selectedFilters.value
112
+ });
113
+ };
116
114
  const search = computed({
117
115
  get() {
118
116
  return rootStore.search;
@@ -14,7 +14,7 @@
14
14
  $stores[type].total,
15
15
  $t("items." + props.type, $stores[type].total),
16
16
  ],
17
- $stores[type].total
17
+ $stores[type].total,
18
18
  )
19
19
  : $t(
20
20
  "list.0-items-found",
@@ -22,7 +22,7 @@
22
22
  $stores[type].total,
23
23
  $t("items." + props.type, $stores[type].total),
24
24
  ],
25
- $stores[type].total
25
+ $stores[type].total,
26
26
  )
27
27
  }}
28
28
  </template>
@@ -42,11 +42,11 @@
42
42
  $t(
43
43
  "items." + props.type,
44
44
  $stores[type].total,
45
- $stores[type].total
45
+ $stores[type].total,
46
46
  ),
47
47
  $stores[type].search,
48
48
  ],
49
- $stores[type].total
49
+ $stores[type].total,
50
50
  )
51
51
  : $t(
52
52
  "list.0-items-found-searching-for",
@@ -55,11 +55,11 @@
55
55
  $t(
56
56
  "items." + props.type,
57
57
  $stores[type].total,
58
- $stores[type].total
58
+ $stores[type].total,
59
59
  ),
60
60
  $stores[type].search,
61
61
  ],
62
- $stores[type].total
62
+ $stores[type].total,
63
63
  )
64
64
  }}
65
65
  </template>
@@ -79,12 +79,12 @@
79
79
  $t(
80
80
  "items." + props.type,
81
81
  $stores[type].total,
82
- $stores[type].total
82
+ $stores[type].total,
83
83
  ),
84
84
  $stores[type].filtersCount,
85
85
  $t("filters", $stores[type].filtersCount),
86
86
  ],
87
- $stores[type].total
87
+ $stores[type].total,
88
88
  )
89
89
  : $t(
90
90
  "list.0-items-found-with-1-filter",
@@ -94,7 +94,7 @@
94
94
  $stores[type].filtersCount,
95
95
  $t("filters", $stores[type].filtersCount),
96
96
  ],
97
- $stores[type].total
97
+ $stores[type].total,
98
98
  )
99
99
  }}
100
100
  </template>
@@ -117,7 +117,7 @@
117
117
  $stores[type].filtersCount,
118
118
  $t("filters", $stores[type].filtersCount),
119
119
  ],
120
- $stores[type].total
120
+ $stores[type].total,
121
121
  )
122
122
  : $t(
123
123
  "list.0-items-found-searching-for-with-1-filter",
@@ -128,7 +128,7 @@
128
128
  $stores[type].filtersCount,
129
129
  $t("filters", $stores[type].filtersCount),
130
130
  ],
131
- $stores[type].total
131
+ $stores[type].total,
132
132
  )
133
133
  }}
134
134
  </template>
@@ -0,0 +1,128 @@
1
+ <template>
2
+ <div class="d-flex flex-grow-1 flex-column">
3
+ <div class="d-flex align-center">
4
+ <v-text-field
5
+ v-model.trim="search"
6
+ :placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
7
+ prepend-inner-icon="mdi-magnify"
8
+ single-line
9
+ class="transition-swing flex-grow-1"
10
+ variant="outlined"
11
+ hide-details
12
+ clearable
13
+ tile
14
+ type="search"
15
+ :loading="rootStore.loading"
16
+ >
17
+ <!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
18
+ $store.state.scrolled }" -->
19
+ <template v-if="!search" #label>
20
+ <div class="searchLabel">
21
+ {{
22
+ type === "all"
23
+ ? $t("search")
24
+ : $t("list.search-type", [$t("items." + type, 2)])
25
+ }}
26
+ </div>
27
+ </template>
28
+ </v-text-field>
29
+
30
+ <v-menu
31
+ v-model="filterMenuOpen"
32
+ :close-on-content-click="false"
33
+ location="bottom end"
34
+ offset="4"
35
+ >
36
+ <template #activator="{ props: menuProps }">
37
+ <v-btn
38
+ v-bind="menuProps"
39
+ :rounded="0"
40
+ variant="outlined"
41
+ size="large"
42
+ height="56"
43
+ >
44
+ <v-icon>mdi-filter</v-icon>
45
+ <v-icon class="ml-1" size="small">
46
+ {{ filterMenuOpen ? "mdi-chevron-up" : "mdi-chevron-down" }}
47
+ </v-icon>
48
+ </v-btn>
49
+ </template>
50
+
51
+ <v-card min-width="200">
52
+ <v-list density="compact">
53
+ <v-list-item
54
+ v-for="(option, index) in filterOptions"
55
+ :key="option.value"
56
+ @click="toggleFilter(option)"
57
+ >
58
+ <template #prepend>
59
+ <v-checkbox
60
+ hide-details
61
+ :model-value="categories.includes(index)"
62
+ @update:model-value="toggleFilter(option)"
63
+ />
64
+ </template>
65
+ <v-list-item-title>{{ option.label }}</v-list-item-title>
66
+ </v-list-item>
67
+ </v-list>
68
+ </v-card>
69
+ </v-menu>
70
+ </div>
71
+ </div>
72
+ </template>
73
+
74
+ <script setup>
75
+ import { useDebounceFn } from "@vueuse/core";
76
+ import { useRootStore } from "../../../stores/root";
77
+ import { computed, useI18n, ref } from "#imports";
78
+ const { locale, t } = useI18n();
79
+ const rootStore = useRootStore();
80
+ const emit = defineEmits(["filter-change"]);
81
+ const props = defineProps({
82
+ type: {
83
+ type: String,
84
+ required: true
85
+ },
86
+ loading: {
87
+ type: Boolean,
88
+ default: false
89
+ },
90
+ categories: {
91
+ type: Array,
92
+ default: () => []
93
+ }
94
+ });
95
+ const filterMenuOpen = ref(false);
96
+ const filterOptions = [
97
+ { value: "people", label: capitalize(t("items.people", 2)) },
98
+ { value: "events", label: capitalize(t("items.events", 2)) },
99
+ { value: "news", label: capitalize(t("items.news", 2)) },
100
+ { value: "publications", label: capitalize(t("items.publications", 2)) },
101
+ { value: "fellowships", label: capitalize(t("items.fellowships", 2)) },
102
+ { value: "projects", label: capitalize(t("items.projects", 2)) }
103
+ ];
104
+ const toggleFilter = (option) => {
105
+ const index = props.categories.indexOf(option.value);
106
+ if (index > -1) {
107
+ props.categories.splice(index, 1);
108
+ } else {
109
+ props.categories.push(option.value);
110
+ }
111
+ emit("filter-change", {
112
+ name: option.value,
113
+ value: props.categories.includes(option.value)
114
+ });
115
+ };
116
+ const search = computed({
117
+ get() {
118
+ return rootStore.search;
119
+ },
120
+ set: await useDebounceFn(async function(v) {
121
+ await rootStore.updateSearch({
122
+ type: props.type,
123
+ search: v || "",
124
+ lang: locale.value
125
+ });
126
+ }, 300)
127
+ });
128
+ </script>
@@ -0,0 +1,79 @@
1
+ <template>
2
+ <div>
3
+ <v-divider />
4
+ <div class="d-flex align-center justify-space-between my-6">
5
+ <v-btn
6
+ variant="text"
7
+ size="large"
8
+ class=""
9
+ @click="$emit('toggle', type)"
10
+ >
11
+ <v-icon size="large">{{
12
+ open ? "mdi-chevron-down" : "mdi-chevron-right"
13
+ }}</v-icon>
14
+ </v-btn>
15
+ <div
16
+ class="d-flex flex-column cursor-pointer"
17
+ @click="$emit('toggle', type)"
18
+ >
19
+ <div class="text-h4">
20
+ {{ capitalize($t("items." + props.type, 2)) }}
21
+ </div>
22
+ <div class="text-overline">
23
+ {{
24
+ feminine
25
+ ? $t(
26
+ "list.0-items-found-f",
27
+ [
28
+ $rootStore.results[type].total,
29
+ $t("items." + props.type, $rootStore.results[type].total),
30
+ ],
31
+ $rootStore.results[type].total,
32
+ )
33
+ : $t(
34
+ "list.0-items-found",
35
+ [
36
+ $rootStore.results[type].total,
37
+ $t("items." + props.type, $rootStore.results[type].total),
38
+ ],
39
+ $rootStore.results[type].total,
40
+ )
41
+ }}
42
+ </div>
43
+ </div>
44
+ <v-spacer />
45
+ <v-btn
46
+ class="ma-2"
47
+ color="default"
48
+ variant="outlined"
49
+ rounded="0"
50
+ :to="localePath(type === 'people' ? '/people' : '/activities/' + type)"
51
+ >
52
+ {{ $t("list.pls-x-more", [$rootStore.results[type].total]) }}
53
+ </v-btn>
54
+ </div>
55
+ <slot />
56
+ </div>
57
+ </template>
58
+
59
+ <script setup>
60
+ import { useNuxtApp, useLocalePath } from "#imports";
61
+ const localePath = useLocalePath();
62
+ const { $rootStore } = useNuxtApp();
63
+ const props = defineProps({
64
+ type: {
65
+ type: String,
66
+ required: true
67
+ },
68
+ feminine: {
69
+ type: Boolean,
70
+ required: false,
71
+ default: false
72
+ },
73
+ open: {
74
+ type: Boolean,
75
+ required: false,
76
+ default: true
77
+ }
78
+ });
79
+ </script>
@@ -1,54 +1,45 @@
1
1
  <template>
2
- <ListMoleculesResultsHeader :type="props.type" />
3
- <div class="results-container">
4
- <component
5
- :is="itemTemplate"
6
- v-for="(item, index) in items"
7
- :key="index"
8
- :item="item"
9
- :index="index"
10
- />
11
- </div>
2
+ <ListMoleculesGlobalSearchInput
3
+ type="all"
4
+ :placeholder="$t('search')"
5
+ variant="outlined"
6
+ />
7
+ <ListMoleculesResultsContainer
8
+ v-for="(type, index) in appConfig.list.modules"
9
+ :key="index"
10
+ :feminine="type === 'people'"
11
+ :type
12
+ :open="$rootStore.results[type].total > 0"
13
+ @toggle="open[$event] = !open[$event]"
14
+ >
15
+ <v-expand-transition class="results-container">
16
+ <div v-show="open[type]">
17
+ <ListAtomsResultsList :type />
18
+ </div> </v-expand-transition
19
+ ></ListMoleculesResultsContainer>
12
20
  </template>
13
21
 
14
22
  <script setup>
15
- import { useRootStore } from "../../../stores/root";
16
- import { capitalize } from "../../../composables/useUtils";
17
23
  import {
18
- useNuxtApp,
19
- resolveComponent,
20
- computed,
21
24
  onBeforeUnmount,
22
25
  onMounted,
23
- useI18n
26
+ useI18n,
27
+ useAppConfig,
28
+ useNuxtApp
24
29
  } from "#imports";
25
- const { $stores } = useNuxtApp();
30
+ const { $rootStore } = useNuxtApp();
31
+ const appConfig = useAppConfig();
26
32
  const { locale } = useI18n();
27
- const rootStore = useRootStore();
28
- const props = defineProps({
29
- type: {
30
- type: String,
31
- default: "people",
32
- required: true
33
- },
34
- items: [Object]
35
- });
36
- const itemTemplate = computed(
37
- () => resolveComponent(
38
- (capitalize(props.type) + capitalize($stores[props.type].view.name) + "Item").toString()
39
- )
40
- );
41
- const items = computed(() => $stores[props.type].items);
33
+ const open = ref({});
42
34
  onMounted(() => {
43
35
  console.log("mounted list");
44
36
  });
45
37
  try {
46
- await rootStore.update(props.type, locale.value);
38
+ await $rootStore.update("all", locale.value);
47
39
  } catch (error) {
48
40
  console.log("error fetching update list: ", error);
49
41
  }
50
42
  onBeforeUnmount(() => {
51
- rootStore.resetState(props.type, locale.value);
52
43
  });
53
44
  </script>
54
45
 
@@ -1,17 +1,30 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="$router.push(localePath('/activities/news/' + item.slug[locale]))"
6
7
  >
7
- <v-col align-self="center" cols="7" class="text-h6 dense">
8
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
9
+ <MiscAtomsImageContainer
10
+ cover
11
+ :loading="$stores.people.loading"
12
+ :src="item.image.url ? item.image : '/default.png'"
13
+ :ratio="1 / 1"
14
+ :name="item.lastname + ' ' + item.firstname"
15
+ :slug="item.slug"
16
+ link="people-slug"
17
+ width="80px"
18
+ />
19
+ </v-col>
20
+ <v-col align-self="center" class="text-h5 dense pl-2">
8
21
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
9
22
  <template v-else>
10
23
  {{ item.name }}
11
24
  </template>
12
25
  </v-col>
13
26
 
14
- <v-col align-self="center" cols="5" class="dense">
27
+ <v-col align-self="center">
15
28
  <v-skeleton-loader
16
29
  v-if="rootStore.loading"
17
30
  :type="
@@ -36,7 +49,7 @@ import { useDisplay } from "vuetify";
36
49
  import { useRootStore } from "../../stores/root";
37
50
  import { computed, useNuxtApp, useI18n, useLocalePath } from "#imports";
38
51
  const { $stores } = useNuxtApp();
39
- const { name } = useDisplay();
52
+ const { name, mdAndUp } = useDisplay();
40
53
  const localePath = useLocalePath();
41
54
  const { locale } = useI18n();
42
55
  const rootStore = useRootStore();
@@ -3,7 +3,14 @@
3
3
  v-ripple
4
4
  no-gutters
5
5
  class="cursor-pointer highlight-on-hover"
6
- @click="$router.push(localePath('/people/' + item.slug))"
6
+ @click="
7
+ $router.push(
8
+ localePath({
9
+ name: 'people-slug',
10
+ params: { slug: item.slug },
11
+ }),
12
+ )
13
+ "
7
14
  >
8
15
  <v-col v-if="mdAndUp" align-self="center" cols="1">
9
16
  <MiscAtomsImageContainer
@@ -14,10 +21,10 @@
14
21
  :name="item.lastname + ' ' + item.firstname"
15
22
  :slug="item.slug"
16
23
  link="people-slug"
17
- width="50"
24
+ width="80px"
18
25
  />
19
26
  </v-col>
20
- <v-col align-self="center" class="text-h6 pl-2">
27
+ <v-col align-self="center" class="text-h6 dense pl-2">
21
28
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
22
29
  <div v-else class="text-h5">
23
30
  {{ item.firstname + " " + item.lastname }}
@@ -26,7 +33,7 @@
26
33
  {{ item.groups.vintage ? item.groups.vintage[0].theme : "" }}
27
34
  </div>
28
35
  </v-col>
29
- <v-col align-self="center">
36
+ <v-col align-self="center" cols="auto">
30
37
  <PeopleGroupBadges :item="item" />
31
38
  </v-col>
32
39
  </v-row>
@@ -1,10 +1,30 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
- @click="$router.push(localePath('/projects/' + item.slug[locale]))"
6
+ @click="
7
+ $router.push(
8
+ localePath({
9
+ name: 'activities-projects-slug',
10
+ params: { slug: item.slug[locale] },
11
+ }),
12
+ )
13
+ "
6
14
  >
7
- <v-col align-self="center" cols="7" class="text-h6 dense">
15
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
16
+ <MiscAtomsImageContainer
17
+ cover
18
+ :loading="$stores.projects.loading"
19
+ :src="item.image.url ? item.image : '/default.png'"
20
+ :ratio="1 / 1"
21
+ :name="item.name"
22
+ :slug="item.slug[locale]"
23
+ link="activities-projects-slug"
24
+ width="50"
25
+ />
26
+ </v-col>
27
+ <v-col align-self="center" class="text-h5 dense pl-2">
8
28
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
9
29
  <template v-else>
10
30
  {{ item.name }}
@@ -33,7 +53,7 @@ import { useDisplay } from "vuetify";
33
53
  import { useRootStore } from "../../stores/root";
34
54
  import { computed, useNuxtApp, useI18n, useLocalePath } from "#imports";
35
55
  const { $stores } = useNuxtApp();
36
- const { name } = useDisplay();
56
+ const { name, mdAndUp } = useDisplay();
37
57
  const localePath = useLocalePath();
38
58
  const { locale } = useI18n();
39
59
  const rootStore = useRootStore();
@@ -1,19 +1,32 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="
6
7
  $router.push(localePath('/activities/publications/' + item.slug[locale]))
7
8
  "
8
9
  >
9
- <v-col align-self="center" cols="7" class="text-h6 dense">
10
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
11
+ <MiscAtomsImageContainer
12
+ cover
13
+ :loading="$stores.people.loading"
14
+ :src="item.image.url ? item.image : '/default.png'"
15
+ :ratio="1 / 1"
16
+ :name="item.lastname + ' ' + item.firstname"
17
+ :slug="item.slug[locale]"
18
+ link="activities-publications-slug"
19
+ width="80px"
20
+ />
21
+ </v-col>
22
+ <v-col align-self="center" class="text-h5 dense pl-2">
10
23
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
11
24
  <template v-else>
12
25
  {{ item.name }}
13
26
  </template>
14
27
  </v-col>
15
28
 
16
- <v-col align-self="center" cols="5" class="dense">
29
+ <v-col align-self="center">
17
30
  <v-skeleton-loader
18
31
  v-if="rootStore.loading"
19
32
  :type="
@@ -38,7 +51,7 @@ import { useDisplay } from "vuetify";
38
51
  import { useRootStore } from "../../stores/root";
39
52
  import { computed, useNuxtApp, useI18n, useLocalePath } from "#imports";
40
53
  const { $stores } = useNuxtApp();
41
- const { name } = useDisplay();
54
+ const { name, mdAndUp } = useDisplay();
42
55
  const localePath = useLocalePath();
43
56
  const { locale } = useI18n();
44
57
  const rootStore = useRootStore();
@@ -4,6 +4,19 @@ query search($appId: ID = "", $search: String = "", $lang: String = "en") {
4
4
  items {
5
5
  firstname
6
6
  id
7
+ groups {
8
+ board
9
+ fellows
10
+ sab
11
+ sponsor
12
+ team
13
+ vintage {
14
+ name
15
+ theme
16
+ url
17
+ year
18
+ }
19
+ }
7
20
  image {
8
21
  alt
9
22
  backgroundColor
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "license": "AGPL-3.0-only",
3
3
  "main": "./dist/module.mjs",
4
- "version": "1.0.106",
4
+ "version": "1.0.107",
5
5
  "name": "@paris-ias/list",
6
6
  "repository": {
7
7
  "url": "git+https://github.com/IEA-Paris/list.git",
@@ -1,59 +0,0 @@
1
- <template>
2
- <v-divider />
3
- <div class="d-flex align-center justify-space-between my-6">
4
- <div class="d-flex flex-column">
5
- <div class="text-h4">
6
- {{ capitalize($t("items." + props.type, 2)) }}
7
- </div>
8
- <div class="text-overline">
9
- {{
10
- feminine
11
- ? $t(
12
- "list.0-items-found-f",
13
- [
14
- $stores[type].total,
15
- $t("items." + props.type, $stores[type].total),
16
- ],
17
- $stores[type].total,
18
- )
19
- : $t(
20
- "list.0-items-found",
21
- [
22
- $stores[type].total,
23
- $t("items." + props.type, $stores[type].total),
24
- ],
25
- $stores[type].total,
26
- )
27
- }}
28
- </div>
29
- </div>
30
- <v-spacer />
31
- <v-btn
32
- class="ma-2"
33
- color="default"
34
- variant="outlined"
35
- rounded="0"
36
- :to="localePath(type === 'people' ? '/people' : '/activities/' + type)"
37
- @click="$emit('add')"
38
- >
39
- {{ $t("list.pls-x-more", [$stores[type].total]) }}
40
- </v-btn>
41
- </div>
42
- </template>
43
-
44
- <script setup>
45
- import { useNuxtApp, useLocalePath } from "#imports";
46
- const localePath = useLocalePath();
47
- const { $stores } = useNuxtApp();
48
- const props = defineProps({
49
- type: {
50
- type: String,
51
- required: true
52
- },
53
- feminine: {
54
- type: Boolean,
55
- required: false,
56
- default: false
57
- }
58
- });
59
- </script>