diff --git a/src/lib/api/adapters/__tests__/search.adapter.test.ts b/src/lib/api/adapters/__tests__/search.adapter.test.ts index 4802f9ec..5bdd3123 100644 --- a/src/lib/api/adapters/__tests__/search.adapter.test.ts +++ b/src/lib/api/adapters/__tests__/search.adapter.test.ts @@ -390,15 +390,7 @@ describe('SearchAdapter', () => { global.fetch = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ - results: [], - page: 2, - total_pages: 5, - meta: { - count: 0, - page: 2, - per_page: 20, - total_pages: 5 - } + results: [] }) }) @@ -420,8 +412,8 @@ describe('SearchAdapter', () => { }) ) - expect(result.page).toBe(2) - expect(result.totalPages).toBe(5) + // Unified search only returns results, no pagination metadata + expect(result.results).toEqual([]) }) }) }) \ No newline at end of file diff --git a/src/lib/api/adapters/search.adapter.ts b/src/lib/api/adapters/search.adapter.ts index 226bc570..4e997d2b 100644 --- a/src/lib/api/adapters/search.adapter.ts +++ b/src/lib/api/adapters/search.adapter.ts @@ -35,8 +35,9 @@ export interface SearchParams { } /** - * Individual search result item - * Represents a weapon, character, or summon + * Individual search result item from type-specific search endpoints + * (searchWeapons, searchCharacters, searchSummons) + * These return full entity data with camelCase field names (transformed by BaseAdapter) */ export interface SearchResult { /** Unique entity ID */ @@ -65,7 +66,40 @@ export interface SearchResult { } /** - * Search API response structure + * Character series reference for unified search + */ +export interface UnifiedSearchSeriesRef { + id: string + slug: string + name: { en: string; ja: string } +} + +/** + * Individual search result item from unified search endpoint (searchAll) + * Uses PgSearch.multisearch which returns different field structure + * Field names are camelCase after BaseAdapter transformation + */ +export interface UnifiedSearchResult { + /** Unique entity ID (from searchable_id) */ + searchableId: string + /** Type of entity */ + searchableType: 'Weapon' | 'Character' | 'Summon' + /** Granblue game ID */ + granblueId: string + /** English name */ + nameEn?: string + /** Japanese name */ + nameJp?: string + /** Element type (1-6 for different elements) */ + element?: number + /** Season (characters only) */ + season?: number | null + /** Series (characters only) */ + series?: UnifiedSearchSeriesRef[] | null +} + +/** + * Search API response structure for type-specific endpoints * Contains results and pagination metadata */ export interface SearchResponse { @@ -86,6 +120,14 @@ export interface SearchResponse { } } +/** + * Search API response structure for unified search endpoint + */ +export interface UnifiedSearchResponse { + /** Array of search results */ + results: UnifiedSearchResult[] +} + /** * Adapter for search-related API operations * Handles entity search with filtering, pagination, and caching @@ -221,11 +263,12 @@ export class SearchAdapter extends BaseAdapter { /** * Searches across all entity types (weapons, characters, summons) + * Uses PgSearch.multisearch which returns a different response structure * * @param params - Search parameters - * @returns Promise resolving to search results + * @returns Promise resolving to unified search results */ - async searchAll(params: SearchParams = {}): Promise { + async searchAll(params: SearchParams = {}): Promise { const body = this.buildSearchBody(params, { element: true, rarity: true, @@ -243,7 +286,7 @@ export class SearchAdapter extends BaseAdapter { // Search endpoints don't use credentials to avoid CORS // Rails expects params nested under 'search' key // Per-page is sent via X-Per-Page header - return this.request('/search/all', { + return this.request('/search', { method: 'POST', body: { search: body }, credentials: 'omit',