1import { parseWhereWithHandlers } from "@/lib/tanstack/db/utils";
2import { BasicIndex, createCollection, parseLoadSubsetOptions } from "@tanstack/db";
3import { queryCollectionOptions } from "@tanstack/query-db-collection";
4
5export const PAGINATED_MOVIES_COLLECTION_QUERY_KEY = "query-driven-movies";
6export const WATCHLIST_COLLECTION_QUERY_KEY = "query-driven-watchlist";
7
8const MOVIE_SORT_KEYS = [
9 "title",
10 "overview",
11 "vote_average",
12 "release_date",
13 "popularity",
14] as const;
15
16type MoviesWhereClause = {
17 page?: { _eq: number };
18 q?: { _eq?: string; _ilike?: string };
19};
20
21function parseSearchQ(where: MoviesWhereClause | null | undefined) {
22 const raw = where?.q?._eq ?? where?.q?._ilike;
23 if (!raw) return undefined;
24 const stripped = raw.replace(/^%|%$/g, "").trim();
25 return stripped || undefined;
26}
27
28export const queryDrivenMoviesCollection = createCollection(
29 queryCollectionOptions({
30 queryKey: [PAGINATED_MOVIES_COLLECTION_QUERY_KEY],
31 queryFn: async (ctx) => {
32 const where = parseWhereWithHandlers<MoviesWhereClause>(ctx.meta?.loadSubsetOptions?.where);
33 const { sorts } = parseLoadSubsetOptions(ctx.meta?.loadSubsetOptions);
34 const page = where?.page?._eq ?? 1;
35 const q = parseSearchQ(where);
36 const primarySort = sorts[0];
37 const { sortBy, sortOrder: sortDirection } = resolveSortOrder({
38 sortBy: primarySort ? String(primarySort.field.at(-1)) : undefined,
39 sortOrder: primarySort?.direction,
40 allowedKeys: MOVIE_SORT_KEYS,
41 defaultSortBy: "vote_average",
42 defaultSortOrder: "desc",
43 });
44 const response = await getPaginatedFakeMoviesFn({
45 data: { page, perPage: 10, q, sortBy, sortDirection, includeTotal: true },
46 });
47 return response;
48 },
49 select: (data) => data.items,
50 queryClient: getQueryClient(),
51 getKey: (item) => item.id,
52 autoIndex: "eager",
53 defaultIndexType: BasicIndex,
54 syncMode: "on-demand",
55 staleTime: 1000 * 60 * 60,
56 }),
57);