diff --git a/src/poll/Poll.dto.ts b/src/poll/Poll.dto.ts index 10c537e..6fc70b7 100644 --- a/src/poll/Poll.dto.ts +++ b/src/poll/Poll.dto.ts @@ -17,6 +17,7 @@ export enum PollSortBy { CREATION_DATE = 'creationDate', END_DATE = 'endDate', PARTICIPANT_COUNT = 'participantCount', + CLOSEST_END_DATE = 'closestEndDate', } export class CreatePollDto { diff --git a/src/poll/poll.service.ts b/src/poll/poll.service.ts index c43830f..0322c92 100644 --- a/src/poll/poll.service.ts +++ b/src/poll/poll.service.ts @@ -250,6 +250,55 @@ export class PollService { return draft } + private async executeQueryPollWithDualSorting( + filters: Prisma.PollWhereInput, + userId: number, + limit: number, + skip: number, + activeFilters: Prisma.PollWhereInput, + secondaryFilters: Prisma.PollWhereInput, + activeOrderBy: Prisma.PollOrderByWithRelationInput, + secondaryOrderBy: Prisma.PollOrderByWithRelationInput, + ) { + const [activePolls, secondaryPolls, total] = + await this.databaseService.$transaction([ + this.databaseService.poll.findMany({ + where: activeFilters, + include: { + author: true, + votes: { + where: { userId }, + select: { voteID: true }, + }, + }, + orderBy: activeOrderBy, + take: Number(limit) + skip, + }), + this.databaseService.poll.findMany({ + where: secondaryFilters, + include: { + author: true, + votes: { + where: { userId }, + select: { voteID: true }, + }, + }, + orderBy: secondaryOrderBy, + take: Number(limit) + skip, + }), + this.databaseService.poll.count({ where: filters }), + ]) + + const combinedPolls = [...activePolls, ...secondaryPolls] + const paginatedPolls = combinedPolls.slice(skip, skip + Number(limit)) + const pollsWithVoteStatus = this.mapPollsWithVoteStatus(paginatedPolls) + + return { + polls: pollsWithVoteStatus, + total, + } + } + async getPolls(query: GetPollsDto, worldID: string) { const { page = 1, @@ -349,105 +398,68 @@ export class PollService { OR: [{ startDate: { gt: now } }, { endDate: { lte: now } }], } - const [activePolls, inactivePolls, total] = - await this.databaseService.$transaction([ - this.databaseService.poll.findMany({ - where: activeFilters, - include: { - author: true, - votes: { - where: { userId }, - select: { voteID: true }, - }, - }, - orderBy: { endDate: sortOrder }, - take: Number(limit) + skip, - }), - this.databaseService.poll.findMany({ - where: inactiveFilters, - include: { - author: true, - votes: { - where: { userId }, - select: { voteID: true }, - }, - }, - orderBy: { endDate: sortOrder }, - take: Number(limit) + skip, - }), - this.databaseService.poll.count({ where: filters }), - ]) - - const combinedPolls = [...activePolls, ...inactivePolls] - - const paginatedPolls = combinedPolls.slice(skip, skip + Number(limit)) - - const pollsWithVoteStatus = this.mapPollsWithVoteStatus(paginatedPolls) + return await this.executeQueryPollWithDualSorting( + filters, + userId, + limit, + skip, + activeFilters, + inactiveFilters, + { endDate: sortOrder }, + { endDate: sortOrder }, + ) + } else if (sortBy === PollSortBy.PARTICIPANT_COUNT) { + // For participantCount: show active polls first (by highest voter count), then ended polls + const activeFilters = { + ...filters, + startDate: { lte: now }, + endDate: { gt: now }, + } - return { - polls: pollsWithVoteStatus, - total, + const endedFilters = { + ...filters, + endDate: { lte: now }, } - } else if (sortBy) { - // creationDate or participantCount - if (sortBy === PollSortBy.PARTICIPANT_COUNT) { - // For participantCount: show active polls first (by highest voter count), then ended polls - const activeFilters = { - ...filters, - startDate: { lte: now }, - endDate: { gt: now }, - } - const endedFilters = { - ...filters, - endDate: { lte: now }, - } + return await this.executeQueryPollWithDualSorting( + filters, + userId, + limit, + skip, + activeFilters, + endedFilters, + { participantCount: sortOrder }, + { participantCount: sortOrder }, + ) + } else if (sortBy === PollSortBy.CLOSEST_END_DATE) { + // For closestEndDate: show active polls first (closest to ending), then ended polls + const activeFilters = { + ...filters, + startDate: { lte: now }, + endDate: { gt: now }, + } - const [activePolls, endedPolls, total] = - await this.databaseService.$transaction([ - this.databaseService.poll.findMany({ - where: activeFilters, - include: { - author: true, - votes: { - where: { userId }, - select: { voteID: true }, - }, - }, - orderBy: { participantCount: sortOrder }, // Highest voter count first for active polls - take: Number(limit) + skip, - }), - this.databaseService.poll.findMany({ - where: endedFilters, - include: { - author: true, - votes: { - where: { userId }, - select: { voteID: true }, - }, - }, - orderBy: { participantCount: sortOrder }, // Highest voter count first for ended polls too - take: Number(limit) + skip, - }), - this.databaseService.poll.count({ where: filters }), - ]) - - const combinedPolls = [...activePolls, ...endedPolls] - const paginatedPolls = combinedPolls.slice(skip, skip + Number(limit)) - - const pollsWithVoteStatus = this.mapPollsWithVoteStatus(paginatedPolls) - - return { - polls: pollsWithVoteStatus, - total, - } - } else { - // creationDate - orderBy.push({ - [sortBy]: sortOrder, - }) + const endedFilters = { + ...filters, + endDate: { lte: now }, } + return await this.executeQueryPollWithDualSorting( + filters, + userId, + limit, + skip, + activeFilters, + endedFilters, + { endDate: 'asc' }, // Closest to ending first for active polls + { endDate: 'desc' }, // Most recently ended first for ended polls + ) + } else if (sortBy) { + // creationDate or other sort types + orderBy.push({ + [sortBy]: sortOrder, + }) + const [polls, total] = await this.databaseService.$transaction([ this.databaseService.poll.findMany({ where: filters,