From 2e23fc38c3ae01f1a271cf53503f27c85c934ea9 Mon Sep 17 00:00:00 2001
From: mahdahar <89adham@gmail.com>
Date: Fri, 16 Jan 2026 17:22:40 +0700
Subject: [PATCH] US-017: Implement Daily Comments per day per test
- Add per-day comment input in monthly entry grid (comment icon per cell)
- Update saveMonthly() to save rescomment field for each result
- Update getMonthlyData() to return per-day comments
- Store comments in results.rescomment field with soft deletes support
---
app/Controllers/Api/EntryApiController.php | 13 ++++-
app/Views/entry/monthly.php | 61 ++++++++++++++++++----
2 files changed, 63 insertions(+), 11 deletions(-)
diff --git a/app/Controllers/Api/EntryApiController.php b/app/Controllers/Api/EntryApiController.php
index d17d358..b8971a1 100644
--- a/app/Controllers/Api/EntryApiController.php
+++ b/app/Controllers/Api/EntryApiController.php
@@ -98,6 +98,7 @@ class EntryApiController extends BaseController
foreach ($tests as $testData) {
$testId = $testData['testId'] ?? 0;
$resvalues = $testData['resvalue'] ?? [];
+ $rescomments = $testData['rescomment'] ?? [];
$controlTest = $this->controlTestModel->getByControlAndTest($controlId, $testId);
$mean = $controlTest['mean'] ?? 0;
@@ -111,12 +112,15 @@ class EntryApiController extends BaseController
foreach ($resvalues as $day => $value) {
if (!empty($value)) {
+ $resdate = $yearMonth . '-' . str_pad($day, 2, '0', STR_PAD_LEFT);
+ $rescomment = $rescomments[$day] ?? '';
+
$resultData = [
'control_ref_id' => $controlId,
'test_ref_id' => $testId,
- 'resdate' => $yearMonth . '-' . str_pad($day, 2, '0', STR_PAD_LEFT),
+ 'resdate' => $resdate,
'resvalue' => $value,
- 'rescomment' => '',
+ 'rescomment' => $rescomment,
];
if ($operation === 'replace') {
@@ -223,9 +227,13 @@ class EntryApiController extends BaseController
$comment = $this->commentModel->getByControlTestMonth($controlId, $testId, $yearMonth);
$formValues = [];
+ $comments = [];
foreach ($results as $row) {
$day = (int)date('j', strtotime($row['resdate']));
$formValues[$day] = $row['resvalue'];
+ if (!empty($row['rescomment'])) {
+ $comments[$day] = $row['rescomment'];
+ }
}
return $this->respond([
@@ -233,6 +241,7 @@ class EntryApiController extends BaseController
'message' => 'fetch success',
'data' => [
'formValues' => $formValues,
+ 'comments' => $comments,
'comment' => $comment ? $comment['comtext'] : ''
]
], 200);
diff --git a/app/Views/entry/monthly.php b/app/Views/entry/monthly.php
index c42cafa..e2d2b56 100644
--- a/app/Views/entry/monthly.php
+++ b/app/Views/entry/monthly.php
@@ -108,15 +108,38 @@
- |
-
+
+
+
+
+
+
+
|
@@ -191,6 +214,7 @@ document.addEventListener('alpine:init', () => {
dirtyCells: new Set(),
operation: 'replace',
saveResult: null,
+ showCommentId: null,
init() {
this.loadDraft();
@@ -230,6 +254,15 @@ document.addEventListener('alpine:init', () => {
this.dirtyCells.add(testId + '_' + day);
},
+ toggleComment(testId, day) {
+ const id = testId + '_' + day;
+ if (this.showCommentId === id) {
+ this.showCommentId = null;
+ } else {
+ this.showCommentId = id;
+ }
+ },
+
async loadControls() {
this.errors = {};
this.controls = [];
@@ -311,9 +344,13 @@ document.addEventListener('alpine:init', () => {
const data = await response.json();
if (data.status === 'success') {
const formValues = data.data.formValues || {};
+ const comments = data.data.comments || {};
for (const [day, value] of Object.entries(formValues)) {
this.monthlyData[testId + '_' + day] = value;
}
+ for (const [day, comment] of Object.entries(comments)) {
+ this.monthlyData[testId + '_' + day + '_comment'] = comment;
+ }
if (!this.comment && data.data.comment) {
this.comment = data.data.comment;
}
@@ -354,17 +391,23 @@ document.addEventListener('alpine:init', () => {
const tests = [];
for (const testId of this.selectedTests) {
const resvalue = {};
+ const rescomment = {};
let hasData = false;
for (let day = 1; day <= this.daysInMonth; day++) {
const key = testId + '_' + day;
const value = this.monthlyData[key];
+ const commentKey = testId + '_' + day + '_comment';
+ const comment = this.monthlyData[commentKey];
if (value !== undefined && value !== null && value !== '') {
resvalue[day] = value;
hasData = true;
}
+ if (comment !== undefined && comment !== null && comment !== '') {
+ rescomment[day] = comment;
+ }
}
if (hasData) {
- tests.push({ testId, resvalue });
+ tests.push({ testId, resvalue, rescomment });
}
}