consolidate series pages into single page with tabs

This commit is contained in:
Justin Edmund 2025-12-14 11:59:35 -08:00
parent 50ee6b80ff
commit f429988981

View file

@ -3,18 +3,55 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { entityQueries } from '$lib/api/queries/entity.queries'
import SegmentedControl from '$lib/components/ui/segmented-control/SegmentedControl.svelte'
import Segment from '$lib/components/ui/segmented-control/Segment.svelte'
// Fetch weapon series list
const seriesQuery = createQuery(() => entityQueries.weaponSeriesList())
type SeriesType = 'weapons' | 'characters' | 'summons'
let activeType = $state<SeriesType>('weapons')
// Fetch all series lists
const weaponSeriesQuery = createQuery(() => entityQueries.weaponSeriesList())
const characterSeriesQuery = createQuery(() => entityQueries.characterSeriesList())
const summonSeriesQuery = createQuery(() => entityQueries.summonSeriesList())
// Get active query based on selected type
const activeQuery = $derived.by(() => {
switch (activeType) {
case 'weapons':
return weaponSeriesQuery
case 'characters':
return characterSeriesQuery
case 'summons':
return summonSeriesQuery
}
})
// Get sorted data
const sortedData = $derived.by(() => {
if (!activeQuery.data) return []
return [...activeQuery.data].sort((a, b) => a.order - b.order)
})
// Check if the current type has flags (only weapons)
const hasFlags = $derived(activeType === 'weapons')
</script>
<div class="database-page">
<div class="grid-container">
{#if seriesQuery.isPending}
<div class="loading">Loading weapon series...</div>
{:else if seriesQuery.error}
<div class="error">Failed to load weapon series</div>
{:else if seriesQuery.data}
<nav class="series-nav" aria-label="Series type">
<SegmentedControl bind:value={activeType} variant="blended" size="small">
<Segment value="weapons">Weapons</Segment>
<Segment value="characters">Characters</Segment>
<Segment value="summons">Summons</Segment>
</SegmentedControl>
</nav>
{#if activeQuery.isPending}
<div class="loading">Loading {activeType} series...</div>
{:else if activeQuery.error}
<div class="error">Failed to load {activeType} series</div>
{:else if sortedData.length > 0}
<div class="series-table">
<table>
<thead>
@ -23,28 +60,34 @@
<th class="name">Name (EN)</th>
<th class="name-ja">Name (JA)</th>
<th class="slug">Slug</th>
<th class="flags">Flags</th>
{#if hasFlags}
<th class="flags">Flags</th>
{/if}
</tr>
</thead>
<tbody>
{#each seriesQuery.data.sort((a, b) => a.order - b.order) as series (series.id)}
{#each sortedData as series (series.id)}
<tr>
<td class="order">{series.order}</td>
<td class="name">{series.name.en}</td>
<td class="name-ja">{series.name.ja}</td>
<td class="slug"><code>{series.slug}</code></td>
<td class="flags">
{#if series.extra}<span class="flag extra">Extra</span>{/if}
{#if series.elementChangeable}<span class="flag element">Element</span>{/if}
{#if series.hasWeaponKeys}<span class="flag keys">Keys</span>{/if}
{#if series.hasAwakening}<span class="flag awaken">Awaken</span>{/if}
{#if series.hasAxSkills}<span class="flag ax">AX</span>{/if}
</td>
{#if hasFlags && 'extra' in series}
<td class="flags">
{#if series.extra}<span class="flag extra">Extra</span>{/if}
{#if series.elementChangeable}<span class="flag element">Element</span>{/if}
{#if series.hasWeaponKeys}<span class="flag keys">Keys</span>{/if}
{#if series.hasAwakening}<span class="flag awaken">Awaken</span>{/if}
{#if series.hasAxSkills}<span class="flag ax">AX</span>{/if}
</td>
{/if}
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<div class="empty">No {activeType} series found</div>
{/if}
</div>
</div>
@ -69,8 +112,17 @@
overflow: hidden;
}
.series-nav {
display: flex;
align-items: center;
gap: spacing.$unit-2x;
padding: spacing.$unit-2x;
border-bottom: 1px solid var(--border-subtle);
}
.loading,
.error {
.error,
.empty {
padding: spacing.$unit-4x;
text-align: center;
color: colors.$grey-50;
@ -100,8 +152,6 @@
font-weight: typography.$medium;
font-size: typography.$font-small;
color: colors.$grey-40;
text-transform: uppercase;
letter-spacing: 0.5px;
}
td {
@ -114,7 +164,7 @@
}
.name {
min-width: 280px;
min-width: 200px;
}
.name-ja {
@ -144,7 +194,15 @@
}
&.element {
background: linear-gradient(to right, #fecaca, #fef08a, #bbf7d0, #bfdbfe, #e9d5ff, #fbcfe8);
background: linear-gradient(
to right,
#fecaca,
#fef08a,
#bbf7d0,
#bfdbfe,
#e9d5ff,
#fbcfe8
);
color: #374151;
}