Skip to content

Commit e7a3872

Browse files
committed
feat(list): create navbar list and basic fetching
1 parent 13e97d1 commit e7a3872

17 files changed

+603
-403
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import type { NVirtualList, VirtualListInst } from 'naive-ui';
2-
32
import type { Ref } from 'vue';
43

54
export type VirtualListRef = VirtualListInst & typeof NVirtualList;
5+
export type VirtualListProps = {
6+
itemSize?: number;
7+
visibleItemsTag?: string | ObjectConstructor;
8+
visibleItemsProps?: ObjectConstructor;
9+
paddingTop?: string | number;
10+
paddingBottom?: string | number;
11+
};
612

713
export type OnScroll = (listRef: Ref<VirtualListRef | undefined>) => void;
814
export type OnUpdated = (listRef: Ref<VirtualListRef | undefined>) => void;

src/components/common/list/ListScroll.vue

+13-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { ref, toRefs } from 'vue';
55
66
import type { PropType, Ref, Transition } from 'vue';
77
8-
import type { VirtualListRef } from '~/components/common/list/ListScroll.model';
8+
import type {
9+
VirtualListProps,
10+
VirtualListRef,
11+
} from '~/components/common/list/ListScroll.model';
912
import type { TraktClientPagination } from '~/models/trakt/trakt-client.model';
1013
1114
import ListEmpty from '~/components/common/list/ListEmpty.vue';
@@ -29,6 +32,10 @@ const props = defineProps({
2932
type: Number,
3033
required: false,
3134
},
35+
listOptions: {
36+
type: Object as PropType<VirtualListProps>,
37+
required: false,
38+
},
3239
});
3340
3441
const emits = defineEmits<{
@@ -59,14 +66,14 @@ const onUpdatedHandler = () => {
5966
v-if="items.length || loading"
6067
ref="virtualList"
6168
class="list-scroll"
62-
:item-size="80"
6369
:data-length="items.length"
6470
:data-page-size="pageSize"
71+
:item-size="listOptions?.itemSize ?? 80"
6572
:items="items"
66-
:visible-items-tag="NTimeline"
67-
:visible-items-tag-props="{ size: 'large' }"
68-
:padding-top="56"
69-
:padding-bottom="16"
73+
:visible-items-tag="listOptions?.visibleItemsTag ?? NTimeline"
74+
:visible-items-props="{ size: 'large', ...listOptions?.visibleItemsProps }"
75+
:padding-top="listOptions?.paddingTop ?? 56"
76+
:padding-bottom="listOptions?.paddingBottom ?? 16"
7077
@scroll="onScrollHandler"
7178
@vue:updated="onUpdatedHandler"
7279
>

src/components/common/navbar/NavbarComponent.vue

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ const navigate = (to: Route) => {
1717
router.push(to);
1818
};
1919
20-
const routes = [Route.Progress, Route.Calendar, Route.History, Route.List, Route.Search];
20+
const routes = [
21+
Route.Progress,
22+
Route.Calendar,
23+
Route.History,
24+
Route.Watchlist,
25+
Route.Search,
26+
];
2127
2228
const isHover = ref(false);
2329
const isFocus = ref(false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<script setup lang="ts">
2+
import { NSelect, NTooltip, type SelectOption } from 'naive-ui';
3+
4+
import { onMounted, ref, toRefs, watch } from 'vue';
5+
6+
import { useI18n } from '~/utils';
7+
8+
const i18n = useI18n('navbar');
9+
10+
const props = defineProps({
11+
parentElement: {
12+
type: HTMLElement,
13+
required: false,
14+
},
15+
pageSize: {
16+
type: Number,
17+
required: true,
18+
},
19+
});
20+
21+
const emit = defineEmits<{
22+
(e: 'update:pageSize', value: number): void;
23+
}>();
24+
25+
const pageSizeOptions: SelectOption[] = [
26+
{ label: '50', value: 50 },
27+
{ label: '100', value: 100 },
28+
{ label: '200', value: 200 },
29+
{ label: '500', value: 500 },
30+
{ label: '1000', value: 1000 },
31+
];
32+
33+
const { pageSize } = toRefs(props);
34+
const innerValue = ref(pageSize.value);
35+
36+
onMounted(() => {
37+
watch(innerValue, () => emit('update:pageSize', innerValue.value));
38+
});
39+
</script>
40+
41+
<template>
42+
<NTooltip
43+
:show-arrow="false"
44+
placement="bottom"
45+
:delay="1000"
46+
trigger="hover"
47+
:to="parentElement"
48+
>
49+
<span> {{ i18n('page_size') }} </span>
50+
<template #trigger>
51+
<NSelect
52+
v-model:value="innerValue"
53+
class="page-select"
54+
:options="pageSizeOptions"
55+
:to="parentElement"
56+
/>
57+
</template>
58+
</NTooltip>
59+
</template>
60+
61+
<style scoped lang="scss">
62+
.page-select {
63+
flex: 0 0 5rem;
64+
}
65+
</style>

src/components/container/ContainerComponent.ce.vue

+13-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,19 @@ const root = ref<HTMLElement>();
9999
}
100100
101101
@media (prefers-color-scheme: dark) {
102-
@include mixin.hover-background(rgb(0 0 0 / 80%), rgb(0 0 0 / 90%));
102+
@include mixin.hover-background(var(--bg-black-80), var(--bg-black-90));
103+
}
104+
}
105+
106+
.n-select-menu {
107+
@include mixin.hover-background(var(--bg-red-20), var(--bg-red-80));
108+
109+
@media (prefers-color-scheme: light) {
110+
@include mixin.hover-background(var(--bg-red-20), var(--bg-red-80));
111+
}
112+
113+
@media (prefers-color-scheme: dark) {
114+
@include mixin.hover-background(var(--bg-black-20), var(--bg-black-80));
103115
}
104116
}
105117

src/components/views/history/HistoryItem.vue

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ defineProps({
1717
1818
const getTitle = (media: TraktHistory) => {
1919
if ('movie' in media) return media.movie.title;
20+
if (!media.episode) return media.show?.title;
2021
const number = media.episode?.number?.toString().padStart(2, '0');
2122
return `${media.episode?.season}x${number} - ${media?.episode?.title}`;
2223
};

src/components/views/history/HistoryNavbar.vue

+20-42
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
<script setup lang="ts">
2-
import { NDatePicker, NFlex, NIcon, NInput, NSelect, NTooltip } from 'naive-ui';
3-
import { computed, defineProps, ref, watch } from 'vue';
2+
import { NDatePicker, NFlex, NIcon, NInput } from 'naive-ui';
43
5-
import type { SelectOption } from 'naive-ui';
4+
import { computed, defineProps, ref, watch } from 'vue';
65
6+
import NavbarPageSizeSelect from '~/components/common/navbar/NavbarPageSizeSelect.vue';
77
import IconLoop from '~/components/icons/IconLoop.vue';
8+
89
import { useHistoryStore, useHistoryStoreRefs } from '~/stores/data/history.store';
10+
import { useI18n } from '~/utils';
911
import { debounce } from '~/utils/debounce.utils';
1012
13+
const i18n = useI18n('navbar');
14+
1115
const { searchHistory, historyEnd, historyStart, pageSize } = useHistoryStoreRefs();
1216
const { setHistoryRange } = useHistoryStore();
1317
1418
const debouncedSearch = ref(searchHistory.value);
1519
16-
const pageSizeOptions: SelectOption[] = [
17-
{ label: '50', value: 50 },
18-
{ label: '100', value: 100 },
19-
{ label: '200', value: 200 },
20-
{ label: '500', value: 500 },
21-
{ label: '1000', value: 1000 },
22-
];
23-
2420
defineProps({
25-
parentElement: HTMLElement,
21+
parentElement: {
22+
type: HTMLElement,
23+
required: false,
24+
},
2625
});
2726
2827
watch(searchHistory, () => {
@@ -51,9 +50,9 @@ const onDateChange = debounce((values?: [number, number]) => {
5150
</script>
5251

5352
<template>
54-
<NFlex class="row" align="center" justify="center" :vertical="false">
53+
<NFlex class="row" align="center" justify="space-evenly" :vertical="false">
5554
<NDatePicker
56-
class="picker"
55+
class="date-picker"
5756
type="daterange"
5857
:to="parentElement"
5958
:default-value="[Date.now(), Date.now()]"
@@ -67,7 +66,7 @@ const onDateChange = debounce((values?: [number, number]) => {
6766
/>
6867
<NInput
6968
v-model:value="debouncedSearch"
70-
class="input"
69+
class="search-input"
7170
placeholder="Search"
7271
autosize
7372
clearable
@@ -76,42 +75,21 @@ const onDateChange = debounce((values?: [number, number]) => {
7675
<NIcon :component="IconLoop" />
7776
</template>
7877
</NInput>
79-
<NTooltip
80-
:show-arrow="false"
81-
placement="bottom"
82-
:delay="500"
83-
trigger="hover"
84-
:to="parentElement"
85-
>
86-
<span> Page size </span>
87-
<template #trigger>
88-
<NSelect
89-
v-model:value="pageSize"
90-
class="empty select"
91-
:options="pageSizeOptions"
92-
:to="parentElement"
93-
/>
94-
</template>
95-
</NTooltip>
78+
<NavbarPageSizeSelect v-model:page-size="pageSize" :parent-element="parentElement" />
9679
</NFlex>
9780
</template>
9881

9982
<style lang="scss" scoped>
100-
@use '~/styles/mixin' as mixin;
101-
10283
.row {
10384
width: 100%;
85+
padding: 0 0.5rem;
10486
105-
.picker {
106-
flex: 0 1 47%;
107-
}
108-
109-
.input {
110-
flex: 0 1 calc(47% - 5rem);
87+
.date-picker {
88+
flex: 0 1 50%;
11189
}
11290
113-
.select {
114-
flex: 0 1 5rem;
91+
.search-input {
92+
flex: 1 1 calc(46% - 5rem);
11593
}
11694
}
11795
</style>

src/components/views/list/ListComponent.vue

-11
This file was deleted.

src/components/views/list/index.ts

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<script lang="ts" setup>
2+
import { onMounted, ref } from 'vue';
3+
4+
import type { TraktClientPagination } from '~/models/trakt/trakt-client.model';
5+
import type { TraktWatchlist } from '~/models/trakt/trakt-watchlist.model';
6+
7+
import ListScroll from '~/components/common/list/ListScroll.vue';
8+
import HistoryItem from '~/components/views/history/HistoryItem.vue';
9+
10+
import { TraktService } from '~/services/trakt.service';
11+
import { useUserSettingsStoreRefs } from '~/stores/settings/user.store';
12+
13+
const { user } = useUserSettingsStoreRefs();
14+
15+
const list = ref<TraktWatchlist[]>([]);
16+
const pagination = ref<TraktClientPagination>();
17+
const loading = ref(true);
18+
const pageSize = 100;
19+
20+
onMounted(() => {
21+
console.info('This is a list component');
22+
TraktService.traktClient.sync.collection.get.cached({ type: 'movies' });
23+
TraktService.traktClient.sync.collection.get.cached({ type: 'shows' });
24+
TraktService.traktClient.sync.watchlist.get.cached().then(async res => {
25+
list.value = await res.json();
26+
pagination.value = res.pagination;
27+
loading.value = false;
28+
});
29+
TraktService.traktClient.users.lists.get.cached({ id: user.value });
30+
TraktService.traktClient.users.lists.collaborations.cached({ id: user.value });
31+
});
32+
</script>
33+
34+
<template>
35+
<ListScroll
36+
:items="list"
37+
:loading="loading"
38+
:pagination="pagination"
39+
:page-size="pageSize"
40+
:list-options="{ itemSize: 51 }"
41+
>
42+
<template #default="{ item, index }">
43+
<HistoryItem :item="item" :index="index" />
44+
</template>
45+
</ListScroll>
46+
</template>

0 commit comments

Comments
 (0)