US-015: Complete Monthly Entry Interface with data loading and comments
This commit is contained in:
parent
f14c0862da
commit
79da3c1c78
@ -37,6 +37,7 @@ $routes->group('api', function ($routes) {
|
|||||||
|
|
||||||
$routes->get('entry/controls', 'Api\EntryApiController::getControls');
|
$routes->get('entry/controls', 'Api\EntryApiController::getControls');
|
||||||
$routes->get('entry/tests', 'Api\EntryApiController::getTests');
|
$routes->get('entry/tests', 'Api\EntryApiController::getTests');
|
||||||
|
$routes->get('entry/monthly', 'Api\EntryApiController::getMonthlyData');
|
||||||
$routes->post('entry/daily', 'Api\EntryApiController::saveDaily');
|
$routes->post('entry/daily', 'Api\EntryApiController::saveDaily');
|
||||||
$routes->post('entry/monthly', 'Api\EntryApiController::saveMonthly');
|
$routes->post('entry/monthly', 'Api\EntryApiController::saveMonthly');
|
||||||
$routes->post('entry/comment', 'Api\EntryApiController::saveComment');
|
$routes->post('entry/comment', 'Api\EntryApiController::saveComment');
|
||||||
|
|||||||
@ -135,4 +135,33 @@ class EntryApiController extends BaseController
|
|||||||
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMonthlyData()
|
||||||
|
{
|
||||||
|
$controlId = $this->request->getGet('controlId');
|
||||||
|
$testId = $this->request->getGet('testId');
|
||||||
|
$yearMonth = $this->request->getGet('yearMonth');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$results = $this->resultModel->getByMonth($controlId, $testId, $yearMonth);
|
||||||
|
$comment = $this->commentModel->getByControlTestMonth($controlId, $testId, $yearMonth);
|
||||||
|
|
||||||
|
$formValues = [];
|
||||||
|
foreach ($results as $row) {
|
||||||
|
$day = (int)date('j', strtotime($row['resdate']));
|
||||||
|
$formValues[$day] = $row['resvalue'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'fetch success',
|
||||||
|
'data' => [
|
||||||
|
'formValues' => $formValues,
|
||||||
|
'comment' => $comment ? $comment['comtext'] : ''
|
||||||
|
]
|
||||||
|
], 200);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $this->failServerError('Something went wrong: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<?= $this->extend("layout/main_layout"); ?>
|
<?= $this->extend("layout/main_layout"); ?>
|
||||||
<?= $this->section("content") ?>
|
<?= $this->section("content") ?>
|
||||||
<main x-data="monthlyEntry()">
|
<main x-data="monthlyEntry()" @keydown.window.ctrl.s.prevent="showEntry ? saveData() : null">
|
||||||
<div class="bg-white rounded-xl border border-slate-100 shadow-sm p-6">
|
<div class="bg-white rounded-xl border border-slate-100 shadow-sm p-6">
|
||||||
<div class="flex items-center justify-between mb-6">
|
<div class="flex items-center justify-between mb-6">
|
||||||
<div>
|
<div>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6" x-show="control && test" x-transition>
|
<div class="mt-6" x-show="control && test" x-transition>
|
||||||
<button @click="showEntry = true" class="btn btn-primary">
|
<button @click="openEntry()" class="btn btn-primary">
|
||||||
<i class="fa-solid fa-plus mr-2"></i>
|
<i class="fa-solid fa-plus mr-2"></i>
|
||||||
Enter Data
|
Enter Data
|
||||||
</button>
|
</button>
|
||||||
@ -101,13 +101,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template x-if="!loading">
|
<template x-if="!loading">
|
||||||
<div class="grid grid-cols-7 gap-2">
|
<div>
|
||||||
<template x-for="day in 31" :key="day">
|
<div class="grid grid-cols-7 gap-2 mb-4">
|
||||||
<div class="text-center">
|
<template x-for="day in 31" :key="day">
|
||||||
<label class="block text-xs text-slate-500 mb-1" x-text="day"></label>
|
<div class="text-center">
|
||||||
<input type="number" step="0.01" :name="'day_' + day" x-model="formValues[day]" class="w-full px-2 py-2 text-sm text-center bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" placeholder="-">
|
<label class="block text-xs text-slate-500 mb-1" x-text="day"></label>
|
||||||
</div>
|
<input type="number" step="0.01" :name="'day_' + day" x-model="formValues[day]" class="w-full px-2 py-2 text-sm text-center bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" placeholder="-">
|
||||||
</template>
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4">
|
||||||
|
<label class="block text-sm font-medium text-slate-700 mb-1">Monthly Comment</label>
|
||||||
|
<textarea x-model="comment" rows="2" class="w-full px-4 py-2.5 text-sm bg-slate-50 border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500" placeholder="Optional monthly comment"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
@ -148,6 +154,7 @@ document.addEventListener('alpine:init', () => {
|
|||||||
errors: {},
|
errors: {},
|
||||||
error: '',
|
error: '',
|
||||||
formValues: {},
|
formValues: {},
|
||||||
|
comment: '',
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.loadDraft();
|
this.loadDraft();
|
||||||
@ -222,6 +229,29 @@ document.addEventListener('alpine:init', () => {
|
|||||||
return Object.keys(this.errors).length === 0;
|
return Object.keys(this.errors).length === 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async openEntry() {
|
||||||
|
this.formValues = {};
|
||||||
|
this.comment = '';
|
||||||
|
this.loading = true;
|
||||||
|
this.showEntry = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${window.BASEURL}/api/entry/monthly?controlid=${this.control}&testid=${this.test}&yearmonth=${this.date}`);
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.status === 'success') {
|
||||||
|
this.formValues = data.data.formValues || {};
|
||||||
|
this.comment = data.data.comment || '';
|
||||||
|
} else {
|
||||||
|
this.error = data.message || 'Failed to load existing data';
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
this.error = 'Failed to load existing data';
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async saveData() {
|
async saveData() {
|
||||||
if (!this.validate()) {
|
if (!this.validate()) {
|
||||||
App.showToast('Please fill all required fields', 'error');
|
App.showToast('Please fill all required fields', 'error');
|
||||||
@ -247,8 +277,8 @@ document.addEventListener('alpine:init', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasData) {
|
if (!hasData && !this.comment) {
|
||||||
App.showToast('Please enter at least one value', 'warning');
|
App.showToast('Please enter at least one value or comment', 'warning');
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,9 +290,13 @@ document.addEventListener('alpine:init', () => {
|
|||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.status === 'success') {
|
if (data.status === 'success') {
|
||||||
|
if (this.comment) {
|
||||||
|
await this.saveComment();
|
||||||
|
}
|
||||||
App.showToast('Data saved successfully!');
|
App.showToast('Data saved successfully!');
|
||||||
this.showEntry = false;
|
this.showEntry = false;
|
||||||
this.formValues = {};
|
this.formValues = {};
|
||||||
|
this.comment = '';
|
||||||
this.saveDraft();
|
this.saveDraft();
|
||||||
} else {
|
} else {
|
||||||
this.error = data.message || 'Failed to save data';
|
this.error = data.message || 'Failed to save data';
|
||||||
@ -275,6 +309,23 @@ document.addEventListener('alpine:init', () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async saveComment() {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('controlid', this.control);
|
||||||
|
formData.append('testid', this.test);
|
||||||
|
formData.append('commonth', this.date);
|
||||||
|
formData.append('comtext', this.comment);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fetch(`${window.BASEURL}/api/entry/comment`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to save comment:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
saveDraft() {
|
saveDraft() {
|
||||||
localStorage.setItem('monthlyEntry', JSON.stringify({
|
localStorage.setItem('monthlyEntry', JSON.stringify({
|
||||||
dept: this.dept,
|
dept: this.dept,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user