56 lines
2.3 KiB
TypeScript
56 lines
2.3 KiB
TypeScript
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
|
|
})
|
|
}
|