@@ -10,7 +10,18 @@ import type { MicronutrientProfile } from "@/lib/micronutrients/types";
1010import type { ShoppingAisle } from "@/lib/shopping/categorize" ;
1111import { notifyDataChanged } from "@/lib/sync/data-bus" ;
1212import { type DBSchema , type IDBPDatabase , openDB } from "idb" ;
13- import type { DailyLog , Versioned , WeightEntry } from "@maqro/core/records" ;
13+ import type {
14+ BloodPressure ,
15+ BodyMeasurement ,
16+ CustomFood ,
17+ DailyLog ,
18+ MealTemplate ,
19+ PantryNotification ,
20+ Sortable ,
21+ Versioned ,
22+ WaterIntake ,
23+ WeightEntry ,
24+ } from "@maqro/core/records" ;
1425
1526const DB_NAME = "maqro" ;
1627const DB_VERSION = 18 ;
@@ -71,18 +82,21 @@ const PROFILE_KEY = "default";
7182 * literals (forms, mappers, tests) don't have to know about sync
7283 * internals; the saver functions in this file fill them in, and the
7384 * sync engine treats missing/null as "never synced". */
74- // `Versioned`, `DailyLog`, and `WeightEntry` now live in `@maqro/core/records`
75- // (shared with the native app). Imported above for this file's record types +
76- // the idb schema, and re-exported here so `@/lib/db` consumers are unchanged.
77- export type { DailyLog , Versioned , WeightEntry } ;
78-
79- /** Optional per-row position used by the "custom" sort mode in the
80- * My Foods / Recipes / Templates views. A `double precision` (number)
81- * rather than an integer so inserting between two rows is just the
82- * average of the neighbors' values - no renumber cascade. Nullable
83- * for rows the user hasn't manually positioned yet; those sort by
84- * `createdAt` as the fallback. */
85- export type Sortable = { sortOrder ?: number } ;
85+ // These persisted-record types now live in `@maqro/core/records` (shared with
86+ // the native app). Imported above for this file's schema + helpers, and
87+ // re-exported here so `@/lib/db` consumers are unchanged.
88+ export type {
89+ BloodPressure ,
90+ BodyMeasurement ,
91+ CustomFood ,
92+ DailyLog ,
93+ MealTemplate ,
94+ PantryNotification ,
95+ Sortable ,
96+ Versioned ,
97+ WaterIntake ,
98+ WeightEntry ,
99+ } ;
86100
87101/** Stores that the sync engine can push DELETEs to. Profile is
88102 * excluded (single-row per user; the only deletion is "delete
@@ -113,74 +127,6 @@ export type DeletionRecord = {
113127 deletedAt : number ;
114128} ;
115129
116- /** Stored custom food. Macros are per 100g; the id is a client-minted
117- * UUID so the same record can exist in IndexedDB and Supabase under the
118- * same key (no mapping needed for sync). createdAt drives most-recent
119- * ordering. */
120- export type CustomFood = Omit < Food , "id" | "source" > & {
121- id : string ;
122- createdAt : number ;
123- } & Versioned &
124- Sortable ;
125-
126- /** A reusable meal template - the user named some set of foods (e.g.
127- * "Greek yogurt bowl") and can apply it to any meal slot on any day. The
128- * `foods` array is captured with portions as-saved. Id is a client-minted
129- * UUID shared with Supabase. */
130- export type MealTemplate = {
131- id : string ;
132- name : string ;
133- foods : FoodItem [ ] ;
134- createdAt : number ;
135- /** Legacy ms-epoch timestamp. Still bumped on local writes so the
136- * existing list-sort ("most recently edited first") keeps working
137- * without a refactor - `localUpdatedAt` is the authoritative one
138- * for sync. */
139- updatedAt : number ;
140- } & Versioned &
141- Sortable ;
142-
143- /** A day's cumulative water intake in millilitres. Keyed by `YYYY-MM-DD`
144- * local date — one row per day, accumulated as the user logs (each tap
145- * adds to `ml`). Mirrors `WeightEntry`'s date-keyed, last-write-wins shape;
146- * the saver differs in that it reads-then-adds rather than overwriting. */
147- export type WaterIntake = {
148- date : string ;
149- ml : number ;
150- recordedAt : number ;
151- } & Versioned ;
152-
153- /** A single body-measurement entry - waist / neck / hips in cm, plus
154- * an optional free-form note. All circumferences optional so the
155- * user can log just what they have today; the Progress view skips
156- * derived metrics (body-fat estimate) when required inputs are
157- * missing. Keyed by `YYYY-MM-DD` like weighIns - most-recent
158- * measurement on a given day wins. */
159- export type BodyMeasurement = {
160- date : string ;
161- waistCm ?: number ;
162- neckCm ?: number ;
163- hipsCm ?: number ;
164- notes ?: string ;
165- recordedAt : number ;
166- } & Versioned ;
167-
168- /** A single blood-pressure reading - systolic / diastolic in mmHg, with
169- * an optional pulse (bpm) and free-form note. Both pressures are required
170- * (a reading is meaningless without the pair); pulse + notes are optional.
171- * Storage is always mmHg - there's no imperial variant for blood pressure,
172- * so unlike weight there's no unit conversion at the boundary. Keyed by
173- * `YYYY-MM-DD` like weigh-ins and body measurements - most-recent reading
174- * on a given day wins (multiple readings per day is a future enhancement). */
175- export type BloodPressure = {
176- date : string ;
177- systolic : number ;
178- diastolic : number ;
179- pulse ?: number ;
180- notes ?: string ;
181- recordedAt : number ;
182- } & Versioned ;
183-
184130/** One completed intermittent fast, archived on Stop / auto-finalize. Unlike
185131 * weigh-ins or BP this is **id-keyed**, not date-keyed: a fast can span
186132 * midnight and a user can run more than one in a day, so `(user, day)` is the
@@ -219,25 +165,6 @@ export type PantryItem = {
219165 updatedAt : number ;
220166} & Versioned ;
221167
222- /** A pantry notification — currently only the "low-stock" kind, fired
223- * when consuming a recipe pushes an item's quantity to/below the
224- * low-stock threshold. Synced so the bell badge + history stay
225- * consistent across the user's devices. `itemId` links back to the
226- * pantry row (kept as a plain field, not an FK, since the item may be
227- * edited/deleted independently and the notification is still a valid
228- * historical event). `read` toggles when the user opens the drawer. */
229- export type PantryNotification = {
230- id : string ;
231- type : "low-stock" ;
232- itemId : string ;
233- itemName : string ;
234- quantity : number ;
235- unit : string ;
236- read : boolean ;
237- createdAt : number ;
238- updatedAt : number ;
239- } & Versioned ;
240-
241168/** Per-item user override for the Shopping List view. Keyed by the
242169 * *lowercased* item name (matches the lowercased lookup keys
243170 * ShoppingListView builds), so the same physical food survives
0 commit comments