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
|
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
|
* Entity adapter for accessing canonical game data
|
||||||
*/
|
*/
|
||||||
|
|
@ -607,6 +680,95 @@ export class EntityAdapter extends BaseAdapter {
|
||||||
updatedAt: response.updated_at
|
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 {
|
export function isOpusDraconicSeries(seriesId: number): boolean {
|
||||||
return OPUS_DRACONIC_SERIES.includes(seriesId)
|
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