Skip to content

Commit d7d3ed3

Browse files
add users pagination, sort and search (#533)
1 parent 4fa21c6 commit d7d3ed3

File tree

4 files changed

+105
-5
lines changed

4 files changed

+105
-5
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ApiQuery } from '@nestjs/swagger'
2+
import { applyDecorators } from '@nestjs/common'
3+
4+
export function PersonQueryDecorator() {
5+
return applyDecorators(
6+
ApiQuery({ name: 'pageindex', required: false, type: Number }),
7+
ApiQuery({ name: 'pagesize', required: false, type: Number }),
8+
ApiQuery({ name: 'search', required: false, type: String }),
9+
ApiQuery({ name: 'sortBy', required: false, type: String }),
10+
ApiQuery({ name: 'sortOrder', required: false, type: String }),
11+
)
12+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Expose, Transform } from 'class-transformer'
2+
import { IsOptional } from 'class-validator'
3+
4+
export class PersonQueryDto {
5+
@Expose()
6+
@IsOptional()
7+
@Transform(({ value }) => falsyToUndefined(value))
8+
search?: string
9+
10+
@Expose()
11+
@IsOptional()
12+
@Transform(({ value }) => falsyToUndefined(value))
13+
sortBy?: string
14+
15+
@Expose()
16+
@IsOptional()
17+
@Transform(({ value }) => falsyToUndefined(value))
18+
sortOrder?: string
19+
20+
@Expose()
21+
@IsOptional()
22+
@Transform(({ value }) => toNumber(value))
23+
pageindex?: number
24+
25+
@Expose()
26+
@IsOptional()
27+
@Transform(({ value }) => toNumber(value))
28+
pagesize?: number
29+
}
30+
31+
function toNumber(value: string): number | undefined {
32+
if (!value || Number.isNaN(value)) {
33+
return undefined
34+
}
35+
36+
const newValue: number = Number.parseInt(value)
37+
return newValue
38+
}
39+
40+
function falsyToUndefined(value: unknown): unknown | undefined {
41+
if (!value || value === 'undefined') {
42+
return undefined
43+
}
44+
45+
return value
46+
}

apps/api/src/person/person.controller.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'
1+
import { Controller, Get, Post, Body, Patch, Param, Delete, Query } from '@nestjs/common'
22
import { RoleMatchingMode, Roles } from 'nest-keycloak-connect'
33
import { RealmViewSupporters, ViewSupporters } from '@podkrepi-bg/podkrepi-types'
44
import { PersonService } from './person.service'
55
import { CreatePersonDto } from './dto/create-person.dto'
66
import { UpdatePersonDto } from './dto/update-person.dto'
77
import { ApiTags } from '@nestjs/swagger'
8+
import { PersonQueryDecorator } from '../common/dto/person-filter-decorator'
9+
import { PersonQueryDto } from '../common/dto/person-query-dto'
810

911
@ApiTags('person')
1012
@Controller('person')
@@ -25,8 +27,15 @@ export class PersonController {
2527
roles: [RealmViewSupporters.role, ViewSupporters.role],
2628
mode: RoleMatchingMode.ANY,
2729
})
28-
async findAll() {
29-
return await this.personService.findAll()
30+
@PersonQueryDecorator()
31+
async findAll(@Query() query?: PersonQueryDto) {
32+
return await this.personService.findAll(
33+
query?.search,
34+
query?.sortBy,
35+
query?.sortOrder,
36+
query?.pageindex,
37+
query?.pagesize,
38+
)
3039
}
3140

3241
@Get(':id')

apps/api/src/person/person.service.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Injectable, Logger } from '@nestjs/common'
22
import { ConfigService } from '@nestjs/config'
33
import client from '@sendgrid/client'
4+
import { Prisma } from '@prisma/client'
45
import { PrismaService } from '../prisma/prisma.service'
56
import { CreatePersonDto } from './dto/create-person.dto'
67
import { UpdatePersonDto } from './dto/update-person.dto'
@@ -30,8 +31,40 @@ export class PersonService {
3031
return person
3132
}
3233

33-
async findAll() {
34-
return await this.prisma.person.findMany()
34+
async findAll(
35+
search?: string,
36+
sortBy?: string,
37+
sortOrder?: string,
38+
pageIndex?: number,
39+
pageSize?: number,
40+
) {
41+
const whereClause: Prisma.PersonWhereInput = {
42+
...(search && {
43+
OR: [
44+
{ firstName: { contains: search, mode: 'insensitive' } },
45+
{ lastName: { contains: search, mode: 'insensitive' } },
46+
{ email: { contains: search, mode: 'insensitive' } },
47+
{ phone: { contains: search } },
48+
],
49+
}),
50+
}
51+
const data = await this.prisma.person.findMany({
52+
skip: pageIndex && pageSize ? pageIndex * pageSize : undefined,
53+
take: pageSize ? pageSize : undefined,
54+
where: whereClause,
55+
orderBy: [sortBy ? { [sortBy]: sortOrder ? sortOrder : 'desc' } : { createdAt: 'desc' }],
56+
})
57+
58+
const count = await this.prisma.person.count({
59+
where: whereClause,
60+
})
61+
62+
const result = {
63+
items: data,
64+
total: count,
65+
}
66+
67+
return result
3568
}
3669

3770
async findOne(id: string) {

0 commit comments

Comments
 (0)