move Recruits and Promotions to Gacha section
This commit is contained in:
parent
850c5dd771
commit
cfb62447a0
3 changed files with 96 additions and 40 deletions
|
|
@ -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}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
Loading…
Reference in a new issue