Skip to content

Commit 0501b61

Browse files
committed
fix: parse tag response in shelter index
1 parent 38c41ac commit 0501b61

File tree

4 files changed

+140
-48
lines changed

4 files changed

+140
-48
lines changed

src/shelter/ShelterSearch.ts

Lines changed: 97 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,39 @@
11
import { Prisma } from '@prisma/client';
22

3-
import { IFilterFormProps } from './types';
43
import { PrismaService } from '../prisma/prisma.service';
4+
import { SupplyPriority } from 'src/supply/types';
5+
import {
6+
IFilterFormProps,
7+
SearchShelterTagResponse,
8+
ShelterTagInfo,
9+
ShelterTagType,
10+
} from './types/search.types';
11+
12+
const defaultTagsData: ShelterTagInfo = {
13+
NeedDonations: 10,
14+
NeedVolunteers: 10,
15+
RemainingSupplies: 10,
16+
};
517

618
class ShelterSearch {
7-
private data: IFilterFormProps;
19+
private formProps: Partial<IFilterFormProps>;
820
private prismaService: PrismaService;
921

10-
constructor(prismaService: PrismaService, props: IFilterFormProps) {
11-
this.data = props;
22+
constructor(
23+
prismaService: PrismaService,
24+
props: Partial<IFilterFormProps> = {},
25+
) {
1226
this.prismaService = prismaService;
27+
this.formProps = { ...props };
1328
}
1429

1530
get priority(): Prisma.ShelterWhereInput[] {
16-
if (this.data.priority) {
31+
if (this.formProps.priority) {
1732
return [
1833
{
1934
shelterSupplies: {
2035
some: {
21-
priority: +this.data.priority,
36+
priority: +this.formProps.priority,
2237
},
2338
},
2439
},
@@ -28,9 +43,9 @@ class ShelterSearch {
2843
}
2944

3045
get shelterStatus(): Prisma.ShelterWhereInput[] {
31-
if (!this.data.shelterStatus) return [];
46+
if (!this.formProps.shelterStatus) return [];
3247
else {
33-
return this.data.shelterStatus.map((status) => {
48+
return this.formProps.shelterStatus.map((status) => {
3449
if (status === 'waiting')
3550
return {
3651
capacity: null,
@@ -52,13 +67,13 @@ class ShelterSearch {
5267
}
5368

5469
get supplyCategoryIds(): Prisma.ShelterWhereInput {
55-
if (!this.data.supplyCategoryIds) return {};
70+
if (!this.formProps.supplyCategoryIds) return {};
5671
return {
5772
shelterSupplies: {
5873
some: {
5974
supply: {
6075
supplyCategoryId: {
61-
in: this.data.supplyCategoryIds,
76+
in: this.formProps.supplyCategoryIds,
6277
},
6378
},
6479
},
@@ -67,13 +82,13 @@ class ShelterSearch {
6782
}
6883

6984
get supplyIds(): Prisma.ShelterWhereInput {
70-
if (!this.data.supplyIds) return {};
85+
if (!this.formProps.supplyIds) return {};
7186
return {
7287
shelterSupplies: {
7388
some: {
7489
supply: {
7590
id: {
76-
in: this.data.supplyIds,
91+
in: this.formProps.supplyIds,
7792
},
7893
},
7994
},
@@ -82,26 +97,26 @@ class ShelterSearch {
8297
}
8398

8499
get search(): Prisma.ShelterWhereInput[] {
85-
if (!this.data.search) return [];
100+
if (!this.formProps.search) return [];
86101
else
87102
return [
88103
{
89104
address: {
90-
contains: this.data.search,
105+
contains: this.formProps.search,
91106
mode: 'insensitive',
92107
},
93108
},
94109
{
95110
name: {
96-
contains: this.data.search,
111+
contains: this.formProps.search,
97112
mode: 'insensitive',
98113
},
99114
},
100115
];
101116
}
102117

103118
get query(): Prisma.ShelterWhereInput {
104-
if (Object.keys(this.data).length === 0) return {};
119+
if (Object.keys(this.formProps).length === 0) return {};
105120
const queryData = {
106121
AND: [
107122
{ OR: this.search },
@@ -116,4 +131,69 @@ class ShelterSearch {
116131
}
117132
}
118133

119-
export { ShelterSearch };
134+
/**
135+
*
136+
* @param formProps Uma interface do tipo ShelterTagInfo | null. Que indica a quantidade máxima de cada categoria deverá ser retornada
137+
* @param results Resultado da query em `this.prismaService.shelter.findMany`
138+
* @param voluntaryIds
139+
* @returns Retorna a lista de resultados, adicionando o campo tags em cada supply para assim categoriza-los corretamente e limitar a quantidade de cada retornada respeitando os parametros em formProps
140+
*/
141+
function parseTagResponse(
142+
tagProps: Partial<Pick<IFilterFormProps, 'tags'>> = {},
143+
results: SearchShelterTagResponse[],
144+
voluntaryIds: string[],
145+
): SearchShelterTagResponse[] {
146+
const tags: ShelterTagInfo = {
147+
...defaultTagsData,
148+
...(tagProps?.tags ?? {}),
149+
};
150+
151+
const parsed = results.map((result) => {
152+
const qtd: Required<ShelterTagInfo> = {
153+
NeedDonations: 0,
154+
NeedVolunteers: 0,
155+
RemainingSupplies: 0,
156+
};
157+
return {
158+
...result,
159+
shelterSupplies: result.shelterSupplies.reduce((prev, shelterSupply) => {
160+
const supplyTags: ShelterTagType[] = [];
161+
let tagged: boolean = false;
162+
if (
163+
tags.NeedDonations &&
164+
[SupplyPriority.Needing, SupplyPriority.Urgent].includes(
165+
shelterSupply.priority,
166+
)
167+
) {
168+
if (qtd.NeedDonations < tags.NeedDonations) {
169+
tagged = true;
170+
supplyTags.push('NeedDonations');
171+
}
172+
}
173+
if (
174+
tags.NeedVolunteers &&
175+
voluntaryIds.includes(shelterSupply.supply.supplyCategoryId)
176+
) {
177+
if (qtd.NeedVolunteers < tags.NeedVolunteers) {
178+
tagged = true;
179+
supplyTags.push('NeedVolunteers');
180+
}
181+
}
182+
if (
183+
tags.RemainingSupplies &&
184+
[SupplyPriority.Remaining].includes(shelterSupply.priority)
185+
) {
186+
if (qtd.RemainingSupplies < tags.RemainingSupplies) {
187+
tagged = true;
188+
supplyTags.push('RemainingSupplies');
189+
}
190+
}
191+
if (tagged) return [...prev, { ...shelterSupply, tags: supplyTags }];
192+
else return prev;
193+
}, [] as any),
194+
};
195+
});
196+
return parsed;
197+
}
198+
199+
export { ShelterSearch, parseTagResponse };

src/shelter/shelter.service.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import { z } from 'zod';
22
import { Injectable } from '@nestjs/common';
33
import * as qs from 'qs';
4+
import { Prisma } from '@prisma/client';
5+
import { DefaultArgs } from '@prisma/client/runtime/library';
46

57
import { PrismaService } from '../prisma/prisma.service';
68
import {
79
CreateShelterSchema,
810
FullUpdateShelterSchema,
9-
IFilterFormProps,
1011
UpdateShelterSchema,
11-
} from './types';
12+
} from './types/types';
1213
import { SearchSchema } from '../types';
13-
import { ShelterSearch } from './ShelterSearch';
14-
import { Prisma } from '@prisma/client';
15-
import { DefaultArgs } from '@prisma/client/runtime/library';
16-
import { SupplyPriority } from 'src/supply/types';
14+
import { ShelterSearch, parseTagResponse } from './ShelterSearch';
15+
import { SupplyPriority } from '../supply/types';
16+
import { IFilterFormProps } from './types/search.types';
1717

1818
@Injectable()
1919
export class ShelterService {
@@ -120,7 +120,6 @@ export class ShelterService {
120120
} = SearchSchema.parse(query);
121121
const queryData = qs.parse(searchQuery) as unknown as IFilterFormProps;
122122
const { query: where } = new ShelterSearch(this.prismaService, queryData);
123-
124123
const count = await this.prismaService.shelter.count({ where });
125124

126125
const take = perPage;
@@ -156,26 +155,24 @@ export class ShelterService {
156155
notIn: [SupplyPriority.UnderControl],
157156
},
158157
},
159-
take: 10,
160158
orderBy: {
161159
updatedAt: 'desc',
162160
},
163-
select: {
164-
supply: {
165-
select: {
166-
id: true,
167-
name: true,
168-
},
169-
},
170-
priority: true,
171-
createdAt: true,
172-
updatedAt: true,
161+
include: {
162+
supply: true,
173163
},
174164
},
175165
},
176166
});
177167

178-
return { page, perPage, count, results };
168+
const parsed = parseTagResponse(queryData, results, this.voluntaryIds);
169+
170+
return {
171+
page,
172+
perPage,
173+
count,
174+
results: parsed,
175+
};
179176
}
180177

181178
loadVoluntaryIds() {

src/shelter/types/search.types.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Shelter, ShelterSupply, Supply } from '@prisma/client';
2+
import { SupplyPriority } from '../../supply/types';
3+
4+
export type ShelterAvailabilityStatus = 'available' | 'unavailable' | 'waiting';
5+
6+
export interface IFilterFormProps {
7+
search: string;
8+
priority: SupplyPriority | null;
9+
supplyCategoryIds: string[];
10+
supplyIds: string[];
11+
shelterStatus: ShelterAvailabilityStatus[];
12+
tags: ShelterTagInfo | null;
13+
}
14+
15+
export type SearchShelterTagResponse = Shelter & {
16+
shelterSupplies: (ShelterSupply & { supply: Supply })[];
17+
};
18+
19+
export type ShelterTagType =
20+
| 'NeedVolunteers'
21+
| 'NeedDonations'
22+
| 'RemainingSupplies';
23+
24+
export type ShelterTagInfo = {
25+
[key in ShelterTagType]?: number;
26+
};

src/shelter/types.ts renamed to src/shelter/types/types.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import z from 'zod';
22

3-
import { capitalize } from '../utils';
4-
import { SupplyPriority } from '../supply/types';
3+
import { capitalize } from '../../utils';
54

65
export interface DefaultSupplyProps {
76
category: string;
@@ -42,16 +41,6 @@ const FullUpdateShelterSchema = ShelterSchema.omit({
4241
updatedAt: true,
4342
}).partial();
4443

45-
export type ShelterAvailabilityStatus = 'available' | 'unavailable' | 'waiting';
46-
47-
export interface IFilterFormProps {
48-
search: string;
49-
priority: SupplyPriority | null;
50-
supplyCategoryIds: string[];
51-
supplyIds: string[];
52-
shelterStatus: ShelterAvailabilityStatus[];
53-
}
54-
5544
export {
5645
ShelterSchema,
5746
CreateShelterSchema,

0 commit comments

Comments
 (0)