Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: buscar coordenadas do abrigo #87

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ DATABASE_URL="postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_
SECRET_KEY=

HOST=::0.0.0.0
PORT=4000
PORT=4000

MAPS_API_KEY=
MAPS_API_URL=https://maps.googleapis.com/maps/api
31 changes: 31 additions & 0 deletions src/googleMaps/mapsApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export class MapsApi {
static key: string = process.env.MAPS_API_KEY || '';
static url: string =
process.env.MAPS_API_URL || 'https://maps.googleapis.com/maps/api';

static async getCoordinates(
address: string,
): Promise<{ lat: number | null; lng: number | null }> {
try {
const response = await fetch(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

o NestJS possui um modulo http para fazer esse tipo de request

`${MapsApi.url}/geocode/json?address=${encodeURI(address)}&key=${MapsApi.key}`,
);
if (!response.ok) {
throw new Error(
`[MAPS API] Failed to fetch coordinates. Status: ${response.status}`,
);
}

const data = await response.json();
const location = data?.results?.[0]?.geometry?.location;
if (!location || !location.lat || !location.lng) {
throw new Error('Invalid response from maps API');
}

return location;
} catch (error: any) {
console.error(`[MAPS API] Error fetching coordinates: ${error.message}`);
return { lat: null, lng: null };
}
}
}
19 changes: 19 additions & 0 deletions src/shelter/shelter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { SearchSchema } from '../types';
import { ShelterSearch, parseTagResponse } from './ShelterSearch';
import { SupplyPriority } from '../supply/types';
import { IFilterFormProps } from './types/search.types';
import { fetchShelterCoordinates } from '../utils';

@Injectable()
export class ShelterService {
Expand All @@ -26,6 +27,14 @@ export class ShelterService {
async store(body: z.infer<typeof CreateShelterSchema>) {
const payload = CreateShelterSchema.parse(body);

const { latitude, longitude } = await fetchShelterCoordinates(
payload.address,
);
if (latitude && longitude) {
payload.latitude = latitude;
payload.longitude = longitude;
}

await this.prismaService.shelter.create({
data: {
...payload,
Expand All @@ -49,6 +58,16 @@ export class ShelterService {

async fullUpdate(id: string, body: z.infer<typeof FullUpdateShelterSchema>) {
const payload = FullUpdateShelterSchema.parse(body);
if (payload.address) {
Copy link

@thaua thaua May 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Que tal passar para um método privado essa lógica, que se repete aqui e no método store? Assim evita duplicidade e isola o preenchimento de coordenadas... esse método pode ser chamado apenas na hora de concatenar o payload na resposta, algo do tipo:

...generatePayloadWithCoordinates(payload),

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Show, obrigado.
É realmente uma boa ideia. Vou alterar.

const { latitude, longitude } = await fetchShelterCoordinates(
payload.address,
);
if (latitude && longitude) {
payload.latitude = latitude;
payload.longitude = longitude;
}
}

await this.prismaService.shelter.update({
where: {
id,
Expand Down
17 changes: 17 additions & 0 deletions src/shelter/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,26 @@ const FullUpdateShelterSchema = ShelterSchema.omit({
updatedAt: true,
}).partial();

interface ShelterData {
id: string;
name: string;
pix: string | null;
address: string;
petFriendly: boolean | null;
shelteredPeople: number | null;
latitude: number | null;
longitude: number | null;
Comment on lines +51 to +52
Copy link

@fabriziomello fabriziomello May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Desculpem a intromissão, não entendo nada de TS, mas notei que estão usando aqui dois atributos para representar um ponto e o mesmo está refletido também na tabela do banco de dados.

No Postgres temos um tipo de dado nativo dele chamado Point que se combinado, por exemplo, com a extensão nativa earthdistance é possível realizar queries para buscar registros mais próximos ou distantes de determinado ponto.

capacity: number | null;
contact: string | null;
verified: boolean;
createdAt: string;
updatedAt: string | null;
}

export {
ShelterSchema,
CreateShelterSchema,
UpdateShelterSchema,
FullUpdateShelterSchema,
ShelterData,
};
2 changes: 2 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getSessionData,
deepMerge,
capitalize,
fetchShelterCoordinates,
} from './utils';

export {
Expand All @@ -12,4 +13,5 @@ export {
removeNotNumbers,
getSessionData,
deepMerge,
fetchShelterCoordinates,
};
11 changes: 11 additions & 0 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Logger } from '@nestjs/common';
import { MapsApi } from '../googleMaps/mapsApi';

class ServerResponse<T> {
readonly message: string;
Expand Down Expand Up @@ -74,11 +75,21 @@ function deepMerge(target: Record<string, any>, source: Record<string, any>) {
return source;
}
}
async function fetchShelterCoordinates(address: string) {
try {
const { lat, lng } = await MapsApi.getCoordinates(address);
return { latitude: lat, longitude: lng };
} catch (error) {
console.error(`Failed to fetch coordinates for shelter: ${error}`);
return { latitude: null, longitude: null };
}
}

export {
ServerResponse,
removeNotNumbers,
getSessionData,
deepMerge,
capitalize,
fetchShelterCoordinates,
};