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 all 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 };
}
}
}
35 changes: 33 additions & 2 deletions src/shelter/shelter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,45 @@ 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 {
private voluntaryIds: string[] = [];

private async generatePayloadWithCoordinates(
payload:
| z.infer<typeof CreateShelterSchema>
| z.infer<typeof FullUpdateShelterSchema>,
) {
if ((payload.latitude && payload.longitude) || !payload.address) {

Choose a reason for hiding this comment

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

No cenário do fullUpdate em que o usuário altera o local do abrigo, os valores da latitude e longitude não serão atualizados

return payload;
}

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

const updatedPayload = {
...payload,
};

if (latitude && longitude) {
updatedPayload.latitude = latitude;
updatedPayload.longitude = longitude;
}

return updatedPayload;
}

constructor(private readonly prismaService: PrismaService) {
this.loadVoluntaryIds();
}

async store(body: z.infer<typeof CreateShelterSchema>) {
const payload = CreateShelterSchema.parse(body);
const payload = CreateShelterSchema.parse(
await this.generatePayloadWithCoordinates(body),
);

await this.prismaService.shelter.create({
data: {
Expand All @@ -48,7 +76,10 @@ export class ShelterService {
}

async fullUpdate(id: string, body: z.infer<typeof FullUpdateShelterSchema>) {
const payload = FullUpdateShelterSchema.parse(body);
const payload = FullUpdateShelterSchema.parse(
await this.generatePayloadWithCoordinates(body),
);

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,
};