feat(pokemon): remove manual sorting and enforce ID-based order

Remove pokemon.order permission and related API endpoints
Update queries to sort Pokemon by internal ID ascending
Replace reorderable list with standard list in Admin view
This commit is contained in:
2026-05-06 22:35:46 +08:00
parent df78685dc3
commit 82f08c1684
6 changed files with 24 additions and 69 deletions

View File

@@ -1460,7 +1460,6 @@ export const api = {
updatePokemon: (id: string | number, payload: PokemonPayload) =>
sendJson<PokemonDetail>(`/api/pokemon/${id}`, 'PUT', payload),
deletePokemon: (id: string | number) => deleteJson(`/api/pokemon/${id}`),
reorderPokemon: (ids: number[]) => sendJson<Pokemon[]>('/api/admin/pokemon/order', 'PUT', { ids }),
habitats: (params: Record<string, string | number | boolean | undefined> = {}) =>
getJson<Habitat[]>(`/api/habitats${buildQuery(params)}`),
habitatsPage: (params: PublicListQueryParams = {}) =>

View File

@@ -156,7 +156,7 @@ const adminNavigationGroups = computed<AdminNavGroup[]>(() => {
label: t('pages.admin.contentGroup'),
items: [
{ key: 'checklist', label: t('pages.admin.checklist'), permission: ['checklist.create', 'checklist.update', 'checklist.delete', 'checklist.order'] },
{ key: 'pokemon', label: t('pages.admin.pokemonList'), permission: ['pokemon.order', 'pokemon.delete'] },
{ key: 'pokemon', label: t('pages.admin.pokemonList'), permission: 'pokemon.delete' },
{ key: 'items', label: t('pages.admin.itemList'), permission: ['items.order', 'items.delete'] },
{
key: 'ancientArtifacts',
@@ -502,8 +502,6 @@ const languageKey = (item: Language) => item.code;
const languageLabel = (item: Language) => item.name;
const configKey = (item: EditableConfig) => item.id;
const configLabel = (item: EditableConfig) => item.name;
const pokemonKey = (item: Pokemon) => item.id;
const pokemonLabel = (item: Pokemon) => `#${item.displayId} ${item.name}`;
const itemKey = (item: Item) => item.id;
const itemLabel = (item: Item) => item.name;
const ancientArtifactKey = (item: AncientArtifact) => item.id;
@@ -932,10 +930,6 @@ function previewConfigOrder(rows: EditableConfig[]) {
configRows.value = rows;
}
function previewPokemonOrder(rows: Pokemon[]) {
pokemonRows.value = rows;
}
function previewItemOrder(rows: Item[]) {
itemRows.value = rows;
}
@@ -1004,18 +998,6 @@ async function persistConfigOrder(nextRows: EditableConfig[], fallbackRows: Edit
});
}
async function persistPokemonOrder(nextRows: Pokemon[], fallbackRows: Pokemon[]) {
pokemonRows.value = nextRows;
await run(async () => {
try {
pokemonRows.value = await api.reorderPokemon(nextRows.map((item) => item.id));
} catch (error) {
pokemonRows.value = fallbackRows;
throw error;
}
});
}
async function persistItemOrder(nextRows: Item[], fallbackRows: Item[]) {
itemRows.value = nextRows;
await run(async () => {
@@ -2319,20 +2301,8 @@ onMounted(() => {
<section v-else-if="canEdit && activeTab === 'pokemon'" class="detail-section">
<h2>{{ t('pages.admin.pokemonList') }}</h2>
<ReorderableList
v-if="pokemonRows.length"
:items="pokemonRows"
:item-key="pokemonKey"
:item-label="pokemonLabel"
list-key-prefix="pokemon"
:disabled="busy || !can('pokemon.order')"
:handle-label="dragSortLabel"
:handle-title="t('pages.admin.dragSortTitle')"
@preview="previewPokemonOrder"
@cancel="previewPokemonOrder"
@reorder="persistPokemonOrder"
>
<template #default="{ item }">
<ul v-if="pokemonRows.length" class="row-list">
<li v-for="item in pokemonRows" :key="item.id">
<RouterLink :to="`/pokemon/${item.id}`">#{{ item.displayId }} {{ item.name }}</RouterLink>
<span class="row-actions">
<button v-if="can('pokemon.delete')" type="button" :disabled="busy" @click="removePokemon(item.id)">
@@ -2340,8 +2310,8 @@ onMounted(() => {
{{ t('common.delete') }}
</button>
</span>
</template>
</ReorderableList>
</li>
</ul>
<p v-else class="meta-line">{{ t('common.noRecords') }}</p>
</section>