components: use centralized image URL helpers
This commit is contained in:
parent
e9463ae5ba
commit
43c291327c
9 changed files with 48 additions and 28 deletions
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import type { Party } from '$lib/types/api/party'
|
||||
import { getGuidebookImage } from '$lib/utils/images'
|
||||
|
||||
export let item: any | undefined
|
||||
export let position: number // 1..3
|
||||
|
|
@ -22,9 +23,7 @@
|
|||
}
|
||||
|
||||
function guidebookImageUrl(g?: any): string {
|
||||
const id = g?.granblueId
|
||||
if (!id) return '/images/placeholders/placeholder-weapon-grid.png'
|
||||
return `/images/guidebooks/book_${id}.png`
|
||||
return getGuidebookImage(g?.granblueId)
|
||||
}
|
||||
|
||||
async function remove() {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
isSkillSlotAvailable,
|
||||
isSkillSlotLocked
|
||||
} from '$lib/utils/jobUtils'
|
||||
import { getAccessoryImage } from '$lib/utils/images'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
|
||||
interface Props {
|
||||
|
|
@ -155,7 +156,7 @@
|
|||
>
|
||||
{#if accessory}
|
||||
<img
|
||||
src="/images/accessory-square/{accessory.granblueId}.jpg"
|
||||
src={getAccessoryImage(accessory.granblueId)}
|
||||
alt={accessory.name.en}
|
||||
class="accessory-icon"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { JobSkill } from '$lib/types/api/entities'
|
||||
import { getSkillCategoryName } from '$lib/utils/jobUtils'
|
||||
import { getJobSkillIcon } from '$lib/utils/images'
|
||||
|
||||
interface Props {
|
||||
skill: JobSkill
|
||||
|
|
@ -13,11 +14,7 @@
|
|||
let { skill, onClick, disabled = false, variant = 'default', onRemove }: Props = $props()
|
||||
|
||||
function getSkillIcon(skill: JobSkill): string {
|
||||
if (skill.slug) {
|
||||
return `/images/job-skills/${skill.slug}.png`
|
||||
}
|
||||
// Fallback if no slug
|
||||
return '/images/job-skills/default.png'
|
||||
return getJobSkillIcon(skill.slug)
|
||||
}
|
||||
|
||||
function getSkillColorClass(skill: JobSkill): string {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import type { JobSkill } from '$lib/types/api/entities'
|
||||
import { getSkillCategoryColor } from '$lib/utils/jobUtils'
|
||||
import { getJobSkillIcon } from '$lib/utils/images'
|
||||
import Icon from '$lib/components/Icon.svelte'
|
||||
import Tooltip from '$lib/components/ui/Tooltip.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
|
|
@ -26,7 +27,7 @@
|
|||
}: Props = $props()
|
||||
|
||||
const categoryColor = $derived(skill ? getSkillCategoryColor(skill) : '')
|
||||
const skillIconUrl = $derived(skill?.slug ? `/images/job-skills/${skill.slug}.png` : '')
|
||||
const skillIconUrl = $derived(skill?.slug ? getJobSkillIcon(skill.slug) : '')
|
||||
|
||||
const isEditable = $derived(editable && !locked && available)
|
||||
const isUnavailable = $derived(!available)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { searchAdapter, type SearchResult } from '$lib/api/adapters'
|
||||
import { getCharacterImage, getWeaponImage, getSummonImage, getPlaceholderImage } from '$lib/utils/images'
|
||||
|
||||
interface Props {
|
||||
open?: boolean
|
||||
|
|
@ -182,10 +183,19 @@
|
|||
}
|
||||
|
||||
function getImageUrl(item: SearchResult): string {
|
||||
if (!item.granblueId) return '/images/placeholders/placeholder-' + type + '.png'
|
||||
const id = item.granblueId
|
||||
if (!id) return getPlaceholderImage(type, 'grid')
|
||||
|
||||
const folder = type === 'weapon' ? 'weapon-grid' : type
|
||||
return `/images/${folder}/${item.granblueId}.jpg`
|
||||
switch (type) {
|
||||
case 'character':
|
||||
return getCharacterImage(id, 'grid', '01')
|
||||
case 'weapon':
|
||||
return getWeaponImage(id, 'grid')
|
||||
case 'summon':
|
||||
return getSummonImage(id, 'grid')
|
||||
default:
|
||||
return getPlaceholderImage(type, 'grid')
|
||||
}
|
||||
}
|
||||
|
||||
function getItemName(item: SearchResult): string {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
import AwakeningSelect from './edit/AwakeningSelect.svelte'
|
||||
import AxSkillSelect from './edit/AxSkillSelect.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
import { getElementIcon } from '$lib/utils/images'
|
||||
|
||||
interface Props {
|
||||
weapon: GridWeapon
|
||||
|
|
@ -78,12 +79,12 @@
|
|||
|
||||
// Element options
|
||||
const elementOptions = [
|
||||
{ value: 1, label: 'Wind', image: '/images/elements/element-wind.png' },
|
||||
{ value: 2, label: 'Fire', image: '/images/elements/element-fire.png' },
|
||||
{ value: 3, label: 'Water', image: '/images/elements/element-water.png' },
|
||||
{ value: 4, label: 'Earth', image: '/images/elements/element-earth.png' },
|
||||
{ value: 5, label: 'Dark', image: '/images/elements/element-dark.png' },
|
||||
{ value: 6, label: 'Light', image: '/images/elements/element-light.png' }
|
||||
{ value: 1, label: 'Wind', image: getElementIcon(1) },
|
||||
{ value: 2, label: 'Fire', image: getElementIcon(2) },
|
||||
{ value: 3, label: 'Water', image: getElementIcon(3) },
|
||||
{ value: 4, label: 'Earth', image: getElementIcon(4) },
|
||||
{ value: 5, label: 'Dark', image: getElementIcon(5) },
|
||||
{ value: 6, label: 'Light', image: getElementIcon(6) }
|
||||
]
|
||||
|
||||
function displayName(input: any): string {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import type { GridCharacter } from '$lib/types/api/party'
|
||||
import { formatRingStat, formatEarringStat } from '$lib/utils/modificationFormatters'
|
||||
import { getRingStat, getElementalizedEarringStat } from '$lib/utils/masteryUtils'
|
||||
import { getMasteryImage } from '$lib/utils/images'
|
||||
import { getLocale } from '$lib/paraglide/runtime.js'
|
||||
|
||||
interface Props {
|
||||
|
|
@ -29,7 +30,7 @@
|
|||
|
||||
if (!stat || !stat.slug) return null
|
||||
|
||||
return `/images/mastery/${stat.slug}.png`
|
||||
return getMasteryImage(stat.slug)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,16 @@
|
|||
|
||||
import type { Job, JobSkill } from '$lib/types/api/entities'
|
||||
import type { JobSkillList } from '$lib/types/api/party'
|
||||
import { getImageBaseUrl } from '$lib/api/adapters/config'
|
||||
|
||||
/**
|
||||
* Gets the base path for images
|
||||
* Returns AWS S3/CDN URL if configured, otherwise local /images path
|
||||
*/
|
||||
function getBasePath(): string {
|
||||
const remoteUrl = getImageBaseUrl()
|
||||
return remoteUrl || '/images'
|
||||
}
|
||||
|
||||
/**
|
||||
* Gender options for job portraits
|
||||
|
|
@ -29,7 +39,7 @@ export function getJobPortraitUrl(job: Job | undefined, gender: Gender = Gender.
|
|||
const slug = job.name.en.toLowerCase().replace(/\s+/g, '-')
|
||||
const genderSuffix = gender === Gender.Djeeta ? 'b' : 'a'
|
||||
|
||||
return `/images/job-portraits/${slug}_${genderSuffix}.png`
|
||||
return `${getBasePath()}/job-portraits/${slug}_${genderSuffix}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -43,20 +53,19 @@ export function getJobFullImageUrl(job: Job | undefined, gender: Gender = Gender
|
|||
|
||||
const genderSuffix = gender === Gender.Djeeta ? 'b' : 'a'
|
||||
|
||||
return `/images/job-zoom/${job.granblueId}_${genderSuffix}.png`
|
||||
return `${getBasePath()}/job-zoom/${job.granblueId}_${genderSuffix}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate job icon URL
|
||||
* Job icons are small square icons representing the job
|
||||
* Images are stored locally in /static/images/job-icons/
|
||||
*/
|
||||
export function getJobIconUrl(granblueId: string | undefined): string {
|
||||
if (!granblueId) {
|
||||
return '/images/placeholders/placeholder-weapon-grid.png'
|
||||
}
|
||||
|
||||
return `/images/job-icons/${granblueId}.png`
|
||||
return `${getBasePath()}/job-icons/${granblueId}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -69,7 +78,7 @@ export function getJobWideImageUrl(job: Job | undefined, gender: Gender = Gender
|
|||
}
|
||||
|
||||
const genderSuffix = gender === Gender.Djeeta ? 'b' : 'a'
|
||||
return `/images/job-wide/${job.granblueId}_${genderSuffix}.jpg`
|
||||
return `${getBasePath()}/job-wide/${job.granblueId}_${genderSuffix}.jpg`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
import type { Awakening, WeaponKey } from '$lib/types/api/entities'
|
||||
import type { SimpleAxSkill } from '$lib/types/SimpleAxSkill'
|
||||
import { getBasePath } from '$lib/utils/images'
|
||||
|
||||
/**
|
||||
* Get the image URL for an awakening type
|
||||
|
|
@ -20,7 +21,7 @@ export function getAwakeningImage(awakening?: { type?: Awakening; level?: number
|
|||
const isCharacterAwakening = slug.startsWith('character-')
|
||||
const extension = isCharacterAwakening ? 'jpg' : 'png'
|
||||
|
||||
return `/images/awakening/${slug}.${extension}`
|
||||
return `${getBasePath()}/awakening/${slug}.${extension}`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -35,7 +36,7 @@ export function getWeaponKeyImage(
|
|||
): string {
|
||||
if (!key.slug) return ''
|
||||
|
||||
const baseUrl = '/images/weapon-keys/'
|
||||
const baseUrl = `${getBasePath()}/weapon-keys/`
|
||||
let filename = key.slug
|
||||
|
||||
// Handle element-specific telumas (Draconic weapons)
|
||||
|
|
@ -97,7 +98,7 @@ export function getWeaponKeyImages(
|
|||
*/
|
||||
export function getAxSkillImage(axSkill?: { slug?: string }): string | null {
|
||||
if (!axSkill?.slug) return null
|
||||
return `/images/ax/${axSkill.slug}.png`
|
||||
return `${getBasePath()}/ax/${axSkill.slug}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue