mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
A forecast period was one all-day event over every day it might fall on, so a period of a few days showed up as a week-long estimate next to the logged ones. Each feed now carries a forecast style: - EXACT: the calculated period only, from the most likely start for the predicted number of bleeding days. - MARGIN: that event, plus separate "possible" events for the days it may start earlier and the days it may still run on, each only where the band reaches that side. Discreet titles use an open dot for them. - BAND: the single range, unchanged. Migration 0495 adds the column with BAND as its default, so every live feed keeps the events it serves. A feed turned on from now on starts on MARGIN, set by the mint route. PATCH changes it, rotate copies it, the status and the audit diff carry it, and the settings card offers it with a one-line explanation of the chosen style. The horizon and its stop rule are the same in every style, and the period event keeps its UID across styles so a calendar updates it in place.
56 lines
1.8 KiB
TypeScript
56 lines
1.8 KiB
TypeScript
/**
|
|
* The cycle calendar feed's request contract (#1350).
|
|
*
|
|
* Only the options are writable. The token, the record and the carrier are
|
|
* never body fields: the record comes from the resolved session, the carrier
|
|
* is the actor, and the token is minted by the server.
|
|
*/
|
|
import { z } from "zod/v4";
|
|
|
|
/** The feed's title modes. Mirrors `CycleCalendarFeedTitleMode`. */
|
|
export const cycleFeedTitleModeEnum = z.enum(["DISCREET", "DESCRIPTIVE"]);
|
|
|
|
/** How a forecast period is drawn. Mirrors `CycleCalendarFeedForecastStyle`. */
|
|
export const cycleFeedForecastStyleEnum = z.enum(["EXACT", "MARGIN", "BAND"]);
|
|
|
|
/**
|
|
* The style a newly minted feed starts with. The column's own default is BAND,
|
|
* which keeps every feed minted before the option on the events it had; a new
|
|
* one starts with the calculated days and their margin drawn apart.
|
|
*/
|
|
export const NEW_FEED_FORECAST_STYLE: z.infer<
|
|
typeof cycleFeedForecastStyleEnum
|
|
> = "MARGIN";
|
|
|
|
/** Forecast cycles ahead. The feed caps itself further by band width. */
|
|
export const FEED_HORIZON_MIN = 1;
|
|
export const FEED_HORIZON_MAX = 6;
|
|
/** Observed cycles included as history. */
|
|
export const FEED_HISTORY_MIN = 0;
|
|
export const FEED_HISTORY_MAX = 12;
|
|
|
|
export const cycleFeedOptionsPatchSchema = z
|
|
.object({
|
|
horizonCycles: z
|
|
.number()
|
|
.int()
|
|
.min(FEED_HORIZON_MIN)
|
|
.max(FEED_HORIZON_MAX)
|
|
.optional(),
|
|
historyCycles: z
|
|
.number()
|
|
.int()
|
|
.min(FEED_HISTORY_MIN)
|
|
.max(FEED_HISTORY_MAX)
|
|
.optional(),
|
|
includeFertile: z.boolean().optional(),
|
|
titleMode: cycleFeedTitleModeEnum.optional(),
|
|
forecastStyle: cycleFeedForecastStyleEnum.optional(),
|
|
})
|
|
.strict()
|
|
.refine((v) => Object.keys(v).length > 0, {
|
|
message: "At least one option is required",
|
|
});
|
|
|
|
export type CycleFeedOptionsPatch = z.infer<typeof cycleFeedOptionsPatchSchema>;
|