* Extended functionalities
* Added different UIs
This commit is contained in:
157
database/scripts/001_diet_tracking.sql
Normal file
157
database/scripts/001_diet_tracking.sql
Normal file
@@ -0,0 +1,157 @@
|
||||
-- DailyMeals diet tracking module
|
||||
-- Apply manually on PostgreSQL (database-first; EF does not run migrations).
|
||||
-- Schema: diet (same as existing recipe tables)
|
||||
--
|
||||
-- Inspired by patterns from MyFitnessPal / Lifesum (meal + macro logging),
|
||||
-- WaterMinder / Hydro Coach (hydration goals + quick-add volumes), and
|
||||
-- generic reminder schedules stored server-side for client push/local alarms.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Daily nutrition & hydration targets (one row per user)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS diet."UserDailyGoals" (
|
||||
"UserId" uuid PRIMARY KEY
|
||||
REFERENCES diet."AspNetUsers"("Id") ON DELETE CASCADE,
|
||||
"CalorieGoal" int NULL CHECK ("CalorieGoal" IS NULL OR "CalorieGoal" >= 0),
|
||||
"ProteinGoalG" numeric(6,2) NULL CHECK ("ProteinGoalG" IS NULL OR "ProteinGoalG" >= 0),
|
||||
"FatGoalG" numeric(6,2) NULL CHECK ("FatGoalG" IS NULL OR "FatGoalG" >= 0),
|
||||
"CarbsGoalG" numeric(6,2) NULL CHECK ("CarbsGoalG" IS NULL OR "CarbsGoalG" >= 0),
|
||||
"WaterGoalMl" int NULL CHECK ("WaterGoalMl" IS NULL OR "WaterGoalMl" > 0),
|
||||
"CreatedAt" timestamptz NOT NULL DEFAULT now(),
|
||||
"UpdatedAt" timestamptz NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE diet."UserDailyGoals" IS 'Per-user daily calorie, macro, and hydration targets (Lifesum-style goals).';
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Drink catalog (reference data; quick-add presets like WaterMinder)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS diet."DrinkCatalog" (
|
||||
"Id" serial PRIMARY KEY,
|
||||
"Code" varchar(32) NOT NULL UNIQUE,
|
||||
"Name" varchar(100) NOT NULL,
|
||||
"DefaultVolumeMl" int NOT NULL CHECK ("DefaultVolumeMl" > 0),
|
||||
"CaloriesPer100Ml" numeric(6,2) NULL CHECK ("CaloriesPer100Ml" IS NULL OR "CaloriesPer100Ml" >= 0),
|
||||
"IconEmoji" varchar(16) NULL,
|
||||
"SortOrder" int NOT NULL DEFAULT 0,
|
||||
"IsActive" boolean NOT NULL DEFAULT true
|
||||
);
|
||||
|
||||
COMMENT ON TABLE diet."DrinkCatalog" IS 'Preset drinks for one-tap logging (water, tea, coffee, etc.).';
|
||||
|
||||
INSERT INTO diet."DrinkCatalog" ("Code", "Name", "DefaultVolumeMl", "CaloriesPer100Ml", "IconEmoji", "SortOrder")
|
||||
VALUES
|
||||
('water', 'Water', 250, 0, '💧', 1),
|
||||
('tea', 'Tea', 200, 1, '🍵', 2),
|
||||
('coffee', 'Coffee', 150, 2, '☕', 3),
|
||||
('juice', 'Juice', 200, 45, '🧃', 4),
|
||||
('milk', 'Milk', 250, 42, '🥛', 5),
|
||||
('soda', 'Soft drink', 330, 42, '🥤', 6),
|
||||
('other', 'Other drink', 250, NULL, '🍶', 99)
|
||||
ON CONFLICT ("Code") DO NOTHING;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Logged meals (MyFitnessPal-style diary entries; optional recipe link)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS diet."MealConsumptions" (
|
||||
"Id" serial PRIMARY KEY,
|
||||
"UserId" uuid NOT NULL
|
||||
REFERENCES diet."AspNetUsers"("Id") ON DELETE CASCADE,
|
||||
"RecipeId" int NULL
|
||||
REFERENCES diet."Recipes"("Id") ON DELETE SET NULL,
|
||||
"MealCategory" int NOT NULL CHECK ("MealCategory" BETWEEN 0 AND 4),
|
||||
"LogDate" date NOT NULL,
|
||||
"ConsumedAt" timestamptz NOT NULL,
|
||||
"Name" varchar(255) NOT NULL,
|
||||
"Portions" numeric(4,2) NOT NULL DEFAULT 1 CHECK ("Portions" > 0),
|
||||
"Calories" int NULL CHECK ("Calories" IS NULL OR "Calories" >= 0),
|
||||
"ProteinG" numeric(6,2) NULL CHECK ("ProteinG" IS NULL OR "ProteinG" >= 0),
|
||||
"FatG" numeric(6,2) NULL CHECK ("FatG" IS NULL OR "FatG" >= 0),
|
||||
"CarbsG" numeric(6,2) NULL CHECK ("CarbsG" IS NULL OR "CarbsG" >= 0),
|
||||
"Notes" text NULL,
|
||||
"CreatedAt" timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
COMMENT ON TABLE diet."MealConsumptions" IS 'Meals the user ate; macros snapshotted at log time.';
|
||||
COMMENT ON COLUMN diet."MealConsumptions"."MealCategory" IS '0=Breakfast, 1=SecondBreakfast, 2=Lunch, 3=Dinner, 4=Snack';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_MealConsumptions_UserId_LogDate"
|
||||
ON diet."MealConsumptions" ("UserId", "LogDate" DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_MealConsumptions_UserId_ConsumedAt"
|
||||
ON diet."MealConsumptions" ("UserId", "ConsumedAt" DESC);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Logged drinks (water tracker entries)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS diet."DrinkConsumptions" (
|
||||
"Id" serial PRIMARY KEY,
|
||||
"UserId" uuid NOT NULL
|
||||
REFERENCES diet."AspNetUsers"("Id") ON DELETE CASCADE,
|
||||
"DrinkCatalogId" int NULL
|
||||
REFERENCES diet."DrinkCatalog"("Id") ON DELETE SET NULL,
|
||||
"LogDate" date NOT NULL,
|
||||
"ConsumedAt" timestamptz NOT NULL,
|
||||
"Name" varchar(255) NOT NULL,
|
||||
"VolumeMl" int NOT NULL CHECK ("VolumeMl" > 0),
|
||||
"Calories" int NULL CHECK ("Calories" IS NULL OR "Calories" >= 0),
|
||||
"CreatedAt" timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
COMMENT ON TABLE diet."DrinkConsumptions" IS 'Hydration and beverage intake log.';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_DrinkConsumptions_UserId_LogDate"
|
||||
ON diet."DrinkConsumptions" ("UserId", "LogDate" DESC);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Reminders (server-stored schedules; clients handle local notifications)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS diet."DietReminders" (
|
||||
"Id" serial PRIMARY KEY,
|
||||
"UserId" uuid NOT NULL
|
||||
REFERENCES diet."AspNetUsers"("Id") ON DELETE CASCADE,
|
||||
"ReminderType" int NOT NULL CHECK ("ReminderType" BETWEEN 0 AND 3),
|
||||
"Title" varchar(120) NOT NULL,
|
||||
"Message" varchar(500) NULL,
|
||||
"TimeOfDay" time NOT NULL,
|
||||
"DaysOfWeekMask" int NOT NULL DEFAULT 127 CHECK ("DaysOfWeekMask" BETWEEN 1 AND 127),
|
||||
"MealCategory" int NULL CHECK ("MealCategory" IS NULL OR "MealCategory" BETWEEN 0 AND 4),
|
||||
"IsEnabled" boolean NOT NULL DEFAULT true,
|
||||
"CreatedAt" timestamptz NOT NULL DEFAULT now(),
|
||||
"UpdatedAt" timestamptz NULL
|
||||
);
|
||||
|
||||
COMMENT ON TABLE diet."DietReminders" IS 'Meal/water/custom reminder schedules (bitmask: Sun=1, Mon=2, Tue=4, Wed=8, Thu=16, Fri=32, Sat=64).';
|
||||
COMMENT ON COLUMN diet."DietReminders"."ReminderType" IS '0=Water, 1=Meal, 2=Snack, 3=Custom';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_DietReminders_UserId_IsEnabled"
|
||||
ON diet."DietReminders" ("UserId", "IsEnabled");
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Optional views for reporting (API computes the same in LINQ)
|
||||
-- ---------------------------------------------------------------------------
|
||||
CREATE OR REPLACE VIEW diet."v_DailyMealTotals" AS
|
||||
SELECT
|
||||
"UserId",
|
||||
"LogDate",
|
||||
COALESCE(SUM("Calories"), 0)::int AS "TotalCalories",
|
||||
COALESCE(SUM("ProteinG"), 0) AS "TotalProteinG",
|
||||
COALESCE(SUM("FatG"), 0) AS "TotalFatG",
|
||||
COALESCE(SUM("CarbsG"), 0) AS "TotalCarbsG",
|
||||
COUNT(*)::int AS "MealCount"
|
||||
FROM diet."MealConsumptions"
|
||||
GROUP BY "UserId", "LogDate";
|
||||
|
||||
CREATE OR REPLACE VIEW diet."v_DailyDrinkTotals" AS
|
||||
SELECT
|
||||
"UserId",
|
||||
"LogDate",
|
||||
COALESCE(SUM("VolumeMl"), 0)::int AS "TotalWaterMl",
|
||||
COALESCE(SUM("Calories"), 0)::int AS "TotalDrinkCalories",
|
||||
COUNT(*)::int AS "DrinkCount"
|
||||
FROM diet."DrinkConsumptions"
|
||||
GROUP BY "UserId", "LogDate";
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user