add quest_id support and lobby/background images for raids

- add quest_id to types and forms
- add lobby and background images to detail page
- update adapter for new image sizes
This commit is contained in:
Justin Edmund 2026-01-06 03:52:40 -08:00
parent 96db589dea
commit b2559f5f39
6 changed files with 64 additions and 10 deletions

View file

@ -109,12 +109,12 @@ export class RaidAdapter extends BaseAdapter {
* Downloads a single image for a raid (synchronous) * Downloads a single image for a raid (synchronous)
* Requires editor role (>= 7) * Requires editor role (>= 7)
* @param slug - Raid slug * @param slug - Raid slug
* @param size - Image size variant ('icon' or 'thumbnail') * @param size - Image size variant ('icon', 'thumbnail', 'lobby', or 'background')
* @param force - Force re-download even if image exists * @param force - Force re-download even if image exists
*/ */
async downloadRaidImage( async downloadRaidImage(
slug: string, slug: string,
size: 'icon' | 'thumbnail', size: 'icon' | 'thumbnail' | 'lobby' | 'background',
force?: boolean, force?: boolean,
options?: RequestOptions options?: RequestOptions
): Promise<{ success: boolean; error?: string }> { ): Promise<{ success: boolean; error?: string }> {
@ -131,7 +131,7 @@ export class RaidAdapter extends BaseAdapter {
*/ */
async downloadRaidImages( async downloadRaidImages(
slug: string, slug: string,
downloadOptions?: { force?: boolean; size?: 'all' | 'icon' | 'thumbnail' }, downloadOptions?: { force?: boolean; size?: 'all' | 'icon' | 'thumbnail' | 'lobby' | 'background' },
requestOptions?: RequestOptions requestOptions?: RequestOptions
): Promise<{ status: string; raidId: string; message: string }> { ): Promise<{ status: string; raidId: string; message: string }> {
return this.request(`/raids/${slug}/download_images`, { return this.request(`/raids/${slug}/download_images`, {

View file

@ -222,6 +222,7 @@ export interface Raid {
element: number element: number
enemy_id?: number enemy_id?: number
summon_id?: number summon_id?: number
quest_id?: number
group?: RaidGroup group?: RaidGroup
} }

View file

@ -18,6 +18,7 @@ export interface RaidFull {
element: number element: number
enemy_id?: number enemy_id?: number
summon_id?: number summon_id?: number
quest_id?: number
group?: RaidGroupFlat group?: RaidGroupFlat
} }
@ -49,6 +50,7 @@ export interface CreateRaidInput {
group_id: string group_id: string
enemy_id?: number enemy_id?: number
summon_id?: number summon_id?: number
quest_id?: number
} }
export interface UpdateRaidInput { export interface UpdateRaidInput {
@ -60,6 +62,7 @@ export interface UpdateRaidInput {
group_id?: string group_id?: string
enemy_id?: number enemy_id?: number
summon_id?: number summon_id?: number
quest_id?: number
} }
// Input types for creating/updating raid groups // Input types for creating/updating raid groups

View file

@ -18,6 +18,8 @@
// CDN base URLs for raid images // CDN base URLs for raid images
const ICON_BASE_URL = 'https://prd-game-a-granbluefantasy.akamaized.net/assets_en/img/sp/assets/enemy/m' const ICON_BASE_URL = 'https://prd-game-a-granbluefantasy.akamaized.net/assets_en/img/sp/assets/enemy/m'
const THUMBNAIL_BASE_URL = 'https://prd-game-a1-granbluefantasy.akamaized.net/assets_en/img/sp/assets/summon/qm' const THUMBNAIL_BASE_URL = 'https://prd-game-a1-granbluefantasy.akamaized.net/assets_en/img/sp/assets/summon/qm'
const LOBBY_BASE_URL = 'https://prd-game-a1-granbluefantasy.akamaized.net/assets_en/img/sp/quest/assets/lobby'
const BACKGROUND_BASE_URL = 'https://prd-game-a-granbluefantasy.akamaized.net/assets_en/img/sp/quest/assets/treasureraid'
function displayName(input: any): string { function displayName(input: any): string {
if (!input) return '—' if (!input) return '—'
@ -85,6 +87,16 @@
return `${THUMBNAIL_BASE_URL}/${summonId}_high.png` return `${THUMBNAIL_BASE_URL}/${summonId}_high.png`
} }
// Get lobby image URL (quest_id with "1" appended)
function getLobbyUrl(questId: number): string {
return `${LOBBY_BASE_URL}/${questId}1.png`
}
// Get background image URL
function getBackgroundUrl(questId: number): string {
return `${BACKGROUND_BASE_URL}/${questId}/raid_image_new.png`
}
// Get header image - prefer thumbnail, fallback to icon // Get header image - prefer thumbnail, fallback to icon
const headerImage = $derived.by(() => { const headerImage = $derived.by(() => {
if (raid?.summon_id) return getThumbnailUrl(raid.summon_id) if (raid?.summon_id) return getThumbnailUrl(raid.summon_id)
@ -97,6 +109,10 @@
const sizes: string[] = [] const sizes: string[] = []
if (raid?.enemy_id) sizes.push('icon') if (raid?.enemy_id) sizes.push('icon')
if (raid?.summon_id) sizes.push('thumbnail') if (raid?.summon_id) sizes.push('thumbnail')
if (raid?.quest_id) {
sizes.push('lobby')
sizes.push('background')
}
return sizes return sizes
}) })
@ -124,17 +140,33 @@
}) })
} }
// Lobby and background images from quest
if (raid.quest_id) {
images.push({
url: getLobbyUrl(raid.quest_id),
label: 'Lobby',
variant: 'lobby'
})
images.push({
url: getBackgroundUrl(raid.quest_id),
label: 'Background',
variant: 'background'
})
}
return images return images
}) })
// Image download handlers // Image download handlers
type RaidImageSize = 'icon' | 'thumbnail' | 'lobby' | 'background'
async function handleDownloadImage( async function handleDownloadImage(
size: string, size: string,
_transformation: string | undefined, _transformation: string | undefined,
force: boolean force: boolean
) { ) {
if (!raidSlug) return if (!raidSlug) return
await raidAdapter.downloadRaidImage(raidSlug, size as 'icon' | 'thumbnail', force) await raidAdapter.downloadRaidImage(raidSlug, size as RaidImageSize, force)
} }
async function handleDownloadAllImages(force: boolean) { async function handleDownloadAllImages(force: boolean) {
@ -144,7 +176,7 @@
async function handleDownloadSize(size: string) { async function handleDownloadSize(size: string) {
if (!raidSlug) return if (!raidSlug) return
await raidAdapter.downloadRaidImage(raidSlug, size as 'icon' | 'thumbnail', false) await raidAdapter.downloadRaidImage(raidSlug, size as RaidImageSize, false)
} }
</script> </script>
@ -188,6 +220,7 @@
<DetailItem label="Level" value={raid.level?.toString() ?? '-'} /> <DetailItem label="Level" value={raid.level?.toString() ?? '-'} />
<DetailItem label="Enemy ID" value={raid.enemy_id?.toString() ?? '-'} /> <DetailItem label="Enemy ID" value={raid.enemy_id?.toString() ?? '-'} />
<DetailItem label="Summon ID" value={raid.summon_id?.toString() ?? '-'} /> <DetailItem label="Summon ID" value={raid.summon_id?.toString() ?? '-'} />
<DetailItem label="Quest ID" value={raid.quest_id?.toString() ?? '-'} />
<DetailItem label="Element"> <DetailItem label="Element">
{#if raid.element !== undefined && raid.element !== null} {#if raid.element !== undefined && raid.element !== null}
<ElementBadge element={raid.element} /> <ElementBadge element={raid.element} />

View file

@ -59,7 +59,8 @@
element: 0, element: 0,
group_id: '', group_id: '',
enemy_id: undefined as number | undefined, enemy_id: undefined as number | undefined,
summon_id: undefined as number | undefined summon_id: undefined as number | undefined,
quest_id: undefined as number | undefined
}) })
// Sync edit data when raid changes // Sync edit data when raid changes
@ -73,7 +74,8 @@
element: raid.element ?? 0, element: raid.element ?? 0,
group_id: raid.group?.id || '', group_id: raid.group?.id || '',
enemy_id: raid.enemy_id, enemy_id: raid.enemy_id,
summon_id: raid.summon_id summon_id: raid.summon_id,
quest_id: raid.quest_id
} }
} }
}) })
@ -118,7 +120,8 @@
element: editData.element, element: editData.element,
group_id: editData.group_id, group_id: editData.group_id,
enemy_id: editData.enemy_id, enemy_id: editData.enemy_id,
summon_id: editData.summon_id summon_id: editData.summon_id,
quest_id: editData.quest_id
}) })
// Invalidate queries // Invalidate queries
@ -201,6 +204,12 @@
editable={true} editable={true}
type="number" type="number"
/> />
<DetailItem
label="Quest ID"
bind:value={editData.quest_id}
editable={true}
type="number"
/>
<DetailItem <DetailItem
label="Element" label="Element"
bind:value={editData.element} bind:value={editData.element}

View file

@ -46,7 +46,8 @@
element: 0, element: 0,
group_id: '', group_id: '',
enemy_id: undefined as number | undefined, enemy_id: undefined as number | undefined,
summon_id: undefined as number | undefined summon_id: undefined as number | undefined,
quest_id: undefined as number | undefined
}) })
// Element options // Element options
@ -89,7 +90,8 @@
element: editData.element, element: editData.element,
group_id: editData.group_id, group_id: editData.group_id,
enemy_id: editData.enemy_id, enemy_id: editData.enemy_id,
summon_id: editData.summon_id summon_id: editData.summon_id,
quest_id: editData.quest_id
}) })
// Invalidate queries // Invalidate queries
@ -167,6 +169,12 @@
editable={true} editable={true}
type="number" type="number"
/> />
<DetailItem
label="Quest ID"
bind:value={editData.quest_id}
editable={true}
type="number"
/>
<DetailItem <DetailItem
label="Element" label="Element"
bind:value={editData.element} bind:value={editData.element}