Skip to content

Commit 49cc8cc

Browse files
committed
feature: Add events pagination
1 parent 2ffcc62 commit 49cc8cc

File tree

10 files changed

+696
-33
lines changed

10 files changed

+696
-33
lines changed

src/shared/lib/io/use-events-requests.ts

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import {storeToRefs} from "pinia";
22
import {useEventsStore, useProfileStore} from "../../stores";
3-
import type { EventId, EventType, ServerEvent } from '../../types';
3+
import type { EventId, EventType, EventTypeCount, EventsPreviewMeta, ServerEvent } from '../../types';
44
import { REST_API_URL } from "./constants";
55

66
type TUseEventsRequests = () => {
77
getAll: () => Promise<ServerEvent<unknown>[]>,
8+
getPreviewPageByType: (
9+
type: EventType,
10+
limit: number,
11+
cursor?: string | null
12+
) => Promise<{ data: ServerEvent<unknown>[]; meta: EventsPreviewMeta | null }>,
13+
getTypeCounts: () => Promise<EventTypeCount[]>,
814
getSingle: (id: EventId) => Promise<ServerEvent<EventType> | null>,
915
deleteAll: () => Promise<void | Response>,
1016
deleteList: (uuids: EventId[]) => Promise<void | Response>,
@@ -22,6 +28,25 @@ export const useEventsRequests: TUseEventsRequests = () => {
2228
const headers = {"X-Auth-Token": token.value }
2329
const getEventRestUrl = (param: string): string => `${REST_API_URL}/api/event/${param}${project.value ? `?project=${project.value}` : ''}`
2430
const getEventsPreviewRestUrl = (): string => `${REST_API_URL}/api/events/preview${project.value ? `?project=${project.value}` : ''}`
31+
const getEventsPreviewByTypeRestUrl = (
32+
type: EventType,
33+
limit: number,
34+
cursor?: string | null
35+
): string => {
36+
const params = new URLSearchParams({
37+
type,
38+
limit: String(limit),
39+
...(project.value ? { project: project.value } : {}),
40+
})
41+
42+
if (cursor) {
43+
params.set('cursor', cursor)
44+
}
45+
46+
return `${REST_API_URL}/api/events/preview?${params.toString()}`
47+
}
48+
const getEventsTypeCountsRestUrl = (): string =>
49+
`${REST_API_URL}/api/events/type-counts${project.value ? `?project=${project.value}` : ''}`
2550

2651
const getAll = () => fetch(getEventsPreviewRestUrl(), { headers })
2752
.then((response) => response.json())
@@ -41,6 +66,45 @@ export const useEventsRequests: TUseEventsRequests = () => {
4166
})
4267
.then((events: ServerEvent<unknown>[]) => events)
4368

69+
const getPreviewPageByType = (type: EventType, limit: number, cursor?: string | null) =>
70+
fetch(getEventsPreviewByTypeRestUrl(type, limit, cursor), { headers })
71+
.then((response) => response.json())
72+
.then((response) => {
73+
if (response?.data) {
74+
return {
75+
data: response.data as ServerEvent<unknown>[],
76+
meta: (response.meta ?? null) as EventsPreviewMeta | null,
77+
}
78+
}
79+
80+
if (response?.code === 403) {
81+
console.error('Forbidden')
82+
return { data: [], meta: null }
83+
}
84+
85+
console.error('Fetch Error')
86+
87+
return { data: [], meta: null }
88+
})
89+
90+
const getTypeCounts = () => fetch(getEventsTypeCountsRestUrl(), { headers })
91+
.then((response) => response.json())
92+
.then((response) => {
93+
if (response?.data) {
94+
return response.data as EventTypeCount[]
95+
}
96+
97+
if (response?.code === 403) {
98+
console.error('Forbidden')
99+
return [];
100+
}
101+
102+
console.error('Fetch Error')
103+
104+
return [];
105+
})
106+
.then((counts: EventTypeCount[]) => counts)
107+
44108
const getSingle = (id: EventId) => fetch(getEventRestUrl(id), {headers})
45109
.then((response) => response.json())
46110
.then((response) => {
@@ -91,6 +155,8 @@ export const useEventsRequests: TUseEventsRequests = () => {
91155

92156
return {
93157
getAll,
158+
getPreviewPageByType,
159+
getTypeCounts,
94160
getSingle,
95161
deleteAll,
96162
deleteList,

src/shared/lib/use-api-transport/use-api-transport.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export const useApiTransport = () => {
2626
const connectionStore = useConnectionStore()
2727
const {
2828
getAll,
29+
getPreviewPageByType,
30+
getTypeCounts,
2931
getSingle,
3032
deleteAll,
3133
deleteList,
@@ -137,6 +139,8 @@ export const useApiTransport = () => {
137139

138140
return {
139141
getEventsAll: getAll,
142+
getEventsPreviewByTypePage: getPreviewPageByType,
143+
getEventsTypeCounts: getTypeCounts,
140144
getEvent: getSingle,
141145
deleteEvent,
142146
deleteEventsAll,

src/shared/lib/use-events/use-events-api.ts

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { storeToRefs } from "pinia";
22
import type { Ref } from 'vue';
33
import { useEventsStore } from "../../stores";
4-
import type { EventId, EventType, ServerEvent } from '../../types';
4+
import { EventTypes, type EventId, type EventType, type EventsPreviewMeta, type ServerEvent } from '../../types';
55
import { useApiTransport } from '../use-api-transport'
66

77

88
export type TUseEventsApi = {
99
items: Ref<ServerEvent<unknown>[]>
1010
getItem: (id: EventId) => Promise<ServerEvent<EventType> | null>
1111
getAll: () => void
12+
loadMoreByType: (
13+
type: EventType,
14+
cursor?: string | null
15+
) => Promise<{ meta: EventsPreviewMeta | null; data: ServerEvent<unknown>[] }>
1216
removeAll: () => void
1317
removeByType: (type: EventType) => void
1418
removeById: (id: EventId) => void
@@ -26,10 +30,13 @@ export const useEventsApi = (): TUseEventsApi => {
2630
deleteEventsAll,
2731
deleteEventsList,
2832
deleteEventsByType,
29-
getEventsAll,
33+
getEventsPreviewByTypePage,
34+
getEventsTypeCounts,
3035
getEvent,
3136
} = useApiTransport();
3237

38+
const LOADING_PAGE_SIZE = 25;
39+
3340
const removeList = async (uuids: EventId[]) => {
3441
const res = await deleteEventsList(uuids)
3542

@@ -79,22 +86,63 @@ export const useEventsApi = (): TUseEventsApi => {
7986
}
8087

8188
const getAll = () => {
82-
getEventsAll().then((eventsList: ServerEvent<unknown>[]) => {
83-
if (eventsList.length) {
84-
eventsStore.initializeEvents(eventsList);
85-
} else {
86-
// NOTE: clear cached events hardly
87-
eventsStore.removeAll();
88-
}
89-
}).catch((e) => {
90-
console.error(e);
89+
eventsStore.initializeEvents([]);
90+
eventsStore.resetPreviewPagination();
91+
92+
getEventsTypeCounts()
93+
.then((typeCounts) => {
94+
eventsStore.setEventCounts(typeCounts);
95+
})
96+
.catch((e) => {
97+
console.error(e);
98+
eventsStore.resetEventCounts();
99+
});
100+
101+
Object.values(EventTypes).forEach((eventType) => {
102+
getEventsPreviewByTypePage(eventType, LOADING_PAGE_SIZE)
103+
.then(({ data, meta }) => {
104+
if (data.length) {
105+
eventsStore.mergeEvents(data, { updateCounts: false });
106+
}
107+
eventsStore.setPreviewPagination(eventType, meta);
108+
})
109+
.catch((e) => {
110+
console.error(e);
111+
})
91112
})
92113
}
93114

115+
const loadMoreByType = async (eventType: EventType, cursor?: string | null) => {
116+
const pagination = eventsStore.previewPagination[eventType as EventTypes];
117+
if (!pagination?.hasMore) {
118+
return { meta: null, data: [] };
119+
}
120+
121+
const requestCursor = cursor ?? pagination.cursor;
122+
const { data, meta } = await getEventsPreviewByTypePage(
123+
eventType,
124+
LOADING_PAGE_SIZE,
125+
requestCursor,
126+
);
127+
128+
if (data.length) {
129+
eventsStore.mergeEvents(data, { updateCounts: false });
130+
131+
if (eventsStore.cachedIds[eventType]?.length) {
132+
eventsStore.appendCachedIds(eventType, data.map(({ uuid }) => uuid));
133+
}
134+
}
135+
136+
eventsStore.setPreviewPagination(eventType, meta);
137+
138+
return { meta, data };
139+
}
140+
94141
return {
95142
items: events as unknown as Ref<ServerEvent<unknown>[]>,
96143
getItem: getEvent,
97144
getAll,
145+
loadMoreByType,
98146
removeAll,
99147
removeByType,
100148
removeById,

0 commit comments

Comments
 (0)