Skip to content

Commit c90ed78

Browse files
committed
feat(listItem): refactor list item to be more composable
1 parent e7a3872 commit c90ed78

File tree

9 files changed

+141
-47
lines changed

9 files changed

+141
-47
lines changed
4.95 KB
Binary file not shown.
+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<script setup lang="ts">
2+
import { NFlex, NImage, NTimelineItem } from 'naive-ui';
3+
4+
import { computed, type PropType, toRefs } from 'vue';
5+
6+
import PosterPlaceholder from '~/assets/images/poster-placholder.webp';
7+
8+
const props = defineProps({
9+
id: {
10+
type: Number,
11+
required: true,
12+
},
13+
index: {
14+
type: Number,
15+
required: true,
16+
},
17+
poster: {
18+
type: String,
19+
required: false,
20+
default: PosterPlaceholder,
21+
},
22+
type: {
23+
type: String as PropType<'default' | 'error' | 'info' | 'success' | 'warning'>,
24+
required: false,
25+
default: 'default',
26+
},
27+
lineType: {
28+
type: String as PropType<'dashed' | 'default'>,
29+
required: false,
30+
default: 'default',
31+
},
32+
});
33+
34+
const { id, index } = toRefs(props);
35+
36+
const isLoading = computed(() => id?.value < 0);
37+
</script>
38+
39+
<template>
40+
<NTimelineItem
41+
:key="id"
42+
class="timeline-item"
43+
:data-key="id"
44+
:data-index="index"
45+
:type="isLoading ? type : 'success'"
46+
:line-type="isLoading ? lineType : 'default'"
47+
>
48+
<NFlex>
49+
<NImage
50+
alt="poster-image"
51+
class="poster"
52+
lazy
53+
preview-disabled
54+
:src="poster"
55+
:preview-src="poster"
56+
:fallback-src="PosterPlaceholder"
57+
/>
58+
<slot :id="id" :index="index" :loading="isLoading" />
59+
</NFlex>
60+
</NTimelineItem>
61+
</template>
62+
63+
<style lang="scss" scoped>
64+
.timeline-item {
65+
font-variant-numeric: tabular-nums;
66+
margin: 0 1rem;
67+
68+
.poster {
69+
justify-content: center;
70+
width: 5.5rem;
71+
height: 8rem;
72+
background-color: #111;
73+
}
74+
}
75+
</style>

