diff --git a/app/Controllers/Api/EntryApiController.php b/app/Controllers/Api/EntryApiController.php
index d00e418..124e78d 100755
--- a/app/Controllers/Api/EntryApiController.php
+++ b/app/Controllers/Api/EntryApiController.php
@@ -195,11 +195,18 @@ class EntryApiController extends BaseController
$date = $input['date'];
$results = $input['results'];
+ $deletedIds = $input['deletedIds'] ?? [];
$savedIds = [];
// Start transaction
$this->resultModel->db->transBegin();
+ // Handle deletions first
+ foreach ($deletedIds as $resultId) {
+ $this->resultModel->delete((int) $resultId);
+ }
+
+ // Save/update results
foreach ($results as $r) {
if (!isset($r['controlId']) || !isset($r['testId']) || !isset($r['value'])) {
continue;
@@ -228,7 +235,7 @@ class EntryApiController extends BaseController
return $this->respond([
'status' => 'success',
- 'message' => 'Saved ' . count($savedIds) . ' results',
+ 'message' => 'Saved ' . count($savedIds) . ' results' . (count($deletedIds) > 0 ? ', deleted ' . count($deletedIds) : ''),
'data' => ['savedIds' => $savedIds]
], 200);
} catch (\Exception $e) {
diff --git a/app/Views/entry/daily.php b/app/Views/entry/daily.php
index 160f203..ab0cb3d 100755
--- a/app/Views/entry/daily.php
+++ b/app/Views/entry/daily.php
@@ -100,8 +100,9 @@
| Test |
Mean ± 2SD |
- Result |
+ Result |
Comment |
+ Action |
@@ -123,18 +124,30 @@
step="0.01"
:placeholder="'...'"
class="input input-bordered input-sm w-full font-mono"
- :class="getInputClass(test, $el.value)"
+ :class="getInputClass(test, $el.value) + ' ' + (deletedResults.includes(test.testId) ? 'input-disabled' : '')"
+ :disabled="deletedResults.includes(test.testId)"
@input.debounce.300ms="updateResult(test.testId, $el.value)"
- :value="test.existingResult ? test.existingResult.resValue : ''">
+ :value="getResultValue(test.testId)">
|
+
+
+ |
@@ -163,6 +176,7 @@ document.addEventListener('alpine:init', () => {
saving: false,
resultsData: {},
commentsData: {},
+ deletedResults: [],
deptId: null,
departments: null,
@@ -236,9 +250,10 @@ document.addEventListener('alpine:init', () => {
const json = await response.json();
this.tests = json.data || [];
- // Initialize resultsData and commentsData with existing values
+ // Initialize resultsData, commentsData, and deletedResults
this.resultsData = {};
this.commentsData = {};
+ this.deletedResults = [];
for (const test of this.tests) {
if (test.existingResult && test.existingResult.resValue !== null) {
this.resultsData[test.testId] = test.existingResult.resValue;
@@ -263,7 +278,17 @@ document.addEventListener('alpine:init', () => {
this.saving = true;
try {
const results = [];
+ const deletedIds = [];
+
for (const test of this.tests) {
+ // Check if this test is marked for deletion
+ if (this.deletedResults.includes(test.testId)) {
+ if (test.existingResult && test.existingResult.resultId) {
+ deletedIds.push(test.existingResult.resultId);
+ }
+ continue;
+ }
+
const value = this.resultsData[test.testId];
if (value !== undefined && value !== '') {
results.push({
@@ -279,15 +304,20 @@ document.addEventListener('alpine:init', () => {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
date: this.date,
- results: results
+ results: results,
+ deletedIds: deletedIds
})
});
const json = await response.json();
if (json.status === 'success') {
- // Save comments using the returned result IDs
+ // Save comments for non-deleted tests
const savedIds = json.data.savedIds || [];
for (const item of savedIds) {
+ // Skip if this test is marked for deletion
+ if (this.deletedResults.includes(item.testId)) {
+ continue;
+ }
const comment = this.commentsData[item.testId];
if (comment) {
await this.saveComment(item.testId, this.date, comment);
@@ -299,6 +329,7 @@ document.addEventListener('alpine:init', () => {
// Refresh data
this.resultsData = {};
this.commentsData = {};
+ this.deletedResults = [];
await this.fetchTests();
} else {
this.$dispatch('notify', { type: 'error', message: json.message || 'Failed to save' });
@@ -329,12 +360,51 @@ document.addEventListener('alpine:init', () => {
}
},
+ getResultValue(testId) {
+ // If marked for deletion, show empty
+ if (this.deletedResults.includes(testId)) {
+ return '';
+ }
+ // Return from resultsData if changed
+ if (testId in this.resultsData) {
+ return this.resultsData[testId];
+ }
+ // Return existing result from database
+ const test = this.tests.find(t => t.testId === testId);
+ if (test && test.existingResult && test.existingResult.resValue !== null) {
+ return test.existingResult.resValue;
+ }
+ return '';
+ },
+
updateResult(testId, value) {
if (value === '') {
delete this.resultsData[testId];
} else {
this.resultsData[testId] = value;
}
+ // Remove from deletedResults if user enters a value
+ if (value !== '' && this.deletedResults.includes(testId)) {
+ this.deletedResults = this.deletedResults.filter(id => id !== testId);
+ }
+ },
+
+ toggleDelete(testId) {
+ const test = this.tests.find(t => t.testId === testId);
+ const hasExistingResult = test && test.existingResult && test.existingResult.resValue !== null;
+ const hasChanges = testId in this.resultsData || testId in this.commentsData;
+
+ if (this.deletedResults.includes(testId)) {
+ // Restore - remove from deleted list
+ this.deletedResults = this.deletedResults.filter(id => id !== testId);
+ } else {
+ // Mark for deletion
+ if (hasExistingResult || hasChanges) {
+ this.deletedResults.push(testId);
+ // Clear any pending changes for this test
+ delete this.resultsData[testId];
+ }
+ }
},
updateComment(testId, value) {
@@ -384,7 +454,11 @@ document.addEventListener('alpine:init', () => {
},
get canSave() {
- return this.selectedControl && (Object.keys(this.resultsData).length > 0 || Object.keys(this.commentsData).length > 0) && !this.saving;
+ return this.selectedControl && (
+ Object.keys(this.resultsData).length > 0 ||
+ Object.keys(this.commentsData).length > 0 ||
+ this.deletedResults.length > 0
+ ) && !this.saving;
},
setToday() {