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 CharacterTypeahead from '$lib/components/ui/CharacterTypeahead.svelte'
|
||||
import { PROMOTION_NAMES, getPromotionNames } from '$lib/types/enums'
|
||||
import { getCharacterImage } from '$lib/utils/images'
|
||||
|
||||
interface Props {
|
||||
weapon: any
|
||||
|
|
@ -40,56 +41,81 @@
|
|||
if (!promotions || promotions.length === 0) return '—'
|
||||
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>
|
||||
|
||||
{#if hasGachaData}
|
||||
<DetailsContainer title="Gacha">
|
||||
{#if editMode}
|
||||
<DetailItem label="Promotions" sublabel="Gacha pools where this weapon appears" editable={true}>
|
||||
<MultiSelect
|
||||
size="medium"
|
||||
options={promotionOptions}
|
||||
bind:value={editData.promotions}
|
||||
placeholder="Select promotions"
|
||||
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)}
|
||||
<DetailsContainer title="Gacha">
|
||||
{#if editMode}
|
||||
<DetailItem label="Promotions" sublabel="Gacha pools where this weapon appears" editable={true}>
|
||||
<MultiSelect
|
||||
size="medium"
|
||||
options={promotionOptions}
|
||||
bind:value={editData.promotions}
|
||||
placeholder="Select promotions"
|
||||
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 label="Recruits" sublabel="Character recruited by this weapon">
|
||||
{#if weapon.recruits}
|
||||
<DetailItem
|
||||
label="Recruits"
|
||||
sublabel="Character recruited by this weapon"
|
||||
value={formatRecruitsDisplay(weapon.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>
|
||||
{:else}
|
||||
<span class="empty-value">—</span>
|
||||
{/if}
|
||||
{/if}
|
||||
</DetailsContainer>
|
||||
{/if}
|
||||
</DetailItem>
|
||||
{/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 CopyableText from '$lib/components/ui/CopyableText.svelte'
|
||||
import { getRarityLabel, getRarityOptions } from '$lib/utils/rarity'
|
||||
import { getCharacterImage } from '$lib/utils/images'
|
||||
|
||||
interface Props {
|
||||
weapon: any
|
||||
|
|
@ -35,6 +34,20 @@
|
|||
|
||||
<DetailsContainer title="Metadata">
|
||||
{#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
|
||||
label="Rarity"
|
||||
bind:value={editData.rarity}
|
||||
|
|
@ -53,6 +66,8 @@
|
|||
type="text"
|
||||
/>
|
||||
{: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="Granblue ID">
|
||||
{#if weapon.granblueId}
|
||||
|
|
@ -61,53 +76,7 @@
|
|||
—
|
||||
{/if}
|
||||
</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}
|
||||
</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