weapon sections: add name fields to metadata, move recruits to gacha
This commit is contained in:
parent
0812e3b2d4
commit
70c0881bb4
2 changed files with 90 additions and 95 deletions
|
|
@ -7,6 +7,7 @@
|
||||||
import MultiSelect from '$lib/components/ui/MultiSelect.svelte'
|
import MultiSelect from '$lib/components/ui/MultiSelect.svelte'
|
||||||
import CharacterTypeahead from '$lib/components/ui/CharacterTypeahead.svelte'
|
import CharacterTypeahead from '$lib/components/ui/CharacterTypeahead.svelte'
|
||||||
import { PROMOTION_NAMES, getPromotionNames } from '$lib/types/enums'
|
import { PROMOTION_NAMES, getPromotionNames } from '$lib/types/enums'
|
||||||
|
import { getCharacterImage } from '$lib/utils/images'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
weapon: any
|
weapon: any
|
||||||
|
|
@ -40,56 +41,81 @@
|
||||||
if (!promotions || promotions.length === 0) return '—'
|
if (!promotions || promotions.length === 0) return '—'
|
||||||
return getPromotionNames(promotions).join(', ')
|
return getPromotionNames(promotions).join(', ')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format recruits for display
|
|
||||||
function formatRecruitsDisplay(recruits: any): string {
|
|
||||||
if (!recruits) return '—'
|
|
||||||
if (typeof recruits === 'string') return recruits
|
|
||||||
return recruits.name?.en || recruits.granblueId || '—'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we should show the section in view mode
|
|
||||||
const hasGachaData = $derived.by(() => {
|
|
||||||
if (editMode) return true
|
|
||||||
const hasPromotions = weapon?.promotions && weapon.promotions.length > 0
|
|
||||||
const hasRecruits = weapon?.recruits
|
|
||||||
return hasPromotions || hasRecruits
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if hasGachaData}
|
<DetailsContainer title="Gacha">
|
||||||
<DetailsContainer title="Gacha">
|
{#if editMode}
|
||||||
{#if editMode}
|
<DetailItem label="Promotions" sublabel="Gacha pools where this weapon appears" editable={true}>
|
||||||
<DetailItem label="Promotions" sublabel="Gacha pools where this weapon appears" editable={true}>
|
<MultiSelect
|
||||||
<MultiSelect
|
size="medium"
|
||||||
size="medium"
|
options={promotionOptions}
|
||||||
options={promotionOptions}
|
bind:value={editData.promotions}
|
||||||
bind:value={editData.promotions}
|
placeholder="Select promotions"
|
||||||
placeholder="Select promotions"
|
contained
|
||||||
contained
|
|
||||||
/>
|
|
||||||
</DetailItem>
|
|
||||||
<DetailItem label="Recruits" sublabel="Character recruited by this weapon" editable={true}>
|
|
||||||
<CharacterTypeahead
|
|
||||||
bind:value={editData.recruits}
|
|
||||||
initialCharacter={weapon.recruits ? { id: weapon.recruits.id, name: weapon.recruits.name?.en || weapon.recruits.granblueId, granblueId: weapon.recruits.granblueId } : null}
|
|
||||||
placeholder="Search for character..."
|
|
||||||
contained
|
|
||||||
/>
|
|
||||||
</DetailItem>
|
|
||||||
{:else}
|
|
||||||
<DetailItem
|
|
||||||
label="Promotions"
|
|
||||||
sublabel="Gacha pools where this weapon appears"
|
|
||||||
value={formatPromotionsDisplay(weapon.promotions)}
|
|
||||||
/>
|
/>
|
||||||
|
</DetailItem>
|
||||||
|
<DetailItem label="Recruits" sublabel="Character recruited by this weapon" editable={true}>
|
||||||
|
<CharacterTypeahead
|
||||||
|
bind:value={editData.recruits}
|
||||||
|
initialCharacter={weapon.recruits ? { id: weapon.recruits.id, name: weapon.recruits.name?.en || weapon.recruits.granblueId, granblueId: weapon.recruits.granblueId } : null}
|
||||||
|
placeholder="Search for character..."
|
||||||
|
contained
|
||||||
|
/>
|
||||||
|
</DetailItem>
|
||||||
|
{:else}
|
||||||
|
<DetailItem
|
||||||
|
label="Promotions"
|
||||||
|
sublabel="Gacha pools where this weapon appears"
|
||||||
|
value={formatPromotionsDisplay(weapon.promotions)}
|
||||||
|
/>
|
||||||
|
<DetailItem label="Recruits" sublabel="Character recruited by this weapon">
|
||||||
{#if weapon.recruits}
|
{#if weapon.recruits}
|
||||||
<DetailItem
|
<a href="/database/characters/{weapon.recruits.granblueId}" class="recruits-link">
|
||||||
label="Recruits"
|
<img
|
||||||
sublabel="Character recruited by this weapon"
|
src={getCharacterImage(weapon.recruits.granblueId, 'square', '01')}
|
||||||
value={formatRecruitsDisplay(weapon.recruits)}
|
alt={weapon.recruits.name?.en || 'Recruited character'}
|
||||||
/>
|
class="recruits-image"
|
||||||
|
/>
|
||||||
|
<span class="recruits-name">{weapon.recruits.name?.en}</span>
|
||||||
|
</a>
|
||||||
|
{:else}
|
||||||
|
<span class="empty-value">—</span>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
</DetailItem>
|
||||||
</DetailsContainer>
|
{/if}
|
||||||
{/if}
|
</DetailsContainer>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@use '$src/themes/colors' as colors;
|
||||||
|
@use '$src/themes/spacing' as spacing;
|
||||||
|
@use '$src/themes/typography' as typography;
|
||||||
|
@use '$src/themes/layout' as layout;
|
||||||
|
|
||||||
|
.recruits-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: spacing.$unit;
|
||||||
|
text-decoration: none;
|
||||||
|
color: colors.$grey-30;
|
||||||
|
|
||||||
|
&:hover .recruits-image {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .recruits-name {
|
||||||
|
color: colors.$blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.recruits-image {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: layout.$item-corner-small;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recruits-name {
|
||||||
|
font-size: typography.$font-regular;
|
||||||
|
transition: color 0.2s ease;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
import SuggestionDetailItem from '$lib/components/ui/SuggestionDetailItem.svelte'
|
import SuggestionDetailItem from '$lib/components/ui/SuggestionDetailItem.svelte'
|
||||||
import CopyableText from '$lib/components/ui/CopyableText.svelte'
|
import CopyableText from '$lib/components/ui/CopyableText.svelte'
|
||||||
import { getRarityLabel, getRarityOptions } from '$lib/utils/rarity'
|
import { getRarityLabel, getRarityOptions } from '$lib/utils/rarity'
|
||||||
import { getCharacterImage } from '$lib/utils/images'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
weapon: any
|
weapon: any
|
||||||
|
|
@ -35,6 +34,20 @@
|
||||||
|
|
||||||
<DetailsContainer title="Metadata">
|
<DetailsContainer title="Metadata">
|
||||||
{#if editMode}
|
{#if editMode}
|
||||||
|
<DetailItem
|
||||||
|
label="Name (EN)"
|
||||||
|
bind:value={editData.name}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="English name"
|
||||||
|
/>
|
||||||
|
<DetailItem
|
||||||
|
label="Name (JP)"
|
||||||
|
bind:value={editData.nameJp}
|
||||||
|
editable={true}
|
||||||
|
type="text"
|
||||||
|
placeholder="日本語名"
|
||||||
|
/>
|
||||||
<SuggestionDetailItem
|
<SuggestionDetailItem
|
||||||
label="Rarity"
|
label="Rarity"
|
||||||
bind:value={editData.rarity}
|
bind:value={editData.rarity}
|
||||||
|
|
@ -53,6 +66,8 @@
|
||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
|
<DetailItem label="Name (EN)" value={weapon.name?.en || '—'} />
|
||||||
|
<DetailItem label="Name (JP)" value={weapon.name?.ja || '—'} />
|
||||||
<DetailItem label="Rarity" value={getRarityLabel(weapon.rarity)} />
|
<DetailItem label="Rarity" value={getRarityLabel(weapon.rarity)} />
|
||||||
<DetailItem label="Granblue ID">
|
<DetailItem label="Granblue ID">
|
||||||
{#if weapon.granblueId}
|
{#if weapon.granblueId}
|
||||||
|
|
@ -61,53 +76,7 @@
|
||||||
—
|
—
|
||||||
{/if}
|
{/if}
|
||||||
</DetailItem>
|
</DetailItem>
|
||||||
{#if weapon.recruits}
|
|
||||||
<DetailItem label="Recruits">
|
|
||||||
<a href="/database/characters/{weapon.recruits.granblueId}" class="recruits-link">
|
|
||||||
<img
|
|
||||||
src={getCharacterImage(weapon.recruits.granblueId, 'square', '01')}
|
|
||||||
alt={weapon.recruits.name.en || 'Recruited character'}
|
|
||||||
class="recruits-image"
|
|
||||||
/>
|
|
||||||
<span class="recruits-name">{weapon.recruits.name.en}</span>
|
|
||||||
</a>
|
|
||||||
</DetailItem>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
</DetailsContainer>
|
</DetailsContainer>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
@use '$src/themes/colors' as colors;
|
|
||||||
@use '$src/themes/spacing' as spacing;
|
|
||||||
@use '$src/themes/typography' as typography;
|
|
||||||
@use '$src/themes/layout' as layout;
|
|
||||||
|
|
||||||
.recruits-link {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: spacing.$unit;
|
|
||||||
text-decoration: none;
|
|
||||||
color: colors.$grey-30;
|
|
||||||
|
|
||||||
&:hover .recruits-image {
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .recruits-name {
|
|
||||||
color: colors.$blue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.recruits-image {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: layout.$item-corner-small;
|
|
||||||
transition: transform 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recruits-name {
|
|
||||||
font-size: typography.$font-regular;
|
|
||||||
transition: color 0.2s ease;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue