From d73438dd298644ebab24aaf4337b4cd66fc4f3f4 Mon Sep 17 00:00:00 2001 From: chris Date: Tue, 8 Sep 2026 10:28:27 -0400 Subject: [PATCH] MovesList: order the TM/HM group by TM number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The learnset's "By TM / HM" group was alphabetical. TM numbers aren't in the snapshot — they resolve lazily per move via /machine/{id}, which the group's enrichers already fetch on expand. So: await those resolutions (fillTm is now async and stashes the label on the move), and once the whole group is enriched, re-append the rows in TM/HM/TR-then-number order — TM01, TM02 … HM01 …, matching the in-game list. Verified against Charizard in FireRed/LeafGreen. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu --- README.md | 3 ++- src/components/MovesList.js | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 24b8b5a..e855fb2 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,8 @@ Working app with a type-themed UI: Moves / Locations); coloured animated stat bars; defensive type matchups; evolution chain re-parented to the selected game's generation; learnset with per-move power/type/accuracy/PP/effect (era-accurate via `past_values`, - incl. pre-Gen-4 physical/special-by-type); wild encounter locations. + incl. pre-Gen-4 physical/special-by-type), the TM/HM group ordered by + TM number for the selected game; wild encounter locations. - **Game-aware** — abilities gated to Gen 3+ (hidden to Gen 5+); type chart applies Gen 1 / pre-Gen 6 rules. - **Games** — overlay picker with stylised version-colour cover tiles, diff --git a/src/components/MovesList.js b/src/components/MovesList.js index 04df0c8..ec7b211 100644 --- a/src/components/MovesList.js +++ b/src/components/MovesList.js @@ -27,6 +27,15 @@ const METHOD_LABEL = { 'form-change': 'On form change', }; const METHOD_ORDER = ['level-up', 'egg', 'machine', 'tutor', 'form-change']; + +/** Numeric sort key from a TM/HM/TR label like "TM25": TMs, then HMs, then TRs. */ +function tmSortKey(label) { + if (!label) return 1e9; // not resolved yet -> sink to the bottom + const m = String(label).match(/^([A-Z]+)0*(\d+)$/); + if (!m) return 1e9 - 1; + const rank = { TM: 0, HM: 1, TR: 2 }[m[1]] ?? 3; + return rank * 1000 + Number(m[2]); +} const DAMAGE_CLASS = { physical: 'Phys', special: 'Spec', status: 'Stat' }; const idFromUrl = (u) => Number(u.replace(/\/$/, '').split('/').pop()); @@ -141,11 +150,12 @@ export function MovesList(pokemonMoves, { versionGroupKey, gen = 9, genOfVg = () const tmCell = method === 'machine' ? el('span', { class: 'moverow__tm' }) : null; let bodyFilled = false; - const fillTm = () => { - if (tmCell && !tmCell.textContent && m.data) { - machineNumber(m.data, versionGroupKey).then((n) => { - if (n) tmCell.textContent = n; - }); + const fillTm = async () => { + if (!tmCell || m._tm != null || !m.data) return; + const n = await machineNumber(m.data, versionGroupKey); + if (n) { + m._tm = n; + tmCell.textContent = n; } }; @@ -167,7 +177,7 @@ export function MovesList(pokemonMoves, { versionGroupKey, gen = 9, genOfVg = () const v = forGeneration(m.data, gen, genOfVg); fillMeta(meta, v); fillBody(body, m.data, v); - fillTm(); + await fillTm(); } catch { body.replaceChildren(el('span', { class: 'moverow__pending' }, 'Details unavailable.')); } @@ -182,13 +192,15 @@ export function MovesList(pokemonMoves, { versionGroupKey, gen = 9, genOfVg = () el('span', { class: 'moverow__chev', 'aria-hidden': 'true' }, '▾'), ); - list.append(el('div', { class: 'movecard' }, row, body)); + const card = el('div', { class: 'movecard' }, row, body); + m._card = card; + list.append(card); enrichers.push(async () => { try { m.data = m.data || (await getMove(m.id)); fillMeta(meta, forGeneration(m.data, gen, genOfVg)); - fillTm(); + await fillTm(); } catch { meta.replaceChildren(el('span', { class: 'moverow__pending' }, '—')); } @@ -212,6 +224,14 @@ export function MovesList(pokemonMoves, { versionGroupKey, gen = 9, genOfVg = () if (enriched) return; enriched = true; await mapLimit(enrichers, 6, (fn) => fn()); + // TM/HM moves land in whatever order the API returned them; reorder + // to TM01, TM02 … once every number has resolved. + if (method === 'machine') { + moves + .slice() + .sort((a, b) => tmSortKey(a._tm) - tmSortKey(b._tm) || a.name.localeCompare(b.name)) + .forEach((mm) => list.append(mm._card)); + } }; group.addEventListener('toggle', () => group.open && runEnrich()); if (method === 'level-up') runEnrich();