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"> <script lang="ts">
import { createQuery } from '@tanstack/svelte-query' import { createQuery } from '@tanstack/svelte-query'
import { entityQueries } from '$lib/api/queries/entity.queries' 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 type SeriesType = 'weapons' | 'characters' | 'summons'
const seriesQuery = createQuery(() => entityQueries.weaponSeriesList())
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> </script>
<div class="database-page"> <div class="database-page">
<div class="grid-container"> <div class="grid-container">
{#if seriesQuery.isPending} <nav class="series-nav" aria-label="Series type">
<div class="loading">Loading weapon series...</div> <SegmentedControl bind:value={activeType} variant="blended" size="small">
{:else if seriesQuery.error} <Segment value="weapons">Weapons</Segment>
<div class="error">Failed to load weapon series</div> <Segment value="characters">Characters</Segment>
{:else if seriesQuery.data} <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"> <div class="series-table">
<table> <table>
<thead> <thead>
@ -23,28 +60,34 @@
<th class="name">Name (EN)</th> <th class="name">Name (EN)</th>
<th class="name-ja">Name (JA)</th> <th class="name-ja">Name (JA)</th>
<th class="slug">Slug</th> <th class="slug">Slug</th>
<th class="flags">Flags</th> {#if hasFlags}
<th class="flags">Flags</th>
{/if}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each seriesQuery.data.sort((a, b) => a.order - b.order) as series (series.id)} {#each sortedData as series (series.id)}
<tr> <tr>
<td class="order">{series.order}</td> <td class="order">{series.order}</td>
<td class="name">{series.name.en}</td> <td class="name">{series.name.en}</td>
<td class="name-ja">{series.name.ja}</td> <td class="name-ja">{series.name.ja}</td>
<td class="slug"><code>{series.slug}</code></td> <td class="slug"><code>{series.slug}</code></td>
<td class="flags"> {#if hasFlags && 'extra' in series}
{#if series.extra}<span class="flag extra">Extra</span>{/if} <td class="flags">
{#if series.elementChangeable}<span class="flag element">Element</span>{/if} {#if series.extra}<span class="flag extra">Extra</span>{/if}
{#if series.hasWeaponKeys}<span class="flag keys">Keys</span>{/if} {#if series.elementChangeable}<span class="flag element">Element</span>{/if}
{#if series.hasAwakening}<span class="flag awaken">Awaken</span>{/if} {#if series.hasWeaponKeys}<span class="flag keys">Keys</span>{/if}
{#if series.hasAxSkills}<span class="flag ax">AX</span>{/if} {#if series.hasAwakening}<span class="flag awaken">Awaken</span>{/if}
</td> {#if series.hasAxSkills}<span class="flag ax">AX</span>{/if}
</td>
{/if}
</tr> </tr>
{/each} {/each}
</tbody> </tbody>
</table> </table>
</div> </div>
{:else}
<div class="empty">No {activeType} series found</div>
{/if} {/if}
</div> </div>
</div> </div>
@ -69,8 +112,17 @@
overflow: hidden; 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, .loading,
.error { .error,
.empty {
padding: spacing.$unit-4x; padding: spacing.$unit-4x;
text-align: center; text-align: center;
color: colors.$grey-50; color: colors.$grey-50;
@ -100,8 +152,6 @@
font-weight: typography.$medium; font-weight: typography.$medium;
font-size: typography.$font-small; font-size: typography.$font-small;
color: colors.$grey-40; color: colors.$grey-40;
text-transform: uppercase;
letter-spacing: 0.5px;
} }
td { td {
@ -114,7 +164,7 @@
} }
.name { .name {
min-width: 280px; min-width: 200px;
} }
.name-ja { .name-ja {
@ -144,7 +194,15 @@
} }
&.element { &.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; color: #374151;
} }