weapons: add frontend adapter methods and interfaces
Add weapon creation infrastructure to entity adapter: - WeaponValidationResult interface for validation response - CreateWeaponPayload interface for weapon creation - WeaponDownloadStatus interface for download status - validateWeaponGranblueId() method - createWeapon() method - downloadWeaponImages() method - getWeaponDownloadStatus() method Also add getWeaponSeriesOptions() utility function. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1fa6429749
commit
901fd5a157
2 changed files with 177 additions and 0 deletions
|
|
@ -327,6 +327,79 @@ export interface SummonDownloadStatus {
|
|||
updatedAt?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Response from weapon granblue_id validation
|
||||
*/
|
||||
export interface WeaponValidationResult {
|
||||
valid: boolean
|
||||
granblueId: string
|
||||
existsInDb: boolean
|
||||
error?: string
|
||||
imageUrls?: {
|
||||
main?: string
|
||||
grid?: string
|
||||
square?: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for creating a new weapon
|
||||
* Note: Frontend uses "transcendence" but API expects "xlb" for stats
|
||||
*/
|
||||
export interface CreateWeaponPayload {
|
||||
granblue_id: string
|
||||
name_en: string
|
||||
name_jp?: string
|
||||
rarity?: number
|
||||
element?: number
|
||||
proficiency?: number
|
||||
series?: number
|
||||
new_series?: number
|
||||
min_hp?: number
|
||||
max_hp?: number
|
||||
max_hp_flb?: number
|
||||
max_hp_ulb?: number
|
||||
min_atk?: number
|
||||
max_atk?: number
|
||||
max_atk_flb?: number
|
||||
max_atk_ulb?: number
|
||||
max_level?: number
|
||||
max_skill_level?: number
|
||||
max_awakening_level?: number
|
||||
flb?: boolean
|
||||
ulb?: boolean
|
||||
transcendence?: boolean
|
||||
extra?: boolean
|
||||
limit?: boolean
|
||||
ax?: boolean
|
||||
release_date?: string | null
|
||||
flb_date?: string | null
|
||||
ulb_date?: string | null
|
||||
transcendence_date?: string | null
|
||||
wiki_en?: string
|
||||
wiki_ja?: string
|
||||
gamewith?: string
|
||||
kamigame?: string
|
||||
recruits?: string | null // Character ID reference
|
||||
nicknames_en?: string[]
|
||||
nicknames_jp?: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Response from weapon image download status
|
||||
*/
|
||||
export interface WeaponDownloadStatus {
|
||||
status: 'queued' | 'processing' | 'completed' | 'failed' | 'not_found'
|
||||
progress?: number
|
||||
imagesDownloaded?: number
|
||||
imagesTotal?: number
|
||||
error?: string
|
||||
weaponId?: string
|
||||
granblueId?: string
|
||||
images?: Record<string, string[]>
|
||||
updatedAt?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity adapter for accessing canonical game data
|
||||
*/
|
||||
|
|
@ -607,6 +680,95 @@ export class EntityAdapter extends BaseAdapter {
|
|||
updatedAt: response.updated_at
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Weapon Creation & Image Download Methods
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Validates a weapon granblue_id by checking if images exist on GBF servers
|
||||
* Requires editor role (>= 7)
|
||||
*/
|
||||
async validateWeaponGranblueId(granblueId: string): Promise<WeaponValidationResult> {
|
||||
const response = await this.request<{
|
||||
valid: boolean
|
||||
granblue_id: string
|
||||
exists_in_db: boolean
|
||||
error?: string
|
||||
image_urls?: {
|
||||
main?: string
|
||||
grid?: string
|
||||
square?: string
|
||||
}
|
||||
}>(`/weapons/validate/${granblueId}`, {
|
||||
method: 'GET'
|
||||
})
|
||||
|
||||
return {
|
||||
valid: response.valid,
|
||||
granblueId: response.granblue_id,
|
||||
existsInDb: response.exists_in_db,
|
||||
error: response.error,
|
||||
imageUrls: response.image_urls
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new weapon record
|
||||
* Requires editor role (>= 7)
|
||||
*/
|
||||
async createWeapon(payload: CreateWeaponPayload): Promise<Weapon> {
|
||||
return this.request<Weapon>('/weapons', {
|
||||
method: 'POST',
|
||||
body: { weapon: payload }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers async image download for a weapon
|
||||
* Requires editor role (>= 7)
|
||||
*/
|
||||
async downloadWeaponImages(
|
||||
weaponId: string,
|
||||
options?: { force?: boolean; size?: 'all' | string }
|
||||
): Promise<{ status: string; weaponId: string; message: string }> {
|
||||
return this.request(`/weapons/${weaponId}/download_images`, {
|
||||
method: 'POST',
|
||||
body: { options }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of an ongoing weapon image download
|
||||
* Requires editor role (>= 7)
|
||||
*/
|
||||
async getWeaponDownloadStatus(weaponId: string): Promise<WeaponDownloadStatus> {
|
||||
const response = await this.request<{
|
||||
status: string
|
||||
progress?: number
|
||||
images_downloaded?: number
|
||||
images_total?: number
|
||||
error?: string
|
||||
weapon_id?: string
|
||||
granblue_id?: string
|
||||
images?: Record<string, string[]>
|
||||
updated_at?: string
|
||||
}>(`/weapons/${weaponId}/download_status`, {
|
||||
method: 'GET'
|
||||
})
|
||||
|
||||
return {
|
||||
status: response.status as WeaponDownloadStatus['status'],
|
||||
progress: response.progress,
|
||||
imagesDownloaded: response.images_downloaded,
|
||||
imagesTotal: response.images_total,
|
||||
error: response.error,
|
||||
weaponId: response.weapon_id,
|
||||
granblueId: response.granblue_id,
|
||||
images: response.images,
|
||||
updatedAt: response.updated_at
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -74,3 +74,18 @@ export function getWeaponSeriesSlug(id: number): string | undefined {
|
|||
export function isOpusDraconicSeries(seriesId: number): boolean {
|
||||
return OPUS_DRACONIC_SERIES.includes(seriesId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all weapon series as options for a select/dropdown.
|
||||
*
|
||||
* @returns Array of { value, label } options
|
||||
*/
|
||||
export function getWeaponSeriesOptions() {
|
||||
return weaponSeries.map((series) => ({
|
||||
value: series.id,
|
||||
label: series.slug
|
||||
.split('_')
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||
.join(' ')
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue