From d0a8284d52043a1b1d80dd6b9db120804fdc4655 Mon Sep 17 00:00:00 2001 From: Shane Jaroch Date: Mon, 26 Jan 2026 00:23:36 -0500 Subject: [PATCH] wip add some features --- include/db/foodrepository.h | 7 +- include/widgets/dailylogwidget.h | 7 +- src/db/foodrepository.cpp | 26 +++++++ src/widgets/dailylogwidget.cpp | 122 +++++++++++++------------------ 4 files changed, 83 insertions(+), 79 deletions(-) diff --git a/include/db/foodrepository.h b/include/db/foodrepository.h index 3a27f47..eeed937 100644 --- a/include/db/foodrepository.h +++ b/include/db/foodrepository.h @@ -48,8 +48,9 @@ public: std::map getNutrientRdas(); void updateRda(int nutrId, double value); - // Helper to get nutrient definition basics if needed - // QString getNutrientName(int nutrientId); + // Helper to get nutrient definition basics + QString getNutrientName(int nutrientId); + QString getNutrientUnit(int nutrientId); private: // Internal helper methods @@ -60,6 +61,8 @@ private: // Cache stores basic food info std::vector m_cache; std::map m_rdas; + std::map m_nutrientNames; + std::map m_nutrientUnits; }; #endif // FOODREPOSITORY_H diff --git a/include/widgets/dailylogwidget.h b/include/widgets/dailylogwidget.h index 3d10eb7..3204e95 100644 --- a/include/widgets/dailylogwidget.h +++ b/include/widgets/dailylogwidget.h @@ -31,18 +31,13 @@ private: // Analysis UI QGroupBox* analysisBox; QVBoxLayout* analysisLayout; - QProgressBar* kcalBar; - QProgressBar* proteinBar; - QProgressBar* carbsBar; - QProgressBar* fatBar; + QTableWidget* analysisTable; QSpinBox* scaleInput; MealRepository m_mealRepo; FoodRepository m_foodRepo; void updateAnalysis(); - void createProgressBar(QVBoxLayout* layout, const QString& label, QProgressBar*& bar, - const QString& color); }; #endif // DAILYLOGWIDGET_H diff --git a/src/db/foodrepository.cpp b/src/db/foodrepository.cpp index 646d195..93ab8b5 100644 --- a/src/db/foodrepository.cpp +++ b/src/db/foodrepository.cpp @@ -36,6 +36,16 @@ void FoodRepository::ensureCacheLoaded() { nutrientCounts[countQuery.value(0).toInt()] = countQuery.value(1).toInt(); } + // 3. Load Nutrient Definition Metadata + m_nutrientNames.clear(); + m_nutrientUnits.clear(); + QSqlQuery defQuery("SELECT id, nutr_desc, unit FROM nutr_def", db); + while (defQuery.next()) { + int id = defQuery.value(0).toInt(); + m_nutrientNames[id] = defQuery.value(1).toString(); + m_nutrientUnits[id] = defQuery.value(2).toString(); + } + while (query.next()) { FoodItem item; item.id = query.value(0).toInt(); @@ -263,3 +273,19 @@ void FoodRepository::updateRda(int nutrId, double value) { qCritical() << "Failed to update RDA:" << query.lastError().text(); } } + +QString FoodRepository::getNutrientName(int nutrientId) { + ensureCacheLoaded(); + if (m_nutrientNames.count(nutrientId) != 0U) { + return m_nutrientNames[nutrientId]; + } + return QString("Unknown Nutrient (%1)").arg(nutrientId); +} + +QString FoodRepository::getNutrientUnit(int nutrientId) { + ensureCacheLoaded(); + if (m_nutrientUnits.count(nutrientId) != 0U) { + return m_nutrientUnits[nutrientId]; + } + return "?"; +} diff --git a/src/widgets/dailylogwidget.cpp b/src/widgets/dailylogwidget.cpp index e91ac80..7e20c12 100644 --- a/src/widgets/dailylogwidget.cpp +++ b/src/widgets/dailylogwidget.cpp @@ -40,12 +40,6 @@ void DailyLogWidget::setupUi() { auto* analysisBox = new QGroupBox("Analysis (Projected)", this); auto* analysisLayout = new QVBoxLayout(analysisBox); - // Analysis UI - kcalBar = nullptr; - proteinBar = nullptr; - carbsBar = nullptr; - fatBar = nullptr; - // Scale Controls auto* scaleLayout = new QHBoxLayout(); scaleLayout->addWidget(new QLabel("Project to Goal:", this)); @@ -56,19 +50,20 @@ void DailyLogWidget::setupUi() { scaleLayout->addWidget(scaleInput); scaleLayout->addWidget(new QLabel("kcal", this)); - - // Add spacer scaleLayout->addStretch(); - analysisLayout->addLayout(scaleLayout); connect(scaleInput, QOverload::of(&QSpinBox::valueChanged), this, &DailyLogWidget::updateAnalysis); - createProgressBar(analysisLayout, "Calories", kcalBar, "#3498db"); // Blue - createProgressBar(analysisLayout, "Protein", proteinBar, "#e74c3c"); // Red - createProgressBar(analysisLayout, "Carbs", carbsBar, "#f1c40f"); // Yellow - createProgressBar(analysisLayout, "Fat", fatBar, "#2ecc71"); // Green + // Analysis Table + analysisTable = new QTableWidget(this); + analysisTable->setColumnCount(3); + analysisTable->setHorizontalHeaderLabels({"Nutrient", "Progress", "Detail"}); + analysisTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); + analysisTable->setEditTriggers(QAbstractItemView::NoEditTriggers); + analysisTable->setSelectionMode(QAbstractItemView::NoSelection); + analysisLayout->addWidget(analysisTable); bottomLayout->addWidget(analysisBox); splitter->addWidget(bottomWidget); @@ -78,21 +73,6 @@ void DailyLogWidget::setupUi() { splitter->setStretchFactor(1, 2); } -void DailyLogWidget::createProgressBar(QVBoxLayout* layout, const QString& label, - QProgressBar*& bar, const QString& color) { - auto* hLayout = new QHBoxLayout(); - hLayout->addWidget(new QLabel(label + ":")); - - bar = new QProgressBar(); - bar->setRange(0, 100); - bar->setValue(0); - bar->setTextVisible(true); - bar->setStyleSheet(QString("QProgressBar::chunk { background-color: %1; }").arg(color)); - - hLayout->addWidget(bar); - layout->addLayout(hLayout); -} - void DailyLogWidget::refresh() { updateTable(); updateAnalysis(); @@ -110,59 +90,59 @@ void DailyLogWidget::updateAnalysis() { } } - // Hardcoded RDAs for now (TODO: Fetch from FoodRepository/User Profile) - double goalKcal = scaleInput->value(); // Projection Target - - // Calculate Multiplier + double goalKcal = scaleInput->value(); double currentKcal = totals[208]; double multiplier = 1.0; if (currentKcal > 0 && goalKcal > 0) { multiplier = goalKcal / currentKcal; } - // Use scaling for "What If" visualization? - // Actually, progress bars usually show % of RDA. - // If we project, we want to show: "If I ate this ratio until I hit 2000kcal, I would have X - // protein." + analysisTable->setRowCount(0); - double rdaKcal = goalKcal; // The goal IS the RDA in this context usually - double rdaProtein = 150; - double rdaCarbs = 300; - double rdaFat = 80; + // Iterate over defined RDAs from repository + auto rdas = m_foodRepo.getNutrientRdas(); + for (const auto& [nutrId, rda] : rdas) { + if (rda <= 0) continue; - auto updateBar = [&](QProgressBar* bar, int nutrId, double rda, const QString& normalColor) { double val = totals[nutrId]; double projectedVal = val * multiplier; - - int pct = 0; - if (rda > 0) pct = static_cast((projectedVal / rda) * 100.0); - - bar->setValue(std::min(pct, 100)); - - // Format: "Actual (Projected) / Target" - QString text = - QString("%1 (%2) / %3 g").arg(val, 0, 'f', 0).arg(projectedVal, 0, 'f', 0).arg(rda); - if (nutrId == 208) - text = QString("%1 (%2) / %3 kcal") - .arg(val, 0, 'f', 0) - .arg(projectedVal, 0, 'f', 0) - .arg(rda); - - bar->setFormat(text); - - if (pct > 100) { - bar->setStyleSheet("QProgressBar::chunk { background-color: #8e44ad; }"); - } else { - // Restore original color - bar->setStyleSheet( - QString("QProgressBar::chunk { background-color: %1; }").arg(normalColor)); - } - }; - - updateBar(kcalBar, 208, rdaKcal, "#3498db"); - updateBar(proteinBar, 203, rdaProtein, "#e74c3c"); - updateBar(carbsBar, 205, rdaCarbs, "#f1c40f"); - updateBar(fatBar, 204, rdaFat, "#2ecc71"); + double pct = (projectedVal / rda) * 100.0; + QString unit = m_foodRepo.getNutrientUnit(nutrId); + QString name = m_foodRepo.getNutrientName(nutrId); + + int row = analysisTable->rowCount(); + analysisTable->insertRow(row); + + // 1. Nutrient Name + analysisTable->setItem(row, 0, new QTableWidgetItem(name)); + + // 2. Progress Bar + auto* bar = new QProgressBar(); + bar->setRange(0, 100); + bar->setValue(std::min(static_cast(pct), 100)); + bar->setTextVisible(true); + bar->setFormat(QString("%1%").arg(pct, 0, 'f', 1)); + + // Coloring logic based on CLI thresholds + QString color = "#3498db"; // Default Blue + if (pct < 50) + color = "#f1c40f"; // Yellow (Under) + else if (pct > 150) + color = "#8e44ad"; // Purple (Over) + else if (pct >= 100) + color = "#2ecc71"; // Green (Good) + + bar->setStyleSheet(QString("QProgressBar::chunk { background-color: %1; }").arg(color)); + analysisTable->setCellWidget(row, 1, bar); + + // 3. Detail Text + QString detail = QString("%1 (%2) / %3 %4") + .arg(val, 0, 'f', 1) + .arg(projectedVal, 0, 'f', 1) + .arg(rda, 0, 'f', 1) + .arg(unit); + analysisTable->setItem(row, 2, new QTableWidgetItem(detail)); + } } void DailyLogWidget::updateTable() { -- 2.52.0