Skip to content

Commit 0630d42

Browse files
committed
Add agencies API integration
1 parent cf425a0 commit 0630d42

3 files changed

Lines changed: 79 additions & 2 deletions

File tree

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: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,31 @@ export type UpdateUserProfilePayload = {
125125
}
126126
primary_email?: string
127127
}
128+
export interface AgenciesRequest extends AuthenticatedRequest {
129+
name?: string
130+
city?: string
131+
state?: string
132+
zip_code?: string
133+
jurisdiction?: string
134+
page?: number
135+
per_page?: number
136+
}
137+
138+
export interface AgencyResponse {
139+
uid: string
140+
title: string
141+
subtitle: string
142+
content_type: string
143+
source: string
144+
last_updated: string
145+
// Could add other agency-specific fields here as needed
146+
}
147+
148+
export type AgenciesApiResponse = {
149+
results: AgencyResponse[]
150+
page: number
151+
per_page: number
152+
pages: number
153+
total: number
154+
error?: string
155+
}

frontend/utils/apiRoutes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const API_ROUTES = {
1313
users: {
1414
self: "/users/self"
1515
}
16+
agencies: "/api/v1/agencies"
1617
}
1718

1819
export const apiBaseUrl: string =

0 commit comments

Comments
 (0)