diff --git a/sqlite.db b/sqlite.db index c50aece..21ae70a 100644 Binary files a/sqlite.db and b/sqlite.db differ diff --git a/src/graphql/query/getDealsOffsetBased.graphql b/src/graphql/query/getDealsOffsetBased.graphql new file mode 100644 index 0000000..7bd683f --- /dev/null +++ b/src/graphql/query/getDealsOffsetBased.graphql @@ -0,0 +1,8 @@ +query getDealsOffsetBased($limit: Float!, $offset: Float!) { + dealsOffsetBased(limit: $limit, offset: $offset) { + id + description + title + __typename + } +} diff --git a/src/graphql/query/getDealsOffsetBasedExpanded.graphql b/src/graphql/query/getDealsOffsetBasedExpanded.graphql new file mode 100644 index 0000000..a80699d --- /dev/null +++ b/src/graphql/query/getDealsOffsetBasedExpanded.graphql @@ -0,0 +1,10 @@ +query getDealsOffsetBasedExpanded($limitTotal: Float!, $offsetTotal: Float!) { + dealsOffsetBasedExpanded(limitTotal: $limitTotal, offsetTotal: $offsetTotal) { + deals { + description + id + title + } + totalCount + } +} diff --git a/src/graphql/schema/deals/deals.resolver.ts b/src/graphql/schema/deals/deals.resolver.ts index 1cad4f8..dc94cd5 100644 --- a/src/graphql/schema/deals/deals.resolver.ts +++ b/src/graphql/schema/deals/deals.resolver.ts @@ -1,7 +1,8 @@ import { db } from "@/db/db"; import { deals as dbDeals } from "@/db/schema"; -import { Query, Resolver } from "type-graphql"; -import { Deal } from "./deals"; +import { Arg, Query, Resolver } from "type-graphql"; +import { Deal, DealsResponse } from "./deals"; +import { count } from "drizzle-orm"; @Resolver(Deal) export class DealResolver { @@ -10,4 +11,27 @@ export class DealResolver { const deals = db.select().from(dbDeals).all(); return deals; } + @Query(() => [Deal]) + async dealsOffsetBased( + @Arg("offset") offset: number, + @Arg("limit") limit: number + ): Promise { + const deals = await db.select().from(dbDeals).offset(offset).limit(limit); + return deals; + } + + @Query(() => DealsResponse) + async dealsOffsetBasedExpanded( + @Arg("offsetTotal") offset: number, + @Arg("limitTotal") limit: number + ): Promise { + const deals = await db.select().from(dbDeals).offset(offset).limit(limit); + const totalCountResult = await db.select({ value: count() }).from(dbDeals); + const totalCount = totalCountResult[0].value; + + return { + deals, + totalCount, + }; + } } diff --git a/src/graphql/schema/deals/deals.ts b/src/graphql/schema/deals/deals.ts index 869bde3..6d15a94 100644 --- a/src/graphql/schema/deals/deals.ts +++ b/src/graphql/schema/deals/deals.ts @@ -9,3 +9,12 @@ export class Deal { @Field() description: string; } + +@ObjectType() +export class DealsResponse { + @Field(() => [Deal]) + deals: Deal[]; + + @Field() + totalCount: number; +} diff --git a/src/pages/based-pagination/index.tsx b/src/pages/based-pagination/index.tsx new file mode 100644 index 0000000..bea4e97 --- /dev/null +++ b/src/pages/based-pagination/index.tsx @@ -0,0 +1,92 @@ +import { + GetDealsOffsetBasedDocument, + GetDealsOffsetBasedExpandedDocument, + useGetDealsOffsetBasedExpandedQuery, + useGetDealsOffsetBasedQuery, +} from "@/generated/graphql"; +import { addApolloState, initializeApollo } from "@/utils/apolloClient"; + +export default function BasedPagitanionPage() { + const { data, fetchMore, loading } = useGetDealsOffsetBasedExpandedQuery({ + variables: { + limitTotal: 3, + offsetTotal: 0, + }, + }); + + /* const { data, fetchMore } = useGetDealsOffsetBasedQuery({ + variables: { + limit: 3, + offset: 0, + }, + }); */ + + /* const loadMore = () => { + const currentLength = data.dealsOffsetBased.length || 0; + console.log(currentLength); + fetchMore({ + variables: { + offset: currentLength, + limit: 3, + }, + }); + }; */ + + const loadMore = () => { + const currentLength = data.dealsOffsetBasedExpanded.deals.length || 0; + console.log(currentLength); + fetchMore({ + variables: { + offsetTotal: currentLength, + limitTotal: 3, + }, + }); + }; + + console.log(data); + if (loading) { + return
loading
; + } + + return ( +
+
+ {data.dealsOffsetBasedExpanded.deals && + data.dealsOffsetBasedExpanded.deals.map((deal) => ( +
+

{deal.title}

+
+ ))} + {/* {data.dealsOffsetBased.deals.map((deal) => ( +
+

{deal.title}

+
+ ))} */} + +
+
+ ); +} + +export async function getServerSideProps() { + const apolloClient = initializeApollo(); + + /* await apolloClient.query({ + query: GetDealsOffsetBasedDocument, + variables: { + limit: 3, + offset: 0, + }, + }); */ + /* await apolloClient.query({ + query: GetDealsOffsetBasedExpandedDocument, + variables: { + limitTotal: 3, + offsetTotal: 0, + }, + }); */ + + return addApolloState(apolloClient, { + props: {}, + }); +} diff --git a/src/utils/apolloClient.ts b/src/utils/apolloClient.ts index 2c4b736..1066733 100644 --- a/src/utils/apolloClient.ts +++ b/src/utils/apolloClient.ts @@ -6,6 +6,10 @@ import { from, } from "@apollo/client"; import { onError } from "@apollo/client/link/error"; +import { + concatPagination, + offsetLimitPagination, +} from "@apollo/client/utilities"; import merge from "deepmerge"; import isEqual from "lodash/isEqual"; import { useMemo } from "react"; @@ -33,8 +37,32 @@ function createApolloClient() { return new ApolloClient({ ssrMode: typeof window === "undefined", link: from([errorLink, httpLink]), - connectToDevTools: process.env.NODE_ENV === "development", - cache: new InMemoryCache(), + connectToDevTools: true, + cache: new InMemoryCache({ + typePolicies: { + Query: { + fields: { + dealsOffsetBasedExpanded: { + keyArgs: false, // None of the arguments will be used to generate a separate cache entry + merge(existing, incoming, { args: { offsetTotal = 0 } }) { + // Combines the incoming list of deals with the existing list + + const mergedDeals = existing ? existing.deals.slice(0) : []; + for (let i = 0; i < incoming.deals.length; i++) { + mergedDeals[offsetTotal + i] = incoming.deals[i]; + } + + return { + ...existing, + deals: mergedDeals, + totalCount: incoming.totalCount, // Assumes totalCount is updated with each query + }; + }, + }, + }, + }, + }, + }), }); } @@ -85,3 +113,32 @@ export function useApollo(pageProps) { const store = useMemo(() => initializeApollo(state), [state]); return store; } + +/* cache: new InMemoryCache({ + typePolicies: { + Query: { + fields: { + dealsOffsetBasedExpanded: { + keyArgs: false, // None of the arguments will be used to generate a separate cache entry + merge(existing, incoming, { args: { offsetTotal = 0 } }) { + // Combines the incoming list of deals with the existing list + const mergedDeals = existing ? existing.deals.slice(0) : []; + for (let i = 0; i < incoming.deals.length; ++i) { + mergedDeals[offsetTotal + i] = incoming.deals[i]; + } + // Returns the combined list of deals and the most recent total count + return { + ...existing, + deals: mergedDeals, + totalCount: incoming.totalCount, // Assumes totalCount is updated with each query + }; + }, + // The read function is not strictly necessary here unless you need to restructure the returned data + read(existing) { + return existing; + }, + }, + }, + }, + }, +}), */