chrysopedia/frontend/src/api/search.ts
jlightner 39e169b4ce feat: Split 945-line public-client.ts into 10 domain API modules with s…
- "frontend/src/api/client.ts"
- "frontend/src/api/index.ts"
- "frontend/src/api/search.ts"
- "frontend/src/api/techniques.ts"
- "frontend/src/api/creators.ts"
- "frontend/src/api/topics.ts"
- "frontend/src/api/stats.ts"
- "frontend/src/api/reports.ts"

GSD-Task: S05/T01
2026-04-03 23:04:56 +00:00

69 lines
1.9 KiB
TypeScript

import { request, BASE } from "./client";
// ── Types ────────────────────────────────────────────────────────────────────
export interface SearchResultItem {
title: string;
slug: string;
type: string;
score: number;
summary: string;
creator_name: string;
creator_slug: string;
topic_category: string;
topic_tags: string[];
technique_page_slug?: string;
match_context?: string;
section_anchor?: string;
section_heading?: string;
}
export interface SearchResponse {
items: SearchResultItem[];
partial_matches: SearchResultItem[];
total: number;
query: string;
fallback_used: boolean;
}
export interface SuggestionItem {
text: string;
type: "topic" | "technique" | "creator";
}
export interface SuggestionsResponse {
suggestions: SuggestionItem[];
}
export interface PopularSearchItem {
query: string;
count: number;
}
export interface PopularSearchesResponse {
items: PopularSearchItem[];
cached: boolean;
}
// ── Functions ────────────────────────────────────────────────────────────────
export async function fetchSuggestions(): Promise<SuggestionsResponse> {
return request<SuggestionsResponse>(`${BASE}/search/suggestions`);
}
export async function searchApi(
q: string,
scope?: string,
limit?: number,
sort?: string,
): Promise<SearchResponse> {
const qs = new URLSearchParams({ q });
if (scope) qs.set("scope", scope);
if (limit !== undefined) qs.set("limit", String(limit));
if (sort) qs.set("sort", sort);
return request<SearchResponse>(`${BASE}/search?${qs.toString()}`);
}
export async function fetchPopularSearches(): Promise<PopularSearchesResponse> {
return request<PopularSearchesResponse>(`${BASE}/search/popular`);
}