Tauri 2 + pure JS + SQLite personal health tracking app. Nutrition module: - 9299 products in DB (Magnit SSR scraping + KDV) - Product search with case-insensitive Cyrillic (name_lower column) - Food logging from product DB or manual entry - Supplement tracking with per-pill micronutrients - Micronutrient % strip on Today screen Fitness/GPS module: - FitoTrack .ftb and GPX import with seq-based ordering - Session detail view: map, speed/elevation charts (Chart.js) - Offline tile caching (IndexedDB) with region download - Track rendering with colored time-gradient points UI: - Fullscreen modals with back-button (history API) - Dark theme, desktop-responsive layout - 5 tabs: Today, Products, Track, Supplements, Profile Tools: - Magnit/KDV HTML parsers - Dedup import with discrepancy detection - FitoTrack backup analysis
492 lines
18 KiB
JavaScript
492 lines
18 KiB
JavaScript
// Database layer — talks to tauri-plugin-sql via raw Tauri IPC.
|
|
// No imports, no npm. window.__TAURI__ is injected by Tauri (withGlobalTauri: true).
|
|
// The DB is preloaded at startup via tauri.conf.json plugins.sql.preload.
|
|
|
|
const DB_PATH = "sqlite:baldav.db";
|
|
|
|
function inv(cmd, args) {
|
|
return window.__TAURI__.core.invoke(`plugin:sql|${cmd}`, args);
|
|
}
|
|
|
|
async function execute(query, params) {
|
|
return inv("execute", { db: DB_PATH, query, values: params ?? [] });
|
|
}
|
|
|
|
async function select(query, params) {
|
|
return inv("select", { db: DB_PATH, query, values: params ?? [] });
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Profile (key-value store)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function getProfileValue(key) {
|
|
const rows = await select("SELECT value FROM profile WHERE key = ?1", [key]);
|
|
return rows.length ? rows[0].value : null;
|
|
}
|
|
|
|
async function setProfileValue(key, value) {
|
|
await execute(
|
|
"INSERT OR REPLACE INTO profile (key, value) VALUES (?1, ?2)",
|
|
[key, String(value)]
|
|
);
|
|
}
|
|
|
|
async function getFullProfile() {
|
|
const rows = await select("SELECT key, value FROM profile");
|
|
const p = {};
|
|
for (const r of rows) p[r.key] = r.value;
|
|
return p;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Weight log
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function addWeight(date, time, kg) {
|
|
await execute(
|
|
"INSERT INTO weight_log (date, time, weight_kg) VALUES (?1, ?2, ?3)",
|
|
[date, time, kg]
|
|
);
|
|
}
|
|
|
|
async function deleteWeight(id) {
|
|
await execute("DELETE FROM weight_log WHERE id = ?1", [id]);
|
|
}
|
|
|
|
async function getWeightsForDate(date) {
|
|
return select("SELECT * FROM weight_log WHERE date = ?1 ORDER BY time ASC", [date]);
|
|
}
|
|
|
|
async function getLatestWeight() {
|
|
const rows = await select(
|
|
"SELECT * FROM weight_log ORDER BY date DESC, time DESC LIMIT 1"
|
|
);
|
|
return rows.length ? rows[0] : null;
|
|
}
|
|
|
|
async function getRecentWeights(days) {
|
|
return select(
|
|
`SELECT date, MIN(weight_kg) as weight_kg
|
|
FROM weight_log
|
|
WHERE date >= date('now', ?1)
|
|
GROUP BY date ORDER BY date ASC`,
|
|
[`-${days ?? 30} days`]
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Sleep log
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function getSleepForDate(date) {
|
|
const rows = await select("SELECT * FROM sleep_log WHERE date = ?1", [date]);
|
|
return rows.length ? rows[0] : null;
|
|
}
|
|
|
|
async function saveSleep(date, bedTime, asleepTime, wakeTime, napMinutes, notes) {
|
|
const existing = await getSleepForDate(date);
|
|
if (existing) {
|
|
await execute(
|
|
`UPDATE sleep_log SET bed_time=?1, asleep_time=?2, wake_time=?3,
|
|
nap_minutes=?4, notes=?5 WHERE date=?6`,
|
|
[bedTime, asleepTime, wakeTime, napMinutes ?? 0, notes ?? null, date]
|
|
);
|
|
} else {
|
|
await execute(
|
|
`INSERT INTO sleep_log (date, bed_time, asleep_time, wake_time, nap_minutes, notes)
|
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6)`,
|
|
[date, bedTime, asleepTime, wakeTime, napMinutes ?? 0, notes ?? null]
|
|
);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Products
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function searchProducts(query, limit) {
|
|
const q = query.toLowerCase();
|
|
return select(
|
|
`SELECT id, name, brand, category, weight_g, kcal_per_100g,
|
|
protein_per_100g, fat_per_100g, carbs_per_100g, fiber_per_100g,
|
|
composition
|
|
FROM products
|
|
WHERE name_lower LIKE ?1
|
|
GROUP BY COALESCE(store_id, id)
|
|
ORDER BY
|
|
CASE WHEN name_lower LIKE ?1 THEN 0 ELSE 1 END,
|
|
name COLLATE NOCASE
|
|
LIMIT ?2`,
|
|
[`%${q}%`, limit ?? 30]
|
|
);
|
|
}
|
|
|
|
async function getProduct(id) {
|
|
const rows = await select("SELECT * FROM products WHERE id = ?1", [id]);
|
|
return rows.length ? rows[0] : null;
|
|
}
|
|
|
|
async function addProduct(p) {
|
|
const r = await execute(
|
|
`INSERT INTO products
|
|
(name, brand, category, weight_g, kcal_per_100g, protein_per_100g,
|
|
fat_per_100g, carbs_per_100g, fiber_per_100g,
|
|
vit_a_mcg, vit_c_mg, vit_d_mcg, vit_e_mg, vit_k_mcg,
|
|
vit_b1_mg, vit_b2_mg, vit_b3_mg, vit_b6_mg, vit_b12_mcg, folate_mcg,
|
|
calcium_mg, iron_mg, magnesium_mg, zinc_mg, copper_mg,
|
|
selenium_mcg, potassium_mg, sodium_mg, source)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29)`,
|
|
[
|
|
p.name, p.brand ?? null, p.category ?? null, p.weight_g ?? null,
|
|
p.kcal_per_100g ?? null, p.protein_per_100g ?? null,
|
|
p.fat_per_100g ?? null, p.carbs_per_100g ?? null, p.fiber_per_100g ?? null,
|
|
p.vit_a_mcg ?? null, p.vit_c_mg ?? null, p.vit_d_mcg ?? null,
|
|
p.vit_e_mg ?? null, p.vit_k_mcg ?? null,
|
|
p.vit_b1_mg ?? null, p.vit_b2_mg ?? null, p.vit_b3_mg ?? null,
|
|
p.vit_b6_mg ?? null, p.vit_b12_mcg ?? null, p.folate_mcg ?? null,
|
|
p.calcium_mg ?? null, p.iron_mg ?? null, p.magnesium_mg ?? null,
|
|
p.zinc_mg ?? null, p.copper_mg ?? null,
|
|
p.selenium_mcg ?? null, p.potassium_mg ?? null, p.sodium_mg ?? null,
|
|
p.source ?? "manual",
|
|
]
|
|
);
|
|
return r.lastInsertId;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Food log
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function getFoodForDate(date) {
|
|
return select(
|
|
`SELECT fl.*, p.name as product_name, p.brand as product_brand,
|
|
r.name as recipe_name
|
|
FROM food_log fl
|
|
LEFT JOIN products p ON fl.product_id = p.id
|
|
LEFT JOIN recipes r ON fl.recipe_id = r.id
|
|
WHERE fl.date = ?1 ORDER BY fl.time ASC`,
|
|
[date]
|
|
);
|
|
}
|
|
|
|
async function addFoodManual(date, time, desc, kcal) {
|
|
await execute(
|
|
"INSERT INTO food_log (date, time, note, amount_g, kcal) VALUES (?1,?2,?3,0,?4)",
|
|
[date, time, desc, kcal ?? null]
|
|
);
|
|
}
|
|
|
|
async function addFoodEntry(date, time, productId, amountG, note) {
|
|
let kcal = null, protein = null, fat = null, carbs = null, fiber = null;
|
|
if (productId) {
|
|
const p = await getProduct(productId);
|
|
if (p && p.kcal_per_100g != null) {
|
|
const f = amountG / 100;
|
|
kcal = Math.round((p.kcal_per_100g ?? 0) * f);
|
|
protein = Math.round((p.protein_per_100g ?? 0) * f * 10) / 10;
|
|
fat = Math.round((p.fat_per_100g ?? 0) * f * 10) / 10;
|
|
carbs = Math.round((p.carbs_per_100g ?? 0) * f * 10) / 10;
|
|
fiber = Math.round((p.fiber_per_100g ?? 0) * f * 10) / 10;
|
|
}
|
|
}
|
|
await execute(
|
|
`INSERT INTO food_log
|
|
(date, time, product_id, amount_g, kcal, protein_g, fat_g, carbs_g, fiber_g, note)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10)`,
|
|
[date, time, productId ?? null, amountG,
|
|
kcal, protein, fat, carbs, fiber, note ?? null]
|
|
);
|
|
}
|
|
|
|
async function updateFoodEntry(id, time, amountG, note, kcalOverride) {
|
|
// Recalculate nutrition from product if linked
|
|
const rows = await select("SELECT product_id FROM food_log WHERE id = ?1", [id]);
|
|
if (!rows.length) return;
|
|
const productId = rows[0].product_id;
|
|
|
|
let kcal = kcalOverride, protein = null, fat = null, carbs = null, fiber = null;
|
|
if (productId && kcalOverride == null) {
|
|
const p = await getProduct(productId);
|
|
if (p && p.kcal_per_100g != null) {
|
|
const f = amountG / 100;
|
|
kcal = Math.round((p.kcal_per_100g ?? 0) * f);
|
|
protein = Math.round((p.protein_per_100g ?? 0) * f * 10) / 10;
|
|
fat = Math.round((p.fat_per_100g ?? 0) * f * 10) / 10;
|
|
carbs = Math.round((p.carbs_per_100g ?? 0) * f * 10) / 10;
|
|
fiber = Math.round((p.fiber_per_100g ?? 0) * f * 10) / 10;
|
|
}
|
|
}
|
|
await execute(
|
|
`UPDATE food_log SET time=?1, amount_g=?2, note=?3,
|
|
kcal=?4, protein_g=?5, fat_g=?6, carbs_g=?7, fiber_g=?8
|
|
WHERE id=?9`,
|
|
[time, amountG, note ?? null, kcal, protein, fat, carbs, fiber, id]
|
|
);
|
|
}
|
|
|
|
async function deleteFoodEntry(id) {
|
|
await execute("DELETE FROM food_log WHERE id = ?1", [id]);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Activity log
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function getActivitiesForDate(date) {
|
|
return select("SELECT * FROM activity_log WHERE date = ?1 ORDER BY time ASC", [date]);
|
|
}
|
|
|
|
async function addActivity(date, time, type, desc, minutes, kcal) {
|
|
await execute(
|
|
"INSERT INTO activity_log (date, time, type, desc, minutes, kcal) VALUES (?1,?2,?3,?4,?5,?6)",
|
|
[date, time, type ?? "manual", desc, minutes ?? null, kcal ?? null]
|
|
);
|
|
}
|
|
|
|
async function deleteActivity(id) {
|
|
await execute("DELETE FROM activity_log WHERE id = ?1", [id]);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Supplements
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function getSupplements() {
|
|
return select("SELECT * FROM supplements ORDER BY name COLLATE NOCASE");
|
|
}
|
|
|
|
async function addSupplement(s) {
|
|
const r = await execute(
|
|
`INSERT INTO supplements
|
|
(name, daily_dose_g, vit_a_mcg, vit_c_mg, vit_d_mcg, vit_e_mg, vit_k_mcg,
|
|
vit_b1_mg, vit_b2_mg, vit_b3_mg, vit_b6_mg, vit_b12_mcg, folate_mcg,
|
|
calcium_mg, iron_mg, magnesium_mg, zinc_mg, copper_mg, selenium_mcg,
|
|
potassium_mg, sodium_mg)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21)`,
|
|
[
|
|
s.name, s.daily_dose_g ?? null,
|
|
s.vit_a_mcg ?? null, s.vit_c_mg ?? null, s.vit_d_mcg ?? null,
|
|
s.vit_e_mg ?? null, s.vit_k_mcg ?? null,
|
|
s.vit_b1_mg ?? null, s.vit_b2_mg ?? null, s.vit_b3_mg ?? null,
|
|
s.vit_b6_mg ?? null, s.vit_b12_mcg ?? null, s.folate_mcg ?? null,
|
|
s.calcium_mg ?? null, s.iron_mg ?? null, s.magnesium_mg ?? null,
|
|
s.zinc_mg ?? null, s.copper_mg ?? null, s.selenium_mcg ?? null,
|
|
s.potassium_mg ?? null, s.sodium_mg ?? null,
|
|
]
|
|
);
|
|
return r.lastInsertId;
|
|
}
|
|
|
|
async function getSupplement(id) {
|
|
const rows = await select("SELECT * FROM supplements WHERE id = ?1", [id]);
|
|
return rows.length ? rows[0] : null;
|
|
}
|
|
|
|
async function deleteSupplement(id) {
|
|
await execute("DELETE FROM supplement_log WHERE supplement_id = ?1", [id]);
|
|
await execute("DELETE FROM supplements WHERE id = ?1", [id]);
|
|
}
|
|
|
|
async function logSupplement(date, time, supplementId, doseG) {
|
|
await execute(
|
|
"INSERT INTO supplement_log (date, time, supplement_id, dose_g) VALUES (?1,?2,?3,?4)",
|
|
[date, time, supplementId, doseG ?? null]
|
|
);
|
|
}
|
|
|
|
async function getSupplementLogForDate(date) {
|
|
return select(
|
|
`SELECT sl.*, s.name as supplement_name, s.daily_dose_g
|
|
FROM supplement_log sl
|
|
JOIN supplements s ON sl.supplement_id = s.id
|
|
WHERE sl.date = ?1 ORDER BY sl.time ASC`,
|
|
[date]
|
|
);
|
|
}
|
|
|
|
async function deleteSupplementLog(id) {
|
|
await execute("DELETE FROM supplement_log WHERE id = ?1", [id]);
|
|
}
|
|
|
|
async function getSupplementTotalsForDate(date) {
|
|
const rows = await select(
|
|
`SELECT
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_a_mcg) as vit_a_mcg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_c_mg) as vit_c_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_d_mcg) as vit_d_mcg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_e_mg) as vit_e_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_k_mcg) as vit_k_mcg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_b1_mg) as vit_b1_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_b2_mg) as vit_b2_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_b3_mg) as vit_b3_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_b6_mg) as vit_b6_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.vit_b12_mcg) as vit_b12_mcg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.folate_mcg) as folate_mcg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.calcium_mg) as calcium_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.iron_mg) as iron_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.magnesium_mg) as magnesium_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.zinc_mg) as zinc_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.copper_mg) as copper_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.selenium_mcg) as selenium_mcg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.potassium_mg) as potassium_mg,
|
|
SUM(COALESCE(sl.dose_g,1) * s.sodium_mg) as sodium_mg
|
|
FROM supplement_log sl
|
|
JOIN supplements s ON sl.supplement_id = s.id
|
|
WHERE sl.date = ?1`,
|
|
[date]
|
|
);
|
|
return rows[0] || {};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Analytics
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function getFoodTotalsForDate(date) {
|
|
const rows = await select(
|
|
`SELECT SUM(kcal) as kcal, SUM(protein_g) as protein_g,
|
|
SUM(fat_g) as fat_g, SUM(carbs_g) as carbs_g, SUM(fiber_g) as fiber_g
|
|
FROM food_log WHERE date = ?1`,
|
|
[date]
|
|
);
|
|
return rows[0] ?? { kcal: 0, protein_g: 0, fat_g: 0, carbs_g: 0, fiber_g: 0 };
|
|
}
|
|
|
|
async function getActivityTotalsForDate(date) {
|
|
const rows = await select(
|
|
"SELECT SUM(kcal) as kcal, SUM(minutes) as minutes FROM activity_log WHERE date = ?1",
|
|
[date]
|
|
);
|
|
return rows[0] ?? { kcal: 0, minutes: 0 };
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// GPS sessions & points
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function createGpsSession(date, startTime, activityType) {
|
|
await execute(
|
|
`INSERT INTO gps_sessions (date, start_time, activity_type, source)
|
|
VALUES (?1, ?2, ?3, 'recorded')`,
|
|
[date, startTime, activityType]
|
|
);
|
|
const rows = await select("SELECT last_insert_rowid() as id");
|
|
return rows[0].id;
|
|
}
|
|
|
|
async function addGpsPoint(sessionId, ts, lat, lon, altGps, speedMs) {
|
|
await execute(
|
|
`INSERT INTO gps_points (session_id, ts, lat, lon, altitude_gps_m, speed_ms)
|
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6)`,
|
|
[sessionId, ts, lat, lon, altGps ?? null, speedMs ?? null]
|
|
);
|
|
}
|
|
|
|
async function finishGpsSession(id, endTime, distM, kcal, avgSpd, maxSpd, elevGain, elevLoss) {
|
|
await execute(
|
|
`UPDATE gps_sessions SET end_time=?1, total_distance_m=?2, total_kcal=?3,
|
|
avg_speed_kmh=?4, max_speed_kmh=?5, elevation_gain_m=?6, elevation_loss_m=?7
|
|
WHERE id=?8`,
|
|
[endTime, distM, kcal, avgSpd, maxSpd, elevGain, elevLoss, id]
|
|
);
|
|
}
|
|
|
|
async function getGpsSessions(limit) {
|
|
return select(
|
|
"SELECT * FROM gps_sessions ORDER BY date DESC, start_time DESC LIMIT ?1",
|
|
[limit ?? 50]
|
|
);
|
|
}
|
|
|
|
async function getGpsSession(id) {
|
|
const rows = await select("SELECT * FROM gps_sessions WHERE id = ?1", [id]);
|
|
return rows.length ? rows[0] : null;
|
|
}
|
|
|
|
async function getGpsPoints(sessionId) {
|
|
return select("SELECT * FROM gps_points WHERE session_id = ?1 ORDER BY COALESCE(seq, 999999), ts ASC", [sessionId]);
|
|
}
|
|
|
|
async function deleteGpsSession(id) {
|
|
await execute("DELETE FROM gps_points WHERE session_id = ?1", [id]);
|
|
await execute("DELETE FROM gps_sessions WHERE id = ?1", [id]);
|
|
}
|
|
|
|
async function importGpxSession(session, points) {
|
|
await execute(
|
|
`INSERT INTO gps_sessions (date, start_time, end_time, activity_type,
|
|
total_distance_m, total_kcal, avg_speed_kmh, max_speed_kmh,
|
|
elevation_gain_m, elevation_loss_m, source)
|
|
VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11)`,
|
|
[session.date, session.start_time, session.end_time, session.activity_type,
|
|
session.total_distance_m, session.total_kcal, session.avg_speed_kmh,
|
|
session.max_speed_kmh, session.elevation_gain_m, session.elevation_loss_m,
|
|
session.source ?? "gpx_import"]
|
|
);
|
|
const rows = await select("SELECT last_insert_rowid() as id");
|
|
const sid = rows[0].id;
|
|
// Batch insert points — build multi-row INSERT to avoid 1 IPC per point
|
|
const BATCH = 50;
|
|
for (let i = 0; i < points.length; i += BATCH) {
|
|
const chunk = points.slice(i, i + BATCH);
|
|
const placeholders = [];
|
|
const vals = [];
|
|
let idx = 1;
|
|
for (const p of chunk) {
|
|
placeholders.push(`(?${idx},?${idx+1},?${idx+2},?${idx+3},?${idx+4},?${idx+5},?${idx+6})`);
|
|
vals.push(sid, p.ts, p.lat, p.lon, p.altitude ?? null, p.speed ?? null, p.seq ?? null);
|
|
idx += 7;
|
|
}
|
|
await execute(
|
|
`INSERT INTO gps_points (session_id, ts, lat, lon, altitude_gps_m, speed_ms, seq) VALUES ${placeholders.join(",")}`,
|
|
vals
|
|
);
|
|
}
|
|
return sid;
|
|
}
|
|
|
|
// Expose as globals — no ES module system, loaded via <script> tags.
|
|
// main.js accesses these as window.DB.xxx
|
|
window.DB = {};
|
|
window.DB.getProfileValue = getProfileValue;
|
|
window.DB.setProfileValue = setProfileValue;
|
|
window.DB.getFullProfile = getFullProfile;
|
|
window.DB.addWeight = addWeight;
|
|
window.DB.deleteWeight = deleteWeight;
|
|
window.DB.getWeightsForDate = getWeightsForDate;
|
|
window.DB.getLatestWeight = getLatestWeight;
|
|
window.DB.getRecentWeights = getRecentWeights;
|
|
window.DB.getSleepForDate = getSleepForDate;
|
|
window.DB.saveSleep = saveSleep;
|
|
window.DB.searchProducts = searchProducts;
|
|
window.DB.getProduct = getProduct;
|
|
window.DB.addProduct = addProduct;
|
|
window.DB.getFoodForDate = getFoodForDate;
|
|
window.DB.addFoodManual = addFoodManual;
|
|
window.DB.addFoodEntry = addFoodEntry;
|
|
window.DB.updateFoodEntry = updateFoodEntry;
|
|
window.DB.deleteFoodEntry = deleteFoodEntry;
|
|
window.DB.getActivitiesForDate = getActivitiesForDate;
|
|
window.DB.addActivity = addActivity;
|
|
window.DB.deleteActivity = deleteActivity;
|
|
window.DB.getSupplements = getSupplements;
|
|
window.DB.getSupplement = getSupplement;
|
|
window.DB.addSupplement = addSupplement;
|
|
window.DB.deleteSupplement = deleteSupplement;
|
|
window.DB.logSupplement = logSupplement;
|
|
window.DB.getSupplementLogForDate = getSupplementLogForDate;
|
|
window.DB.deleteSupplementLog = deleteSupplementLog;
|
|
window.DB.getSupplementTotalsForDate = getSupplementTotalsForDate;
|
|
window.DB.getFoodTotalsForDate = getFoodTotalsForDate;
|
|
window.DB.getActivityTotalsForDate = getActivityTotalsForDate;
|
|
window.DB.createGpsSession = createGpsSession;
|
|
window.DB.addGpsPoint = addGpsPoint;
|
|
window.DB.finishGpsSession = finishGpsSession;
|
|
window.DB.getGpsSessions = getGpsSessions;
|
|
window.DB.getGpsSession = getGpsSession;
|
|
window.DB.getGpsPoints = getGpsPoints;
|
|
window.DB.deleteGpsSession = deleteGpsSession;
|
|
window.DB.importGpxSession = importGpxSession;
|
|
|
|
console.log("[db.js] window.DB ready, keys:", Object.keys(window.DB).length);
|