Skip to content

Commit b9551b0

Browse files
committed
Add agencies API integration
1 parent 4577759 commit b9551b0

File tree

3 files changed

+81
-3
lines changed

3 files changed

+81
-3
lines changed

frontend/providers/SearchProvider.tsx

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { createContext, useCallback, useContext, useMemo, useState } from "react"
33
import { apiFetch } from "@/utils/apiFetch"
44
import { useAuth } from "@/providers/AuthProvider"
5-
import { SearchRequest, SearchResponse, PaginatedSearchResponses } from "@/utils/api"
5+
import { SearchRequest, SearchResponse, PaginatedSearchResponses, AgenciesRequest, AgenciesApiResponse } from "@/utils/api"
66
import API_ROUTES, { apiBaseUrl } from "@/utils/apiRoutes"
77
import { ApiError } from "@/utils/apiError"
88
import { useRouter, useSearchParams } from "next/navigation"
@@ -11,6 +11,9 @@ interface SearchContext {
1111
searchAll: (
1212
query: Omit<SearchRequest, "access_token" | "accessToken">
1313
) => Promise<PaginatedSearchResponses>
14+
searchAgencies: (
15+
params: Omit<AgenciesRequest, "access_token" | "accessToken">
16+
) => Promise<AgenciesApiResponse>
1417
searchResults?: PaginatedSearchResponses
1518
loading: boolean
1619
}
@@ -94,5 +97,50 @@ function useHook(): SearchContext {
9497
[accessToken, refreshAccessToken, router]
9598
)
9699

97-
return useMemo(() => ({ searchAll, searchResults, loading }), [searchResults, searchAll, loading])
100+
const searchAgencies = useCallback(
101+
async (params: Omit<AgenciesRequest, "access_token" | "accessToken">) => {
102+
if (!accessToken) throw new ApiError("No access token", "NO_ACCESS_TOKEN", 401)
103+
setLoading(true)
104+
105+
try {
106+
const queryParams = new URLSearchParams()
107+
Object.entries(params).forEach(([key, value]) => {
108+
if (value !== undefined) {
109+
queryParams.set(key, String(value))
110+
}
111+
})
112+
113+
const apiUrl = `${apiBaseUrl}${API_ROUTES.agencies}?${queryParams.toString()}`
114+
115+
const response = await apiFetch(apiBaseUrl, {
116+
method: "GET",
117+
headers: {
118+
"Content-Type": "application/json"
119+
}
120+
})
121+
122+
if (!response.ok) {
123+
throw new Error("Failed to search agencies")
124+
}
125+
126+
const data: AgenciesApiResponse = await response.json()
127+
return data
128+
} catch (error) {
129+
console.error("Error searching agencies:", error)
130+
return {
131+
error: String(error),
132+
results: [],
133+
page: 0,
134+
per_page: 0,
135+
pages: 0,
136+
total: 0
137+
}
138+
} finally {
139+
setLoading(false)
140+
}
141+
},
142+
[accessToken]
143+
)
144+
145+
return useMemo(() => ({ searchAll, searchResults, loading }), [searchResults, searchAll, searchResults, loading])
98146
}

frontend/utils/api.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,32 @@ export type PaginatedSearchResponses = {
5959
total: number
6060
results: SearchResponse[]
6161
}
62+
63+
export interface AgenciesRequest extends AuthenticatedRequest {
64+
name?: string
65+
city?: string
66+
state?: string
67+
zip_code?: string
68+
jurisdiction?: string
69+
page?: number
70+
per_page?: number
71+
}
72+
73+
export interface AgencyResponse {
74+
uid: string
75+
title: string
76+
subtitle: string
77+
content_type: string
78+
source: string
79+
last_updated: string
80+
// Could add other agency-specific fields here, as needed
81+
}
82+
83+
export type AgenciesApiResponse = {
84+
results: AgencyResponse[]
85+
page: number
86+
per_page: number
87+
pages: number
88+
total: number
89+
error?: string
90+
}

frontend/utils/apiRoutes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ const API_ROUTES = {
88
search: {
99
all: "/search/",
1010
incidents: "/incidents/search"
11-
}
11+
},
12+
agencies: "/api/v1/agencies"
1213
}
1314

1415
export const apiBaseUrl: string =

0 commit comments

Comments
 (0)