Skip to content

Commit

Permalink
add users pagination, sort and search (#533)
Browse files Browse the repository at this point in the history
  • Loading branch information
tongo-angelov authored Aug 14, 2023
1 parent 4fa21c6 commit d7d3ed3
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 5 deletions.
12 changes: 12 additions & 0 deletions apps/api/src/common/dto/person-filter-decorator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApiQuery } from '@nestjs/swagger'
import { applyDecorators } from '@nestjs/common'

export function PersonQueryDecorator() {
return applyDecorators(
ApiQuery({ name: 'pageindex', required: false, type: Number }),
ApiQuery({ name: 'pagesize', required: false, type: Number }),
ApiQuery({ name: 'search', required: false, type: String }),
ApiQuery({ name: 'sortBy', required: false, type: String }),
ApiQuery({ name: 'sortOrder', required: false, type: String }),
)
}
46 changes: 46 additions & 0 deletions apps/api/src/common/dto/person-query-dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Expose, Transform } from 'class-transformer'
import { IsOptional } from 'class-validator'

export class PersonQueryDto {
@Expose()
@IsOptional()
@Transform(({ value }) => falsyToUndefined(value))
search?: string

@Expose()
@IsOptional()
@Transform(({ value }) => falsyToUndefined(value))
sortBy?: string

@Expose()
@IsOptional()
@Transform(({ value }) => falsyToUndefined(value))
sortOrder?: string

@Expose()
@IsOptional()
@Transform(({ value }) => toNumber(value))
pageindex?: number

@Expose()
@IsOptional()
@Transform(({ value }) => toNumber(value))
pagesize?: number
}

function toNumber(value: string): number | undefined {
if (!value || Number.isNaN(value)) {
return undefined
}

const newValue: number = Number.parseInt(value)
return newValue
}

function falsyToUndefined(value: unknown): unknown | undefined {
if (!value || value === 'undefined') {
return undefined
}

return value
}
15 changes: 12 additions & 3 deletions apps/api/src/person/person.controller.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common'
import { RoleMatchingMode, Roles } from 'nest-keycloak-connect'
import { RealmViewSupporters, ViewSupporters } from '@podkrepi-bg/podkrepi-types'
import { PersonService } from './person.service'
import { CreatePersonDto } from './dto/create-person.dto'
import { UpdatePersonDto } from './dto/update-person.dto'
import { ApiTags } from '@nestjs/swagger'
import { PersonQueryDecorator } from '../common/dto/person-filter-decorator'
import { PersonQueryDto } from '../common/dto/person-query-dto'

@ApiTags('person')
@Controller('person')
Expand All @@ -25,8 +27,15 @@ export class PersonController {
roles: [RealmViewSupporters.role, ViewSupporters.role],
mode: RoleMatchingMode.ANY,
})
async findAll() {
return await this.personService.findAll()
@PersonQueryDecorator()
async findAll(@Query() query?: PersonQueryDto) {
return await this.personService.findAll(
query?.search,
query?.sortBy,
query?.sortOrder,
query?.pageindex,
query?.pagesize,
)
}

@Get(':id')
Expand Down
37 changes: 35 additions & 2 deletions apps/api/src/person/person.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Injectable, Logger } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import client from '@sendgrid/client'
import { Prisma } from '@prisma/client'
import { PrismaService } from '../prisma/prisma.service'
import { CreatePersonDto } from './dto/create-person.dto'
import { UpdatePersonDto } from './dto/update-person.dto'
Expand Down Expand Up @@ -30,8 +31,40 @@ export class PersonService {
return person
}

async findAll() {
return await this.prisma.person.findMany()
async findAll(
search?: string,
sortBy?: string,
sortOrder?: string,
pageIndex?: number,
pageSize?: number,
) {
const whereClause: Prisma.PersonWhereInput = {
...(search && {
OR: [
{ firstName: { contains: search, mode: 'insensitive' } },
{ lastName: { contains: search, mode: 'insensitive' } },
{ email: { contains: search, mode: 'insensitive' } },
{ phone: { contains: search } },
],
}),
}
const data = await this.prisma.person.findMany({
skip: pageIndex && pageSize ? pageIndex * pageSize : undefined,
take: pageSize ? pageSize : undefined,
where: whereClause,
orderBy: [sortBy ? { [sortBy]: sortOrder ? sortOrder : 'desc' } : { createdAt: 'desc' }],
})

const count = await this.prisma.person.count({
where: whereClause,
})

const result = {
items: data,
total: count,
}

return result
}

async findOne(id: string) {
Expand Down

0 comments on commit d7d3ed3

Please sign in to comment.