add job accessory types and adapter methods
- add accessoryType field to JobAccessory entity - add accessory CRUD methods to job adapter - add accessory query options - add jobAccessoryUtils with type helpers
This commit is contained in:
parent
4401191738
commit
29211709ef
6 changed files with 232 additions and 26 deletions
|
|
@ -42,6 +42,19 @@ export interface JobSkillPayload {
|
|||
action_id?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for creating/updating a job accessory
|
||||
*/
|
||||
export interface JobAccessoryPayload {
|
||||
name_en: string
|
||||
name_jp?: string
|
||||
granblue_id: string
|
||||
rarity?: number
|
||||
release_date?: string
|
||||
accessory_type: number // 1 = Shield, 2 = Manatura
|
||||
job_id?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for updating a job entity
|
||||
*/
|
||||
|
|
@ -123,15 +136,25 @@ export class JobAdapter extends BaseAdapter {
|
|||
* Gets all accessories available for a specific job
|
||||
* Only returns data if the job supports accessories
|
||||
*/
|
||||
async getAccessories(jobId: string): Promise<JobAccessory[]> {
|
||||
const response = await this.request<{ accessories: JobAccessory[] }>(
|
||||
`/jobs/${jobId}/accessories`,
|
||||
{
|
||||
method: 'GET',
|
||||
cacheTTL: 300000 // Cache for 5 minutes
|
||||
}
|
||||
)
|
||||
return response.accessories
|
||||
async getAccessoriesForJob(jobId: string): Promise<JobAccessory[]> {
|
||||
return this.request<JobAccessory[]>(`/jobs/${jobId}/accessories`, {
|
||||
method: 'GET',
|
||||
cacheTTL: 300000 // Cache for 5 minutes
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new job entity (database admin function)
|
||||
* @param data The job data
|
||||
*/
|
||||
async createJob(data: JobUpdatePayload): Promise<Job> {
|
||||
const response = await this.request<Job>('/jobs', {
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
// Clear jobs cache to reflect the new job
|
||||
this.clearCache('/jobs')
|
||||
return response
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -327,12 +350,78 @@ export class JobAdapter extends BaseAdapter {
|
|||
this.clearCache(`/parties/${partyId}`)
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Job Accessory Methods (Database Management)
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* Gets all job accessories
|
||||
* @param accessoryType Optional filter by type (1=Shield, 2=Manatura)
|
||||
*/
|
||||
async getAllAccessories(accessoryType?: number): Promise<JobAccessory[]> {
|
||||
const params = accessoryType ? `?accessory_type=${accessoryType}` : ''
|
||||
return this.request<JobAccessory[]>(`/job_accessories${params}`, {
|
||||
method: 'GET',
|
||||
cacheTTL: 300000 // Cache for 5 minutes
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single job accessory by ID or granblue_id
|
||||
*/
|
||||
async getAccessoryById(id: string): Promise<JobAccessory> {
|
||||
return this.request<JobAccessory>(`/job_accessories/${id}`, {
|
||||
method: 'GET',
|
||||
cacheTTL: 300000 // Cache for 5 minutes
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new job accessory
|
||||
* @param data The accessory data
|
||||
*/
|
||||
async createAccessory(data: JobAccessoryPayload): Promise<JobAccessory> {
|
||||
const response = await this.request<JobAccessory>('/job_accessories', {
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
this.clearCache('/job_accessories')
|
||||
return response
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing job accessory
|
||||
* @param id The accessory's ID or granblue_id
|
||||
* @param data The updated accessory data
|
||||
*/
|
||||
async updateAccessory(id: string, data: Partial<JobAccessoryPayload>): Promise<JobAccessory> {
|
||||
const response = await this.request<JobAccessory>(`/job_accessories/${id}`, {
|
||||
method: 'PUT',
|
||||
body: data
|
||||
})
|
||||
this.clearCache('/job_accessories')
|
||||
this.clearCache(`/job_accessories/${id}`)
|
||||
return response
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a job accessory
|
||||
* @param id The accessory's ID or granblue_id
|
||||
*/
|
||||
async deleteAccessory(id: string): Promise<void> {
|
||||
await this.request(`/job_accessories/${id}`, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
this.clearCache('/job_accessories')
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache for job-related data
|
||||
*/
|
||||
clearJobCache() {
|
||||
this.clearCache('/jobs')
|
||||
this.clearCache('/search/job_skills')
|
||||
this.clearCache('/job_accessories')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,15 +140,15 @@ export const jobQueries = {
|
|||
}),
|
||||
|
||||
/**
|
||||
* Job accessories query options
|
||||
* Job accessories query options (for a specific job)
|
||||
*
|
||||
* @param jobId - Job ID to fetch accessories for
|
||||
* @returns Query options for fetching job accessories
|
||||
*/
|
||||
accessories: (jobId: string) =>
|
||||
accessoriesForJob: (jobId: string) =>
|
||||
queryOptions({
|
||||
queryKey: ['jobs', jobId, 'accessories'] as const,
|
||||
queryFn: () => jobAdapter.getAccessories(jobId),
|
||||
queryFn: () => jobAdapter.getAccessoriesForJob(jobId),
|
||||
enabled: !!jobId,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
gcTime: 1000 * 60 * 60 // 1 hour
|
||||
|
|
@ -165,6 +165,39 @@ export const jobQueries = {
|
|||
queryFn: () => jobAdapter.getAllSkills(),
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
gcTime: 1000 * 60 * 60 // 1 hour
|
||||
}),
|
||||
|
||||
// ============================================
|
||||
// Job Accessory Database Queries
|
||||
// ============================================
|
||||
|
||||
/**
|
||||
* All job accessories list query options
|
||||
*
|
||||
* @param accessoryType - Optional filter by type (1=Shield, 2=Manatura)
|
||||
* @returns Query options for fetching all job accessories
|
||||
*/
|
||||
accessoriesList: (accessoryType?: number) =>
|
||||
queryOptions({
|
||||
queryKey: ['jobAccessories', { accessoryType }] as const,
|
||||
queryFn: () => jobAdapter.getAllAccessories(accessoryType),
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
gcTime: 1000 * 60 * 60 // 1 hour
|
||||
}),
|
||||
|
||||
/**
|
||||
* Single job accessory query options
|
||||
*
|
||||
* @param id - Accessory ID or granblue_id
|
||||
* @returns Query options for fetching a single accessory
|
||||
*/
|
||||
accessoryById: (id: string) =>
|
||||
queryOptions({
|
||||
queryKey: ['jobAccessories', id] as const,
|
||||
queryFn: () => jobAdapter.getAccessoryById(id),
|
||||
enabled: !!id,
|
||||
staleTime: 1000 * 60 * 30, // 30 minutes
|
||||
gcTime: 1000 * 60 * 60 // 1 hour
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +226,15 @@ export const jobKeys = {
|
|||
empSkills: (jobId: string) => [...jobKeys.all, jobId, 'emp_skills'] as const,
|
||||
skillsSearch: (jobId: string, params?: Omit<SearchJobSkillsParams, 'jobId' | 'page'>) =>
|
||||
[...jobKeys.skills(jobId), 'search', params] as const,
|
||||
accessories: (jobId: string) => [...jobKeys.all, jobId, 'accessories'] as const,
|
||||
accessoriesForJob: (jobId: string) => [...jobKeys.all, jobId, 'accessories'] as const,
|
||||
allSkills: () => [...jobKeys.all, 'skills', 'all'] as const
|
||||
}
|
||||
|
||||
/**
|
||||
* Job accessory query key helpers for cache invalidation
|
||||
*/
|
||||
export const jobAccessoryKeys = {
|
||||
all: ['jobAccessories'] as const,
|
||||
lists: (accessoryType?: number) => [...jobAccessoryKeys.all, { accessoryType }] as const,
|
||||
detail: (id: string) => [...jobAccessoryKeys.all, id] as const
|
||||
}
|
||||
|
|
|
|||
13
src/lib/types/JobAccessory.d.ts
vendored
13
src/lib/types/JobAccessory.d.ts
vendored
|
|
@ -1,11 +1,2 @@
|
|||
export interface JobAccessory {
|
||||
id: string
|
||||
granblue_id: string
|
||||
job: Job
|
||||
name: {
|
||||
[key: string]: string
|
||||
en: string
|
||||
ja: string
|
||||
}
|
||||
rarity: number
|
||||
}
|
||||
// Re-export from entities for backwards compatibility
|
||||
export type { JobAccessory } from './api/entities'
|
||||
|
|
|
|||
|
|
@ -201,12 +201,15 @@ export interface JobSkill {
|
|||
actionId?: number // Unique game ID
|
||||
}
|
||||
|
||||
// JobAccessory entity
|
||||
// JobAccessory entity from JobAccessoryBlueprint
|
||||
export interface JobAccessory {
|
||||
id: string
|
||||
name: LocalizedName
|
||||
slug: string
|
||||
granblueId: string
|
||||
rarity: number
|
||||
releaseDate?: string
|
||||
accessoryType: number // 1 = Shield, 2 = Manatura
|
||||
job?: Job // Associated job (optional, included when available)
|
||||
}
|
||||
|
||||
// Raid entity from RaidBlueprint
|
||||
|
|
|
|||
50
src/lib/utils/jobAccessoryUtils.ts
Normal file
50
src/lib/utils/jobAccessoryUtils.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Job Accessory Utilities
|
||||
*
|
||||
* Helper functions for working with job accessories (Shields and Manatura).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Accessory type constants
|
||||
*/
|
||||
export const ACCESSORY_TYPES = {
|
||||
SHIELD: 1,
|
||||
MANATURA: 2
|
||||
} as const
|
||||
|
||||
export type AccessoryType = (typeof ACCESSORY_TYPES)[keyof typeof ACCESSORY_TYPES]
|
||||
|
||||
/**
|
||||
* Gets the display name for an accessory type
|
||||
*/
|
||||
export function getAccessoryTypeName(type: number): string {
|
||||
switch (type) {
|
||||
case ACCESSORY_TYPES.SHIELD:
|
||||
return 'Shield'
|
||||
case ACCESSORY_TYPES.MANATURA:
|
||||
return 'Manatura'
|
||||
default:
|
||||
return 'Unknown'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets options for accessory type filter/select
|
||||
*/
|
||||
export function getAccessoryTypeOptions(): Array<{ value: number; label: string }> {
|
||||
return [
|
||||
{ value: ACCESSORY_TYPES.SHIELD, label: 'Shield' },
|
||||
{ value: ACCESSORY_TYPES.MANATURA, label: 'Manatura' }
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the image URL for a job accessory
|
||||
* @param granblueId The accessory's granblue_id
|
||||
* @param accessoryType The type of accessory (1=Shield, 2=Manatura)
|
||||
*/
|
||||
export function getJobAccessoryImageUrl(granblueId: string, accessoryType: number): string {
|
||||
// Different asset paths based on accessory type
|
||||
const folder = accessoryType === ACCESSORY_TYPES.SHIELD ? 'shield' : 'manatura'
|
||||
return `/images/job-accessories/${folder}/${granblueId}.png`
|
||||
}
|
||||
|
|
@ -290,3 +290,34 @@ export function validateSkillConfiguration(
|
|||
errors
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proficiency options for job forms
|
||||
*/
|
||||
export const PROFICIENCIES = [
|
||||
{ value: 0, label: 'None' },
|
||||
{ value: 1, label: 'Sabre' },
|
||||
{ value: 2, label: 'Dagger' },
|
||||
{ value: 3, label: 'Axe' },
|
||||
{ value: 4, label: 'Spear' },
|
||||
{ value: 5, label: 'Bow' },
|
||||
{ value: 6, label: 'Staff' },
|
||||
{ value: 7, label: 'Melee' },
|
||||
{ value: 8, label: 'Harp' },
|
||||
{ value: 9, label: 'Gun' },
|
||||
{ value: 10, label: 'Katana' }
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Row options for job forms
|
||||
*/
|
||||
export const ROWS = [
|
||||
{ value: '1', label: 'Class I' },
|
||||
{ value: '2', label: 'Class II' },
|
||||
{ value: '3', label: 'Class III' },
|
||||
{ value: '4', label: 'Class IV' },
|
||||
{ value: '5', label: 'Class V' },
|
||||
{ value: 'ex', label: 'EX' },
|
||||
{ value: 'ex2', label: 'EX II' },
|
||||
{ value: 'o1', label: 'Origin I' }
|
||||
] as const
|
||||
|
|
|
|||
Loading…
Reference in a new issue