health: smart-scale columns, deduped body measurement imports, quick-add form
All checks were successful
Deploy production / deploy (push) Successful in 2m32s
All checks were successful
Deploy production / deploy (push) Successful in 2m32s
This commit is contained in:
@@ -1,4 +1,14 @@
|
||||
import { check, date, index, integer, numeric, text, timestamp, uuid } from 'drizzle-orm/pg-core';
|
||||
import {
|
||||
check,
|
||||
date,
|
||||
index,
|
||||
integer,
|
||||
numeric,
|
||||
text,
|
||||
timestamp,
|
||||
uniqueIndex,
|
||||
uuid
|
||||
} from 'drizzle-orm/pg-core';
|
||||
import { sql } from 'drizzle-orm';
|
||||
import { healthSchema } from './schemas';
|
||||
import { timestamps, timestamptz } from './helpers';
|
||||
@@ -42,11 +52,25 @@ export const healthBodyMeasurements = healthSchema.table(
|
||||
weightKg: numeric('weight_kg', { precision: 5, scale: 2, mode: 'number' }),
|
||||
waistCm: numeric('waist_cm', { precision: 5, scale: 1, mode: 'number' }), // at the navel
|
||||
bodyFatPct: numeric('body_fat_pct', { precision: 4, scale: 1, mode: 'number' }),
|
||||
// Optional smart-scale (BIA) readings, e.g. Renpho.
|
||||
muscleMassKg: numeric('muscle_mass_kg', { precision: 5, scale: 2, mode: 'number' }),
|
||||
skeletalMuscleKg: numeric('skeletal_muscle_kg', { precision: 5, scale: 2, mode: 'number' }),
|
||||
boneMassKg: numeric('bone_mass_kg', { precision: 4, scale: 2, mode: 'number' }),
|
||||
visceralFat: numeric('visceral_fat', { precision: 4, scale: 1, mode: 'number' }), // scale's index
|
||||
bodyWaterPct: numeric('body_water_pct', { precision: 4, scale: 1, mode: 'number' }),
|
||||
proteinPct: numeric('protein_pct', { precision: 4, scale: 1, mode: 'number' }),
|
||||
bmrKcal: integer('bmr_kcal'),
|
||||
bmi: numeric('bmi', { precision: 4, scale: 1, mode: 'number' }),
|
||||
measuredAt: timestamptz('measured_at'), // exact moment of the reading, when known
|
||||
source: text('source'), // e.g. "Renpho", "manual"
|
||||
notes: text('notes'),
|
||||
...timestamps
|
||||
},
|
||||
(t) => [
|
||||
index('body_measurements_date_idx').on(t.date),
|
||||
// Dedupe keys for repeat imports (see writeRows in #lib/server/health-import).
|
||||
uniqueIndex('body_measurements_date_weight_key').on(t.date, t.weightKg),
|
||||
uniqueIndex('body_measurements_measured_at_key').on(t.measuredAt),
|
||||
check(
|
||||
'body_measurements_any_check',
|
||||
sql`${t.weightKg} IS NOT NULL OR ${t.waistCm} IS NOT NULL OR ${t.bodyFatPct} IS NOT NULL`
|
||||
@@ -63,6 +87,17 @@ export const healthBodyMeasurements = healthSchema.table(
|
||||
'body_measurements_fat_check',
|
||||
sql`${t.bodyFatPct} IS NULL OR ${t.bodyFatPct} BETWEEN 1 AND 75`
|
||||
),
|
||||
check(
|
||||
'body_measurements_scale_check',
|
||||
sql`(${t.muscleMassKg} IS NULL OR ${t.muscleMassKg} BETWEEN 5 AND 250)
|
||||
AND (${t.skeletalMuscleKg} IS NULL OR ${t.skeletalMuscleKg} BETWEEN 5 AND 200)
|
||||
AND (${t.boneMassKg} IS NULL OR ${t.boneMassKg} BETWEEN 0.5 AND 20)
|
||||
AND (${t.visceralFat} IS NULL OR ${t.visceralFat} BETWEEN 1 AND 60)
|
||||
AND (${t.bodyWaterPct} IS NULL OR ${t.bodyWaterPct} BETWEEN 20 AND 85)
|
||||
AND (${t.proteinPct} IS NULL OR ${t.proteinPct} BETWEEN 5 AND 40)
|
||||
AND (${t.bmrKcal} IS NULL OR ${t.bmrKcal} BETWEEN 500 AND 6000)
|
||||
AND (${t.bmi} IS NULL OR ${t.bmi} BETWEEN 10 AND 80)`
|
||||
),
|
||||
check('body_measurements_date_check', sane('date'))
|
||||
]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user