diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index d5efd5f..8cd87c3 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -246,7 +246,6 @@ export interface NexusGenObjects { id: number; // Int! judges: NexusGenRootTypes['TournamentJudge'][]; // [TournamentJudge!]! location: string; // String! - makers_count: number; // Int! prizes: NexusGenRootTypes['TournamentPrize'][]; // [TournamentPrize!]! projects_count: number; // Int! start_date: NexusGenScalars['Date']; // Date! @@ -274,6 +273,11 @@ export interface NexusGenObjects { jobTitle: string; // String! name: string; // String! } + TournamentMakersResponse: { // root type + hasNext?: boolean | null; // Boolean + hasPrev?: boolean | null; // Boolean + makers: NexusGenRootTypes['User'][]; // [User!]! + } TournamentPrize: { // root type amount: string; // String! image: string; // String! @@ -487,7 +491,7 @@ export interface NexusGenFieldTypes { getDonationsStats: NexusGenRootTypes['DonationsStats']; // DonationsStats! getFeed: NexusGenRootTypes['Post'][]; // [Post!]! getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails! - getMakersInTournament: NexusGenRootTypes['User'][]; // [User!]! + getMakersInTournament: NexusGenRootTypes['TournamentMakersResponse']; // TournamentMakersResponse! getMyDrafts: NexusGenRootTypes['Post'][]; // [Post!]! getPostById: NexusGenRootTypes['Post']; // Post! getProject: NexusGenRootTypes['Project']; // Project! @@ -577,6 +581,11 @@ export interface NexusGenFieldTypes { jobTitle: string; // String! name: string; // String! } + TournamentMakersResponse: { // field return type + hasNext: boolean | null; // Boolean + hasPrev: boolean | null; // Boolean + makers: NexusGenRootTypes['User'][]; // [User!]! + } TournamentPrize: { // field return type amount: string; // String! image: string; // String! @@ -813,7 +822,7 @@ export interface NexusGenFieldTypeNames { getDonationsStats: 'DonationsStats' getFeed: 'Post' getLnurlDetailsForProject: 'LnurlDetails' - getMakersInTournament: 'User' + getMakersInTournament: 'TournamentMakersResponse' getMyDrafts: 'Post' getPostById: 'Post' getProject: 'Project' @@ -903,6 +912,11 @@ export interface NexusGenFieldTypeNames { jobTitle: 'String' name: 'String' } + TournamentMakersResponse: { // field return type name + hasNext: 'Boolean' + hasPrev: 'Boolean' + makers: 'User' + } TournamentPrize: { // field return type name amount: 'String' image: 'String' diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 878e998..b5e634a 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -252,7 +252,7 @@ type Query { getDonationsStats: DonationsStats! getFeed(skip: Int = 0, sortBy: String, tag: Int = 0, take: Int = 10): [Post!]! getLnurlDetailsForProject(project_id: Int!): LnurlDetails! - getMakersInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): [User!]! + getMakersInTournament(roleId: Int, search: String, skip: Int = 0, take: Int = 10, tournamentId: Int!): TournamentMakersResponse! getMyDrafts(type: POST_TYPE!): [Post!]! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! @@ -374,6 +374,12 @@ type TournamentJudge { name: String! } +type TournamentMakersResponse { + hasNext: Boolean + hasPrev: Boolean + makers: [User!]! +} + type TournamentPrize { amount: String! image: String! diff --git a/api/functions/graphql/types/tournament.js b/api/functions/graphql/types/tournament.js index c8aaffa..eb6e6fc 100644 --- a/api/functions/graphql/types/tournament.js +++ b/api/functions/graphql/types/tournament.js @@ -79,7 +79,11 @@ const Tournament = objectType({ t.nonNull.string('website'); t.nonNull.int('events_count'); - t.nonNull.int('makers_count'); + t.nonNull.int('makers_count', { + resolve(parent) { + return prisma.user.count(); + } + }); t.nonNull.int('projects_count'); t.nonNull.list.nonNull.field('prizes', { type: TournamentPrize, }); @@ -89,6 +93,29 @@ const Tournament = objectType({ } }) + +const TournamentMakersResponse = objectType({ + name: 'TournamentMakersResponse', + definition(t) { + t.boolean('hasNext'); + t.boolean('hasPrev'); + + t.nonNull.list.nonNull.field('makers', { type: "User" }) + } +} +) + +const TournamentProjectsResponse = objectType({ + name: 'TournamentProjectsResponse', + definition(t) { + t.boolean('hasNext'); + t.boolean('hasPrev'); + + t.nonNull.list.nonNull.field('projects', { type: "Project" }) + } +} +) + const getTournamentById = extendType({ type: "Query", definition(t) { @@ -104,18 +131,20 @@ const getTournamentById = extendType({ } }) + + const getMakersInTournament = extendType({ type: "Query", definition(t) { - t.nonNull.list.nonNull.field('getMakersInTournament', { - type: "User", + t.nonNull.field('getMakersInTournament', { + type: TournamentMakersResponse, args: { tournamentId: nonNull(intArg()), ...paginationArgs({ take: 10 }), search: stringArg(), roleId: intArg(), }, - resolve(_, args) { + async resolve(_, args) { let filters = []; @@ -147,15 +176,84 @@ const getMakersInTournament = extendType({ }) - return prisma.user.findMany({ + const makers = await prisma.user.findMany({ ...(filters.length > 0 && { where: { AND: filters } }), skip: args.skip, - take: args.take, + take: args.take + 1, + }); + + return { + hasNext: makers.length === args.take + 1, + hasPrev: args.skip !== 0, + makers: makers.slice(0, args.take) + } + } + }) + } +}) + +const getProjectsInTournament = extendType({ + type: "Query", + definition(t) { + t.nonNull.field('getProjectsInTournament', { + type: TournamentProjectsResponse, + args: { + tournamentId: nonNull(intArg()), + ...paginationArgs({ take: 10 }), + search: stringArg(), + roleId: intArg(), + }, + async resolve(_, args) { + + + let filters = []; + + if (args.search) filters.push({ + OR: [ + { + title: { + contains: args.search, + mode: 'insensitive' + } + }, + { + description: { + contains: args.search, + mode: 'insensitive' + } + } + ] }) + + + // if (args.roleId) filters.push({ + // roles: { + // some: { + // roleId: args.roleId + // } + // } + // }) + + + const makers = await prisma.project.findMany({ + ...(filters.length > 0 && { + where: { + AND: filters + } + }), + skip: args.skip, + take: args.take + 1, + }); + + return { + hasNext: makers.length === args.take + 1, + hasPrev: args.skip !== 0, + makers: makers.slice(0, args.take) + } } }) } diff --git a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx index 4876187..3dde58f 100644 --- a/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakerCard/MakerCard.tsx @@ -13,10 +13,10 @@ import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; import Badge from 'src/Components/Badge/Badge'; import { createRoute, PAGES_ROUTES } from 'src/utils/routing'; -type MakerType = GetMakersInTournamentQuery['getMakersInTournament'][number] +type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] interface Props { - maker: GetMakersInTournamentQuery['getMakersInTournament'][number], + maker: MakerType, isMe?: boolean; } diff --git a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx index bc18640..69b8fad 100644 --- a/src/features/Tournaments/pages/MakersPage/MakersPage.tsx +++ b/src/features/Tournaments/pages/MakersPage/MakersPage.tsx @@ -1,126 +1,29 @@ -import { NetworkStatus } from '@apollo/client'; -import { useDebouncedCallback, useDebouncedState } from '@react-hookz/web'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; -import IconButton from 'src/Components/IconButton/IconButton'; -import LoadingPage from 'src/Components/LoadingPage/LoadingPage'; -import { GenericMakerRole, GetMakersInTournamentQueryVariables, Tournament, useGetMakersInTournamentQuery, User } from 'src/graphql' -import ScrollToTop from 'src/utils/routing/scrollToTop'; +import { Tournament, useMeTournamentQuery, User } from 'src/graphql' import MakerCard from './MakerCard/MakerCard'; import MakerCardSkeleton from './MakerCard/MakerCard.Skeleton'; -import MakersFilters from './MakersFilters/MakersFilters'; +import ParticipantsSection from './ParticipantsSection/ParticipantsSection'; interface Props { data: Pick } -const ITEMS_PER_PAGE = 15; export default function MakersPage({ data: { id } }: Props) { - const [page, setPage] = useState(0) - const [searchFilter, setSearchFilter] = useState(""); - const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); - const [roleFilter, setRoleFilter] = useState(null); - - const loadingContainerCbRef = useCallback((e: HTMLDivElement) => { - if (e) - e.scrollIntoView({ - behavior: 'smooth', - block: "center" - }) - }, []) - - const [queryFilter, setQueryFilter] = useState({ - tournamentId: id, - roleId: roleFilter?.id ?? null, - search: debouncedsearchFilter, - skip: ITEMS_PER_PAGE * page, - take: ITEMS_PER_PAGE, - }); - - - const query = useGetMakersInTournamentQuery({ - variables: queryFilter, - notifyOnNetworkStatusChange: true, - }); - - - useEffect(() => { - setPage(0); - setQueryFilter(f => ({ ...f, search: debouncedsearchFilter, roleId: roleFilter?.id ?? null, skip: 0 })) - }, [debouncedsearchFilter, roleFilter]); - - - - - - if (query.networkStatus === NetworkStatus.loading) return - - - const changeSearchFilter = (new_value: string) => { - setSearchFilter(new_value); - setDebouncedSearchFilter(new_value); - } - - - const nextPage = () => { - setPage(p => p + 1) - setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) + ITEMS_PER_PAGE })) - } - const prevPage = () => { - if (page === 0) return - setPage(p => p - 1) - setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) - ITEMS_PER_PAGE })) - } - - - const isFetchingMore = query.networkStatus === NetworkStatus.setVariables; - const itemsCount = query.data?.getMakersInTournament && query.data.getMakersInTournament.length; - + const query = useMeTournamentQuery(); return (
- {(query.data?.me ?? query.previousData?.me) && } -
-

Makers 👾

- -
- -
-
- {isFetchingMore ? - <> -
- -
- - - + {query.loading ? + : - (itemsCount !== 0 ? - query.data?.getMakersInTournament.map(maker => ) : -
-

No makers found here...

-
) + query.data?.me ? + + : null } - - -
- - - - - - -
+
diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx new file mode 100644 index 0000000..bb281b4 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/MakersList.tsx @@ -0,0 +1,105 @@ +import { useEffect, useRef, useState } from 'react' +import { FaChevronLeft, FaChevronRight } from 'react-icons/fa'; +import IconButton from 'src/Components/IconButton/IconButton'; +import { GetMakersInTournamentQueryVariables, useGetMakersInTournamentQuery } from 'src/graphql'; +import MakerCard from '../MakerCard/MakerCard'; +import MakerCardSkeleton from '../MakerCard/MakerCard.Skeleton'; + +interface Props { + tournamentId: number + searchFilter: string, + roleFilter: number | null +} + +const ITEMS_PER_PAGE = 3; + +export default function MakersList(props: Props) { + + + const [page, setPage] = useState(0); + const topContainerRef = useRef(null) + const [scrollToTop, setScrollToTop] = useState(false) + + const [queryFilter, setQueryFilter] = useState({ + tournamentId: props.tournamentId, + roleId: props.roleFilter ?? null, + search: props.searchFilter ?? null, + skip: ITEMS_PER_PAGE * page, + take: ITEMS_PER_PAGE, + }); + + + + + + const query = useGetMakersInTournamentQuery({ + variables: queryFilter, + }); + + + useEffect(() => { + setPage(0); + setQueryFilter(f => ({ ...f, search: props.searchFilter, roleId: props.roleFilter, skip: 0 })) + }, [props.roleFilter, props.searchFilter]); + + + + useEffect(() => { + if (scrollToTop && topContainerRef.current) { + topContainerRef.current.scrollIntoView({ + behavior: 'smooth', + block: "center" + }) + setScrollToTop(false) + } + }, [scrollToTop]) + + + + const nextPage = () => { + setPage(p => p + 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) + ITEMS_PER_PAGE })) + setScrollToTop(true) + } + const prevPage = () => { + if (page === 0) return + setPage(p => p - 1) + setQueryFilter(f => ({ ...f, skip: (f.skip ?? 0) - ITEMS_PER_PAGE })) + setScrollToTop(true) + } + + + const itemsCount = query.data?.getMakersInTournament && query.data.getMakersInTournament.makers.length; + + return ( +
+
+
+ { + query.loading ? + <> +
+ +
+ + + + : + (itemsCount !== 0 ? + query.data?.getMakersInTournament.makers.map(maker => ) : +
+

No makers found here...

+
) + } + < div className='flex justify-center gap-36 text-gray-400' > + + + + + + +
+
+ + ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx new file mode 100644 index 0000000..1e73b20 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ParticipantsSection/ParticipantsSection.tsx @@ -0,0 +1,41 @@ +import { useDebouncedState } from '@react-hookz/web'; +import { useState } from 'react' +import { GenericMakerRole } from 'src/graphql' +import MakersFilters from '../MakersFilters/MakersFilters'; +import MakersList from './MakersList'; + +interface Props { + tournamentId: number +} +export default function ParticipantsSection({ tournamentId }: Props) { + + const [searchFilter, setSearchFilter] = useState(""); + const [debouncedsearchFilter, setDebouncedSearchFilter] = useDebouncedState("", 500); + const [roleFilter, setRoleFilter] = useState(null); + + + + const changeSearchFilter = (new_value: string) => { + setSearchFilter(new_value); + setDebouncedSearchFilter(new_value); + } + + + + return (<> +
+

Makers 👾

+ +
+ +
+
+ + + ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx new file mode 100644 index 0000000..9fb5ad1 --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.Skeleton.tsx @@ -0,0 +1,40 @@ +import Card from 'src/Components/Card/Card'; +import Badge from 'src/Components/Badge/Badge'; +import Skeleton from 'react-loading-skeleton'; + + +export default function ProjectCardSkeleton() { + + + return ( + +
+
+ +
+
+

+

+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )} +
+
+
+
+ +
+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )} +
+
+ +
+

+
    + {Array(3).fill(0).map((_, idx) =>
  • Loading role
  • )}
+
+
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx new file mode 100644 index 0000000..31da7cf --- /dev/null +++ b/src/features/Tournaments/pages/MakersPage/ProjectCard/ProjectCard.tsx @@ -0,0 +1,62 @@ +import Button from "src/Components/Button/Button" +import { GetMakersInTournamentQuery, } from "src/graphql"; +import { useAppDispatch, } from "src/utils/hooks"; +import Card from 'src/Components/Card/Card'; +import Avatar from 'src/features/Profiles/Components/Avatar/Avatar'; +import Badge from 'src/Components/Badge/Badge'; +import { createRoute } from 'src/utils/routing'; + +type MakerType = GetMakersInTournamentQuery['getMakersInTournament']['makers'][number] + +interface Props { + maker: MakerType, + isMe?: boolean; +} + +export default function ProjectCard({ maker, isMe }: Props) { + + return ( + +
+
+ +
+
+

{maker.name}

+ {maker.jobTitle ?

{maker.jobTitle}

+ : +

No job title

} + {maker.roles.length ?
    + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} +
+ : +

No roles added

+ } +
+ {isMe && } +
+
+ +
+

🌈 Roles

+ + {maker.roles.length ?
    + {maker.roles.map(role =>
  • {role.icon} {role.title}
  • )} +
+ : +

No roles added

+ } +
+ +
+

🛠️ Skills

+ {maker.skills.length ?
    + {maker.skills.map(skill =>
  • {skill.title}
  • )} +
+ : +

No skills added

+ } +
+ {isMe && }
+ ) +} diff --git a/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql similarity index 66% rename from src/features/Tournaments/pages/MakersPage/makersInTournament.graphql rename to src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql index 72828fa..b58628c 100644 --- a/src/features/Tournaments/pages/MakersPage/makersInTournament.graphql +++ b/src/features/Tournaments/pages/MakersPage/tournamentMakers.graphql @@ -5,14 +5,6 @@ query GetMakersInTournament( $search: String $roleId: Int ) { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } - getMakersInTournament( tournamentId: $tournamentId take: $take @@ -20,19 +12,33 @@ query GetMakersInTournament( search: $search roleId: $roleId ) { + hasNext + hasPrev + makers { + id + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } + } + } +} + +query MeTournament { + me { id name avatar jobTitle - roles { - id - icon - title - } - skills { - id - title - } + ...UserRolesSkills } } diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index feb5a39..14bc7b7 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -330,7 +330,7 @@ export type Query = { getDonationsStats: DonationsStats; getFeed: Array; getLnurlDetailsForProject: LnurlDetails; - getMakersInTournament: Array; + getMakersInTournament: TournamentMakersResponse; getMyDrafts: Array; getPostById: Post; getProject: Project; @@ -555,6 +555,13 @@ export type TournamentJudge = { name: Scalars['String']; }; +export type TournamentMakersResponse = { + __typename?: 'TournamentMakersResponse'; + hasNext: Maybe; + hasPrev: Maybe; + makers: Array; +}; + export type TournamentPrize = { __typename?: 'TournamentPrize'; amount: Scalars['String']; @@ -809,7 +816,12 @@ export type GetMakersInTournamentQueryVariables = Exact<{ }>; -export type GetMakersInTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null, getMakersInTournament: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> }; +export type GetMakersInTournamentQuery = { __typename?: 'Query', getMakersInTournament: { __typename?: 'TournamentMakersResponse', hasNext: boolean | null, hasPrev: boolean | null, makers: Array<{ __typename?: 'User', id: number, name: string, avatar: string, jobTitle: string | null, roles: Array<{ __typename?: 'MakerRole', id: number, icon: string, title: string }>, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }> }> } }; + +export type MeTournamentQueryVariables = Exact<{ [key: string]: never; }>; + + +export type MeTournamentQuery = { __typename?: 'Query', me: { __typename?: 'MyProfile', id: number, name: string, avatar: string, jobTitle: string | null, skills: Array<{ __typename?: 'MakerSkill', id: number, title: string }>, roles: Array<{ __typename?: 'MakerRole', id: number, title: string, icon: string, level: RoleLevelEnum }> } | null }; export type GetAllRolesQueryVariables = Exact<{ [key: string]: never; }>; @@ -2148,13 +2160,6 @@ export type ProjectDetailsLazyQueryHookResult = ReturnType; export const GetMakersInTournamentDocument = gql` query GetMakersInTournament($tournamentId: Int!, $take: Int, $skip: Int, $search: String, $roleId: Int) { - me { - id - name - avatar - jobTitle - ...UserRolesSkills - } getMakersInTournament( tournamentId: $tournamentId take: $take @@ -2162,22 +2167,26 @@ export const GetMakersInTournamentDocument = gql` search: $search roleId: $roleId ) { - id - name - avatar - jobTitle - roles { + hasNext + hasPrev + makers { id - icon - title - } - skills { - id - title + name + avatar + jobTitle + roles { + id + icon + title + } + skills { + id + title + } } } } - ${UserRolesSkillsFragmentDoc}`; + `; /** * __useGetMakersInTournamentQuery__ @@ -2210,6 +2219,44 @@ export function useGetMakersInTournamentLazyQuery(baseOptions?: Apollo.LazyQuery export type GetMakersInTournamentQueryHookResult = ReturnType; export type GetMakersInTournamentLazyQueryHookResult = ReturnType; export type GetMakersInTournamentQueryResult = Apollo.QueryResult; +export const MeTournamentDocument = gql` + query MeTournament { + me { + id + name + avatar + jobTitle + ...UserRolesSkills + } +} + ${UserRolesSkillsFragmentDoc}`; + +/** + * __useMeTournamentQuery__ + * + * To run a query within a React component, call `useMeTournamentQuery` and pass it any options that fit your needs. + * When your component renders, `useMeTournamentQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useMeTournamentQuery({ + * variables: { + * }, + * }); + */ +export function useMeTournamentQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(MeTournamentDocument, options); + } +export function useMeTournamentLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(MeTournamentDocument, options); + } +export type MeTournamentQueryHookResult = ReturnType; +export type MeTournamentLazyQueryHookResult = ReturnType; +export type MeTournamentQueryResult = Apollo.QueryResult; export const GetAllRolesDocument = gql` query GetAllRoles { getAllMakersRoles { diff --git a/src/mocks/handlers.ts b/src/mocks/handlers.ts index 06630e1..20e57c4 100644 --- a/src/mocks/handlers.ts +++ b/src/mocks/handlers.ts @@ -36,6 +36,7 @@ import { GetAllRolesQuery, GetMakersInTournamentQuery, GetMakersInTournamentQueryVariables, + MeTournamentQuery, } from 'src/graphql' const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000)) @@ -286,12 +287,21 @@ export const handlers = [ ) }), + graphql.query('MeTournament', async (req, res, ctx) => { + await delay() + + return res( + ctx.data({ + me: { ...me() } + }) + ) + }), + graphql.query('GetMakersInTournament', async (req, res, ctx) => { await delay() return res( ctx.data({ - me: { ...me() }, getMakersInTournament: getMakersInTournament(req.variables) }) ) diff --git a/src/mocks/resolvers.ts b/src/mocks/resolvers.ts index b5ffa36..74ffc2d 100644 --- a/src/mocks/resolvers.ts +++ b/src/mocks/resolvers.ts @@ -99,10 +99,13 @@ export function getTournamentById(id: number) { export function getMakersInTournament(vars: GetMakersInTournamentQueryVariables) { - const offsetStart = vars.skip ?? 0; - const offsetEnd = offsetStart + (vars.take ?? 15) + const take = vars.take ?? 15; + const skip = vars.skip ?? 0; - return MOCK_DATA.users.slice(1) + const offsetStart = skip; + const offsetEnd = offsetStart + take; + + const allMakers = MOCK_DATA.users.slice(1) .filter(u => { if (!vars.search) return true; return [u.name, u.jobTitle].some(attr => attr?.search(new RegExp(vars.search!, 'i')) !== -1) @@ -111,5 +114,12 @@ export function getMakersInTournament(vars: GetMakersInTournamentQueryVariables) if (!vars.roleId) return true; return u.roles.some(r => r.id === vars.roleId) }) - .slice(offsetStart, offsetEnd) as User[]; + .slice(offsetStart, offsetEnd + 1) as User[] + ; + + return { + hasNext: allMakers.length === take + 1, + hasPrev: skip !== 0, + makers: allMakers.slice(0, take) + }; } \ No newline at end of file