@@ -74,6 +74,19 @@ function formatRollingLabel(start: Date, end: Date): string {
7474 return `${ formatter . format ( start ) } to ${ formatter . format ( end ) } ` ;
7575}
7676
77+ /**
78+ * Resolves a {@link DashboardPeriod} from a loose set of URL search-param inputs.
79+ *
80+ * Resolution priority (first match wins):
81+ * 1. **Custom range** — both `input.from` and `input.to` are valid ISO date strings.
82+ * 2. **Month** — `input.month` matches `YYYY-MM` and represents a valid calendar month.
83+ * 3. **Year** — `input.year` matches `YYYY` and falls within the range 2008–(now+5).
84+ * 4. **Rolling 12 months** — default fallback when none of the above match.
85+ *
86+ * @param {DashboardPeriodInput } input - Raw query-string values (year, month, from, to).
87+ * @param {Date } [now=new Date()] - Reference date used for the rolling-window default and year validation.
88+ * @returns {DashboardPeriod } A fully resolved period object with `kind`, `label`, `from`, and `to`.
89+ */
7790export function resolveDashboardPeriod (
7891 input : DashboardPeriodInput ,
7992 now : Date = new Date ( )
@@ -145,6 +158,22 @@ export function resolveDashboardPeriod(
145158 } ;
146159}
147160
161+ /**
162+ * Shifts a {@link DashboardPeriod} one step forwards or backwards.
163+ *
164+ * Shift semantics vary by period kind:
165+ * - **month** — moves to the previous or next calendar month.
166+ * - **year** — moves to the previous or next calendar year.
167+ * - **range** — shifts by the exact number of days spanned by the current range.
168+ * - **rolling** — shifts the 12-month window by one month in the requested direction.
169+ *
170+ * The function always delegates to {@link resolveDashboardPeriod} so that the returned
171+ * period is normalised and fully hydrated.
172+ *
173+ * @param {DashboardPeriod } period - The currently active period.
174+ * @param {'prev' | 'next' } direction - Direction to shift: `'prev'` for earlier, `'next'` for later.
175+ * @returns {DashboardPeriod } The shifted, fully resolved period.
176+ */
148177export function shiftDashboardPeriod (
149178 period : DashboardPeriod ,
150179 direction : 'prev' | 'next'
@@ -183,6 +212,18 @@ export function shiftDashboardPeriod(
183212 return resolveDashboardPeriod ( { from : shiftedFrom . toISOString ( ) , to : shiftedTo . toISOString ( ) } ) ;
184213}
185214
215+ /**
216+ * Serialises a {@link DashboardPeriod} into a `URLSearchParams` instance suitable for
217+ * appending to a dashboard URL.
218+ *
219+ * Serialisation strategy:
220+ * - **month** — emits a single `month=YYYY-MM` param.
221+ * - **year** — emits a single `year=YYYY` param.
222+ * - **range / rolling** — emits `from` and `to` ISO timestamp params.
223+ *
224+ * @param {DashboardPeriod } period - The period to serialise.
225+ * @returns {URLSearchParams } The query-string representation of the period.
226+ */
186227export function dashboardPeriodToSearchParams ( period : DashboardPeriod ) : URLSearchParams {
187228 const params = new URLSearchParams ( ) ;
188229
0 commit comments