src/components/common/list/ListScroll.vue

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import type {
1212
import type { TraktClientPagination } from '~/models/trakt/trakt-client.model';
1313
1414
import ListEmpty from '~/components/common/list/ListEmpty.vue';
15+
import ListItem from '~/components/common/list/ListItem.vue';
1516
1617
const virtualList = ref<VirtualListRef>();
1718
@@ -68,7 +69,7 @@ const onUpdatedHandler = () => {
6869
class="list-scroll"
6970
:data-length="items.length"
7071
:data-page-size="pageSize"
71-
:item-size="listOptions?.itemSize ?? 80"
72+
:item-size="listOptions?.itemSize ?? 148"
7273
:items="items"
7374
:visible-items-tag="listOptions?.visibleItemsTag ?? NTimeline"
7475
:visible-items-props="{ size: 'large', ...listOptions?.visibleItemsProps }"
@@ -78,7 +79,9 @@ const onUpdatedHandler = () => {
7879
@vue:updated="onUpdatedHandler"
7980
>
8081
<template #default="{ item, index }">
81-
<slot :item="item" :index="index" />
82+
<ListItem :id="item.id" :index="index">
83+
<slot :id="item.id" :item="item" :index="index" :loading="item.id < 0" />
84+
</ListItem>
8285
</template>
8386
</NVirtualList>
8487
<ListEmpty

src/components/views/history/HistoryComponent.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ const onUpdated: OnUpdated = listRef => {
6666
@on-scroll="onScroll"
6767
@on-updated="onUpdated"
6868
>
69-
<template #default="{ item, index }">
70-
<HistoryItem :item="item" :index="index" />
69+
<template #default="{ item, loading: itemLoading }">
70+
<HistoryItem :item="item" :loading="itemLoading" />
7171
</template>
7272
</ListScroll>
7373
</template>
+50-37
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
<script setup lang="ts">
2-
import { NFlex, NSkeleton, NTimelineItem } from 'naive-ui';
2+
import { NFlex, NSkeleton } from 'naive-ui';
3+
4+
import { type PropType } from 'vue';
35
4-
import type { PropType } from 'vue';
56
import type { TraktHistory } from '~/models/trakt/trakt-history.model';
67
8+
import PosterPlaceholder from '~/assets/images/poster-placholder.webp';
9+
710
defineProps({
811
item: {
912
type: Object as PropType<TraktHistory>,
1013
required: true,
1114
},
12-
index: {
13-
type: Number,
15+
loading: {
16+
type: Boolean,
1417
required: true,
1518
},
19+
poster: {
20+
type: String,
21+
required: false,
22+
default: PosterPlaceholder,
23+
},
1624
});
1725
1826
const getTitle = (media: TraktHistory) => {
@@ -32,41 +40,46 @@ const getDate = (media: TraktHistory) =>
3240
</script>
3341

3442
<template>
35-
<template v-if="item.id >= 0">
36-
<NTimelineItem
37-
v-if="item.id >= 0"
38-
:key="item.id"
39-
class="timeline-item"
40-
:data-key="item.id"
41-
:data-index="index"
42-
type="success"
43-
:title="getTitle(item)"
44-
:content="getContent(item)"
45-
:time="getDate(item)"
46-
/>
47-
</template>
48-
<template v-else>
49-
<NTimelineItem
50-
:key="item.id"
51-
class="timeline-item"
52-
:data-key="item.id"
53-
:data-index="index"
54-
line-type="dashed"
55-
>
56-
<template #default>
57-
<NFlex vertical>
58-
<NSkeleton text style="width: 70%" />
59-
<NSkeleton text style="width: 60%" />
60-
<NSkeleton text style="width: 20%" />
61-
</NFlex>
62-
</template>
63-
</NTimelineItem>
64-
</template>
43+
<NFlex class="panel" vertical size="small" :theme-overrides="{ gapSmall: '0' }">
44+
<div class="title">
45+
<NSkeleton v-if="loading" text style="width: 70%" />
46+
<template v-else>{{ getTitle(item) }}</template>
47+
</div>
48+
<div class="content">
49+
<NSkeleton v-if="loading" text style="width: 60%" />
50+
<template v-else>{{ getContent(item) }}</template>
51+
</div>
52+
<div class="time">
53+
<NSkeleton v-if="loading" text style="width: 20%" />
54+
<template v-else>{{ getDate(item) }}</template>
55+
</div>
56+
</NFlex>
6557
</template>
6658

6759
<style lang="scss" scoped>
68-
.timeline-item {
69-
font-variant-numeric: tabular-nums;
70-
margin: 0 1rem;
60+
.panel {
61+
flex: 1 1 auto;
62+
margin: 0.25rem 0;
63+
64+
.title {
65+
margin: var(--n-title-margin);
66+
color: var(--n-title-text-color);
67+
font-weight: var(--n-title-font-weight);
68+
font-size: var(--n-title-font-size);
69+
transition: color 0.3s var(--n-bezier);
70+
}
71+
72+
.content {
73+
color: var(--n-content-text-color);
74+
font-size: var(--n-content-font-size);
75+
transition: color 0.3s var(--n-bezier);
76+
}
77+
78+
.time {
79+
margin-top: 6px;
80+
color: var(--n-meta-text-color);
81+
font-size: 12px;
82+
transition: color 0.3s var(--n-bezier);
83+
}
7184
}
7285
</style>

src/components/views/history/HistoryNavbar.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const onDateChange = debounce((values?: [number, number]) => {
6767
<NInput
6868
v-model:value="debouncedSearch"
6969
class="search-input"
70-
placeholder="Search"
70+
:placeholder="i18n('search')"
7171
autosize
7272
clearable
7373
>

src/components/views/watchlist/WatchlistComponent.vue

+2-3
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,9 @@ onMounted(() => {
3737
:loading="loading"
3838
:pagination="pagination"
3939
:page-size="pageSize"
40-
:list-options="{ itemSize: 51 }"
4140
>
42-
<template #default="{ item, index }">
43-
<HistoryItem :item="item" :index="index" />
41+
<template #default="{ item, loading: itemLoading }">
42+
<HistoryItem :item="item" :loading="itemLoading" />
4443
</template>
4544
</ListScroll>
4645
</template>

src/components/views/watchlist/WatchlistNavbar.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useI18n } from '~/utils';
99
1010
const i18n = useI18n('navbar');
1111
12-
const activeList = ref('watchlist');
12+
const activeList = ref('list-watchlist');
1313
const listOptions = [
1414
{ label: 'Movie collection', value: 'collection-movie' },
1515
{ label: 'TV collection', value: 'collection-tv' },
@@ -41,7 +41,7 @@ defineProps({
4141
<NInput
4242
v-model:value="debouncedSearch"
4343
class="search-input"
44-
placeholder="Search"
44+
:placeholder="i18n('search')"
4545
autosize
4646
clearable
4747
>

src/i18n/en/navbar/navbar.json

+4
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,9 @@
22
"navbar__page_size": {
33
"message": "Page Size",
44
"description": "Page Size tooltip."
5+
},
6+
"navbar__search": {
7+
"message": "Search",
8+
"description": "Search placeholder."
59
}
610
}

0 commit comments

Comments
 (0)