Add database provider for REST API integration
This commit is contained in:
parent
d3d4b8a767
commit
5c814b8054
1 changed files with 112 additions and 0 deletions
112
src/lib/providers/DatabaseProvider.ts
Normal file
112
src/lib/providers/DatabaseProvider.ts
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
import { RestDataProvider } from 'wx-grid-data-provider'
|
||||||
|
import { API_BASE } from '$lib/api/core'
|
||||||
|
|
||||||
|
interface DatabaseProviderOptions {
|
||||||
|
resource: 'weapons' | 'characters' | 'summons'
|
||||||
|
pageSize?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface APIResponse {
|
||||||
|
data: any[]
|
||||||
|
meta: {
|
||||||
|
page: number
|
||||||
|
totalPages: number
|
||||||
|
pageSize: number
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DatabaseProvider extends RestDataProvider {
|
||||||
|
private resource: string
|
||||||
|
private pageSize: number
|
||||||
|
private currentPage: number = 1
|
||||||
|
private apiUrl: string
|
||||||
|
private totalCount: number = 0
|
||||||
|
private totalPages: number = 1
|
||||||
|
|
||||||
|
constructor(options: DatabaseProviderOptions) {
|
||||||
|
const apiUrl = `${API_BASE}/search/${options.resource}`
|
||||||
|
|
||||||
|
super(apiUrl, (item) => {
|
||||||
|
// Normalize data if needed
|
||||||
|
if (item.name && typeof item.name === 'object') {
|
||||||
|
// Ensure name is accessible for display
|
||||||
|
item.displayName = item.name.en || item.name.ja || '—'
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
|
||||||
|
this.apiUrl = apiUrl
|
||||||
|
this.resource = options.resource
|
||||||
|
this.pageSize = options.pageSize || 20
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override getData to handle our API's pagination format
|
||||||
|
async getData(params?: { page?: number; per_page?: number }): Promise<any[]> {
|
||||||
|
const page = params?.page || this.currentPage
|
||||||
|
const perPage = params?.per_page || this.pageSize
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(this.apiUrl)
|
||||||
|
url.searchParams.set('page', page.toString())
|
||||||
|
|
||||||
|
const response = await fetch(url.toString(), {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'include',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Per-Page': perPage.toString()
|
||||||
|
},
|
||||||
|
body: JSON.stringify({})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`API request failed: ${response.statusText}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json()
|
||||||
|
|
||||||
|
// Store metadata for pagination
|
||||||
|
this.currentPage = page
|
||||||
|
if (result.meta) {
|
||||||
|
this.totalCount = result.meta.count || 0
|
||||||
|
this.totalPages = result.meta.total_pages || 1
|
||||||
|
// Update pageSize if it's different from the response
|
||||||
|
if (result.meta.per_page) {
|
||||||
|
this.pageSize = result.meta.per_page
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply normalizer if defined
|
||||||
|
if (this.normalizer && result.results) {
|
||||||
|
return result.results.map(this.normalizer)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.results || []
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch data:', error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current pagination state
|
||||||
|
getPaginationMeta() {
|
||||||
|
return {
|
||||||
|
page: this.currentPage,
|
||||||
|
pageSize: this.pageSize,
|
||||||
|
total: this.totalCount,
|
||||||
|
totalPages: this.totalPages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle pagination
|
||||||
|
async loadPage(page: number) {
|
||||||
|
return this.getData({ page, per_page: this.pageSize })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle page size changes
|
||||||
|
async setPageSize(size: number) {
|
||||||
|
this.pageSize = size
|
||||||
|
return this.getData({ page: 1, per_page: size })
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue