diff --git a/src/components/ResourceTable.tsx b/src/components/ResourceTable.tsx index 77702e8..76824fd 100644 --- a/src/components/ResourceTable.tsx +++ b/src/components/ResourceTable.tsx @@ -4,9 +4,10 @@ import { ClipboardDocumentListIcon } from '@heroicons/react/24/outline'; import Image from 'next/image'; import Link from 'next/link'; import { translateEnumPlatform, translateEnumSkill } from '~/utils/enumWordLut'; -import { type ChangeEvent, type Dispatch, type SetStateAction, useState } from 'react'; +import { type ChangeEvent } from 'react'; import { ChevronDownIcon } from '@heroicons/react/24/outline'; import { type ParsedUrlQuery, type ParsedUrlQueryInput } from 'querystring'; +import { useRouter } from 'next/router'; export const ResourceInfo = ({resource, showMoreInfo}: {resource: AuditoryResource, showMoreInfo?: boolean}) => { const PriceIcons = ({type}: {type: PaymentType}) => { @@ -169,10 +170,10 @@ interface PagesNavigationProps { currentPage: number; pageCount: number; resultsPerPage: number; - updateResultsPerPage: Dispatch>; } -const PagesNavigation = ({query, currentPage, pageCount, resultsPerPage, updateResultsPerPage}: PagesNavigationProps) => { +const PagesNavigation = ({query, currentPage, pageCount, resultsPerPage}: PagesNavigationProps) => { + const router = useRouter(); const PageButton = ({number}: {number: number}) => { const redirectQueryData: ParsedUrlQueryInput = {...query}; redirectQueryData.page = number; @@ -194,7 +195,28 @@ const PagesNavigation = ({query, currentPage, pageCount, resultsPerPage, updateR }); const handleChange = (event: ChangeEvent) => { - updateResultsPerPage(parseInt(event.target.value)); + if (!query) { + router.push({ + pathname: '/resources', + query: { + perPage: event.target.value, + } + }).catch((reason) => { + console.error(reason); + }); + + return; + } + + query['perPage'] = event.target.value; + router.push({ + pathname: '/resources', + query: { + ...query, + } + }).catch((reason) => { + console.error(reason); + }); }; return ( @@ -225,21 +247,23 @@ const PagesNavigation = ({query, currentPage, pageCount, resultsPerPage, updateR ) } -const ResourceTable = ({resources, currentPage, query}: {resources?: AuditoryResource[], currentPage: number, query?: ParsedUrlQuery}) => { - const [resourcesPerPage, setResourcesPerPage] = useState(10); - - const totalPages = Math.ceil((resources?.length ?? 0) / resourcesPerPage); - const pageResources = resources?.slice(resourcesPerPage*(currentPage-1), (resourcesPerPage*currentPage)) ?? []; - const resourceElements = pageResources?.map((resource, index) => { - return (); +const ResourceTable = ({resources, resourcesPerPage, currentPage, totalPages, query}: { + resources: AuditoryResource[], + resourcesPerPage: number, + currentPage: number, + totalPages: number, + query: ParsedUrlQuery +}) => { + const resourceElements = resources.map((resource, index) => { + return (); }) ?? []; return(
-
- - - +
+ +
+
@@ -262,6 +286,9 @@ const ResourceTable = ({resources, currentPage, query}: {resources?: AuditoryRes {resourceElements}
+ {(resources && resources.length > 4) ? + + : undefined}
); diff --git a/src/pages/resources/index.tsx b/src/pages/resources/index.tsx index 52f7cdc..c441d32 100644 --- a/src/pages/resources/index.tsx +++ b/src/pages/resources/index.tsx @@ -12,17 +12,21 @@ const Resources = () => { const queryData = parseQueryData(router.query); const currentPage = queryData.page; - const query = api.auditoryResource.search.useQuery({ - ages: queryData.age, - platforms: queryData.platforms, - skill_levels: queryData.skill_levels, - skills: queryData.skills, + const resourceQuery = api.auditoryResource.search.useQuery({ + skip: (queryData.page - 1) * queryData.perPage, + take: queryData.perPage, + ages: queryData.age, + platforms: queryData.platforms, + skill_levels: queryData.skill_levels, + skills: queryData.skills, }); - - if (!query.data) { - return <> + + if (!resourceQuery.data) { + return <> } + const totalPages = Math.ceil(resourceQuery.data.count / queryData.perPage); + return ( <> @@ -43,7 +47,7 @@ const Resources = () => {

for specific resource recommendations.

- + ); diff --git a/src/server/api/routers/auditoryResources.ts b/src/server/api/routers/auditoryResources.ts index 20a28b3..46dede4 100644 --- a/src/server/api/routers/auditoryResources.ts +++ b/src/server/api/routers/auditoryResources.ts @@ -1,4 +1,4 @@ -import { SkillLevel, Skill, Platform, AuditoryResource } from "@prisma/client"; +import { SkillLevel, Skill, Platform, type AuditoryResource } from "@prisma/client"; import { z } from "zod"; import { @@ -24,6 +24,8 @@ export const auditoryResourceRouter = createTRPCRouter({ search: publicProcedure .input(z.object({ + take: z.number().int(), + skip: z.number().int(), ages: z.object({ min: z.number().int(), max: z.number().int(), @@ -32,34 +34,47 @@ export const auditoryResourceRouter = createTRPCRouter({ skill_levels: z.nativeEnum(SkillLevel).array().optional(), skills: z.nativeEnum(Skill).array().optional(), })) - .query(({ input, ctx}) => { - - return ctx.prisma.auditoryResource.findMany({ - where: { - ages: { - is: { - min: { - lte: input.ages?.min, - }, - max: { - gte: input.ages?.max, - } + .query(async ({ input, ctx}) => { + const search = { + ages: { + is: { + min: { + lte: input.ages?.min, + }, + max: { + gte: input.ages?.max, } - }, - skill_levels: { - hasEvery: input.skill_levels ?? [], - }, - skills: { - hasEvery: input.skills ?? [], - }, - platform_links: { - some: { - platform: { - in: input.platforms, - } + } + }, + skill_levels: { + hasEvery: input.skill_levels ?? [], + }, + skills: { + hasEvery: input.skills ?? [], + }, + platform_links: { + some: { + platform: { + in: input.platforms, } } } - }) + } + + const [count, resources] = await ctx.prisma.$transaction([ + ctx.prisma.auditoryResource.count({ + where: search, + }), + ctx.prisma.auditoryResource.findMany({ + skip: input.skip, + take: input.take, + where: search, + }) + ]); + + return { + count, + resources, + } }), }); diff --git a/src/utils/parseSearchForm.ts b/src/utils/parseSearchForm.ts index 8e75356..eed0b7b 100644 --- a/src/utils/parseSearchForm.ts +++ b/src/utils/parseSearchForm.ts @@ -3,6 +3,7 @@ import { type ParsedUrlQuery } from "querystring"; export interface ViewDetails { page: number; + perPage: number; } export interface SearchQuery { @@ -17,6 +18,7 @@ export type ParsedQueryData = SearchQuery & ViewDetails; export const parseQueryData = (query: ParsedUrlQuery): ParsedQueryData => { const view = { page: Number(query["page"] ?? 1), + perPage: Number(query["perPage"] ?? 10), } const filter: SearchQuery = {};