import type { MonthStat } from '@/api/stats' /** * Pure derived-stat helpers for the Stats page (Task 6). * * Extracted from {@link Stats.vue} so the two pieces of trivia that are easy * to get wrong — (1) finding the current month's count in a DESC-ordered list * and (2) flipping that list to chronological ASC for the line chart — are * unit-testable without mounting the component or stubbing ECharts. */ /** * Look up the inquiry count for a given `YYYY-MM` month in the `monthly` list. * * Used by Stats.vue for the "本月新增" card: it passes * `dayjs().format('YYYY-MM')` and we return the matching count, or `0` when * there's no data for the current month yet (the backend omits zero-count * months entirely, and a fresh month may not have appeared in the trailing * 12-month window at all). * * The lookup is by value equality on `ym`, so input order (DESC vs ASC) is * irrelevant. Returns `0` for an empty list — graceful fallback for an empty * DB / new install. */ export function currentMonthCount( monthly: readonly MonthStat[], ym: string, ): number { // `find` rather than indexing `[0]` — the current month is not guaranteed to // be the first entry (DESC newest-first only covers months that have data, // and a brand-new month may be ABSENT from the trailing 12-month window). const hit = monthly.find((m) => m.ym === ym) return hit?.count ?? 0 } /** * Return a new array of monthly stats sorted **ascending** by `ym` * (chronological order — what the trend line chart needs). * * The backend returns `monthly` **DESC** (newest first). The line chart's X * axis wants oldest → newest, so this flips the order. A fresh copy is always * returned (the input is never mutated), even when the input is already ASC — * callers can safely pass a `readonly` slice from the API response. * * String comparison on `YYYY-MM` is lexicographically correct (zero-padded * fixed-width format), so no Date parsing is needed. */ export function sortMonthlyAsc(monthly: readonly MonthStat[]): MonthStat[] { // Slice first so `.sort` cannot reorder the caller's array — important // because `monthly` may be the live API response object. return monthly.slice().sort((a, b) => { if (a.ym !== b.ym) return a.ym < b.ym ? -1 : 1 return 0 }) }