move Recruits and Promotions to Gacha section

This commit is contained in:
Justin Edmund 2025-12-14 21:50:35 -08:00
parent 850c5dd771
commit cfb62447a0
3 changed files with 96 additions and 40 deletions

View file

@ -0,0 +1,93 @@
<svelte:options runes={true} />
<script lang="ts">
import type { WeaponSuggestions } from '$lib/api/adapters/entity.adapter'
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
import DetailItem from '$lib/components/ui/DetailItem.svelte'
import MultiSelect from '$lib/components/ui/MultiSelect.svelte'
import CharacterTypeahead from '$lib/components/ui/CharacterTypeahead.svelte'
import { PROMOTION_NAMES, getPromotionNames } from '$lib/types/enums'
interface Props {
weapon: any
editMode?: boolean
editData?: any
// Suggestion support for batch import
suggestions?: WeaponSuggestions
dismissedSuggestions?: Set<string>
onAcceptSuggestion?: (field: string, value: any) => void
onDismissSuggestion?: (field: string) => void
}
let {
weapon,
editMode = false,
editData = $bindable(),
suggestions,
dismissedSuggestions,
onAcceptSuggestion,
onDismissSuggestion
}: Props = $props()
// Promotion options for multiselect
const promotionOptions = Object.entries(PROMOTION_NAMES).map(([value, label]) => ({
value: Number(value),
label
}))
// Format promotions for display
function formatPromotionsDisplay(promotions: number[]): string {
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">
<CharacterTypeahead
bind:value={editData.recruits}
placeholder="Search for character..."
/>
</DetailItem>
{:else}
<DetailItem
label="Promotions"
sublabel="Gacha pools where this weapon appears"
value={formatPromotionsDisplay(weapon.promotions)}
/>
{#if weapon.recruits}
<DetailItem
label="Recruits"
sublabel="Character recruited by this weapon"
value={formatRecruitsDisplay(weapon.recruits)}
/>
{/if}
{/if}
</DetailsContainer>
{/if}

View file

@ -7,14 +7,12 @@
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
import DetailItem from '$lib/components/ui/DetailItem.svelte'
import SuggestionDetailItem from '$lib/components/ui/SuggestionDetailItem.svelte'
import MultiSelect from '$lib/components/ui/MultiSelect.svelte'
import ElementLabel from '$lib/components/labels/ElementLabel.svelte'
import ProficiencyLabel from '$lib/components/labels/ProficiencyLabel.svelte'
import { getElementLabel, getElementOptions } from '$lib/utils/element'
import { getProficiencyOptions } from '$lib/utils/proficiency'
import { getSeriesDisplayName } from '$lib/utils/weaponSeries'
import { isWeaponSeriesRef, type WeaponSeriesRef } from '$lib/types/api/weaponSeries'
import { PROMOTION_NAMES, getPromotionNames } from '$lib/types/enums'
import type { WeaponSeriesRef } from '$lib/types/api/weaponSeries'
type ElementName = 'wind' | 'fire' | 'water' | 'earth' | 'dark' | 'light'
@ -58,12 +56,6 @@
]
})
// Promotion options for multiselect
const promotionOptions = Object.entries(PROMOTION_NAMES).map(([value, label]) => ({
value: Number(value),
label
}))
// Get element name for checkbox theming
const elementName = $derived.by((): ElementName | undefined => {
const el = editMode ? editData.element : weapon?.element
@ -76,12 +68,6 @@
if (!series) return '—'
return getSeriesDisplayName(series, 'en') || '—'
}
// Format promotions for display
function formatPromotionsDisplay(promotions: number[]): string {
if (!promotions || promotions.length === 0) return '—'
return getPromotionNames(promotions).join(', ')
}
</script>
<DetailsContainer title="Details">
@ -139,15 +125,6 @@
type="checkbox"
element={elementName}
/>
<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>
{:else}
<DetailItem label="Element">
<ElementLabel element={weapon.element} size="medium" />
@ -170,10 +147,5 @@
value={weapon.limit ? 'Yes' : 'No'}
/>
<DetailItem label="AX Skills" sublabel="Can have AX Skills" value={weapon.ax ? 'Yes' : 'No'} />
<DetailItem
label="Promotions"
sublabel="Gacha pools where this weapon appears"
value={formatPromotionsDisplay(weapon.promotions)}
/>
{/if}
</DetailsContainer>

View file

@ -16,6 +16,7 @@
import WeaponUncapSection from '$lib/features/database/weapons/sections/WeaponUncapSection.svelte'
import WeaponTaxonomySection from '$lib/features/database/weapons/sections/WeaponTaxonomySection.svelte'
import WeaponStatsSection from '$lib/features/database/weapons/sections/WeaponStatsSection.svelte'
import WeaponGachaSection from '$lib/features/database/weapons/sections/WeaponGachaSection.svelte'
import DetailsContainer from '$lib/components/ui/DetailsContainer.svelte'
import DetailItem from '$lib/components/ui/DetailItem.svelte'
import TagInput from '$lib/components/ui/TagInput.svelte'
@ -218,6 +219,7 @@
<WeaponUncapSection {weapon} {editMode} bind:editData />
<WeaponTaxonomySection {weapon} {editMode} bind:editData />
<WeaponStatsSection {weapon} {editMode} bind:editData />
<WeaponGachaSection {weapon} {editMode} bind:editData />
<DetailsContainer title="Nicknames">
<DetailItem label="Nicknames (EN)">
@ -299,17 +301,6 @@
width="480px"
/>
</DetailsContainer>
<DetailsContainer title="Character">
<DetailItem
label="Recruits"
sublabel="Character ID this weapon recruits"
bind:value={editData.recruits}
editable={true}
type="text"
placeholder="Character ID..."
/>
</DetailsContainer>
</section>
</DetailScaffold>
{:else}