feat: auto-generate PDF after val2 validation from preview - Call /report/{accessnumber}/pdf endpoint when second validation succeeds

This commit is contained in:
mahdahar 2026-02-12 13:50:01 +07:00
parent 7b6d7f6d85
commit f2e01adfc5
3 changed files with 39 additions and 18 deletions

View File

@ -17,16 +17,19 @@
</button> </button>
</div> </div>
<p class="mb-2 flex gap-2"> <p class="mb-2 flex gap-2 items-center">
<button id="preview-validate-btn" class="btn btn-sm btn-success" <button id="preview-validate-btn" class="btn btn-sm btn-success"
@click="validateFromPreview(previewAccessnumber, '<?=session('userid');?>')" @click="validateFromPreview(previewAccessnumber, '<?=session('userid');?>')"
:disabled="!isPreviewIframeLoaded || isPreviewValidating"> :disabled="!isPreviewIframeLoaded || isPreviewValidating || previewItem?.VAL1USER === '<?=session('userid');?>' || previewItem?.VAL2USER === '<?=session('userid');?>'">
<span x-text="isPreviewValidating ? 'Validating...' : 'Validate'"></span> <span x-text="isPreviewValidating ? 'Validating...' : 'Validate'"></span>
<span x-show="isPreviewValidating" class="loading loading-spinner loading-xs ml-1"></span> <span x-show="isPreviewValidating" class="loading loading-spinner loading-xs ml-1"></span>
</button> </button>
<button class="btn btn-sm btn-ghost" @click="closePreviewDialog()"> <button class="btn btn-sm btn-ghost" @click="closePreviewDialog()">
Close (Esc) Close (Esc)
</button> </button>
<span x-show="previewItem?.VAL1USER === '<?=session('userid');?>' || previewItem?.VAL2USER === '<?=session('userid');?>'" class="text-sm text-error">
<i class="fa fa-exclamation-circle"></i> You have already validated this request
</span>
</p> </p>
<iframe id="preview-iframe" x-ref="previewIframe" :src="getPreviewUrl()" @load="onPreviewIframeLoad()" width="100%" height="500px" <iframe id="preview-iframe" x-ref="previewIframe" :src="getPreviewUrl()" @load="onPreviewIframeLoad()" width="100%" height="500px"
class="border border-base-300 rounded"></iframe> class="border border-base-300 rounded"></iframe>

View File

@ -359,7 +359,7 @@ document.addEventListener('alpine:init', () => {
const eng = this.generateLang === 1 ? '?eng=1' : ''; const eng = this.generateLang === 1 ? '?eng=1' : '';
try { try {
const res = await fetch(`${BASEURL}/report/${this.generateAccessnumber}/pdf${eng}`); const res = await fetch(`${BASEURL}report/${this.generateAccessnumber}/pdf${eng}`);
const data = await res.json(); const data = await res.json();
if (data.success) { if (data.success) {
@ -436,24 +436,44 @@ document.addEventListener('alpine:init', () => {
this.isPreviewIframeLoaded = false; this.isPreviewIframeLoaded = false;
}, },
getPreviewUrl() { getPreviewUrl() {
return `${BASEURL}/report/${this.previewAccessnumber}`; if(this.previewAccessnumber != null) {
return `${BASEURL}report/${this.previewAccessnumber}`;
}
}, },
onPreviewIframeLoad() { onPreviewIframeLoad() {
this.isPreviewIframeLoaded = true; this.isPreviewIframeLoaded = true;
}, },
validateFromPreview(accessnumber, userid) { async validateFromPreview(accessnumber, userid) {
if (!this.isPreviewIframeLoaded || this.isPreviewValidating) return; if (!this.isPreviewIframeLoaded || this.isPreviewValidating) return;
this.isPreviewValidating = true; this.isPreviewValidating = true;
fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, { try {
method: 'POST', const res = await fetch(`${BASEURL}/api/requests/validate/${accessnumber}`, {
headers: { 'Content-Type': 'application/json' } method: 'POST',
}) headers: { 'Content-Type': 'application/json' }
.then(res => res.json()) });
.then(data => { const data = await res.json();
this.isPreviewValidating = false; this.isPreviewValidating = false;
if (data.val) { if (data.val) {
this.showToast(`Validated (val${data.val}): ${accessnumber}`, 'success'); this.showToast(`Validated (val${data.val}): ${accessnumber}`, 'success');
// Generate PDF if second validation (val2) succeeded
if (data.val === 2) {
try {
const pdfRes = await fetch(`${BASEURL}report/${accessnumber}/pdf`);
const pdfData = await pdfRes.json();
if (pdfData.success) {
this.showToast(`${pdfData.lang} PDF queued for download`, 'success');
} else {
this.showToast('PDF generation failed', 'error');
}
} catch (e) {
this.showToast('PDF generation failed', 'error');
}
}
this.fetchList(); this.fetchList();
this.closePreviewDialog(); this.closePreviewDialog();
} else if (data.message && data.message.includes('already validate')) { } else if (data.message && data.message.includes('already validate')) {
@ -461,11 +481,10 @@ document.addEventListener('alpine:init', () => {
} else { } else {
this.showToast(data.message || 'Validation failed', 'error'); this.showToast(data.message || 'Validation failed', 'error');
} }
}) } catch (e) {
.catch(() => {
this.isPreviewValidating = false; this.isPreviewValidating = false;
this.showToast('Validation failed', 'error'); this.showToast('Validation failed', 'error');
}); }
}, },
showToast(message, type = 'success') { showToast(message, type = 'success') {

View File

@ -210,12 +210,11 @@ document.addEventListener('alpine:init', () => {
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ userid: `${userid}` }) body: JSON.stringify({ userid: `${userid}` })
}).then(response => response.json()).then(data => { }).then(response => response.json()).then(data => {
// Capture accessnumber before async operations console.log(data);
const currentAccessnumber = accessnumber;
if (data.val === 2) { if (data.val === 2) {
this.showToast(`Validated (val2): ${currentAccessnumber} - PDF queued`); this.showToast(`Validated (val2): ${data.accessnumber} - PDF queued`);
// Trigger PDF auto-generation after val2 // Trigger PDF auto-generation after val2
fetch(`${BASEURL}/report/${currentAccessnumber}/pdf`).then(res => res.json()).then(pdfData => { fetch(`${BASEURL}/report/${data.accessnumber}/pdf`).then(res => res.json()).then(pdfData => {
if (pdfData.success) { if (pdfData.success) {
console.log('PDF generation queued:', pdfData.jobId); console.log('PDF generation queued:', pdfData.jobId);
} else { } else {