Update 'coretabs.user.js'

Add action buttons at the top.
This commit is contained in:
2025-08-20 09:56:32 +00:00
parent 0fef550ecb
commit fc1c42624a

View File

@@ -35,6 +35,7 @@
#ct-header-text { flex-grow: 1; min-width: 0; }
#ct-header-title { font-size: 16px; font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#ct-header-subtitle { font-size: 12px; color: #adb5bd; }
#ct-header-actions { margin-left: auto; flex-shrink: 0; display: flex; gap: 5px; }
#ct-tab-bar{display:flex;background-color:#e9ecef;border-bottom:1px solid #ccc;flex-shrink:0}.ct-tab-button{padding:10px 15px;border:none;background-color:transparent;cursor:pointer;font-size:14px;border-bottom:3px solid transparent;transition:background-color .2s,border-color .2s}.ct-tab-button:hover{background-color:#dcdcdc}.ct-tab-button.active{border-bottom:3px solid #0056b3;font-weight:700;background-color:#fff}#ct-tab-content-area{padding:15px;flex-grow:1;overflow:hidden;display:flex;flex-direction:column}.ct-tab-panel{display:none;flex-grow:1;overflow:hidden;flex-direction:column}.ct-tab-panel.active{display:flex}
.filter-container{margin-bottom:10px;flex-shrink:0;display:flex;gap:15px;align-items:center;}
.filter-container label{font-weight:700;margin-right:5px}.filter-container select{padding:5px;border-radius:4px;border:1px solid #ccc}
@@ -70,6 +71,7 @@
<div id="ct-header-title">No Case Selected</div>
<div id="ct-header-subtitle">Please select a case from the "My Cases" tab</div>
</div>
<div id="ct-header-actions"></div>
</div>
<div id="ct-tab-bar">
<button class="ct-tab-button active" data-tab="tab-my-cases">My Cases</button>
@@ -79,15 +81,15 @@
</div>
<div id="ct-tab-content-area">
<div id="tab-my-cases" class="ct-tab-panel active"><div class="filter-container"><div><label for="cases-status-filter">Filter by Status:</label><select id="cases-status-filter"></select></div><button id="toggle-cases-btn" class="action-btn" style="margin-left:auto">Collapse All</button></div><div class="results-container"><p style="padding:15px;color:#666;">Loading my cases...</p></div></div>
<div id="tab-docs" class="ct-tab-panel"><div class="filter-container"><div><label for="docs-status-filter">Filter by Status:</label><select id="docs-status-filter"></select></div><button id="toggle-docs-btn" class="action-btn" style="margin-left:auto">Collapse All</button></div><div class="results-container"><p style="padding:15px;color:#666;">Please select a case or use 'View Docs'.</p></div></div>
<div id="tab-users" class="ct-tab-panel"><div class="filter-container"><div><label for="users-role-filter">Filter by Role:</label><select id="users-role-filter"></select></div></div><div class="results-container"><p style="padding:15px;color:#666;">Please select a case or use 'View Users'.</p></div></div>
<div id="tab-docs" class="ct-tab-panel"><div class="filter-container"><div><label for="docs-status-filter">Filter by Status:</label><select id="docs-status-filter"></select></div><button id="toggle-docs-btn" class="action-btn" style="margin-left:auto">Collapse All</button></div><div class="results-container"><p style="padding:15px;color:#666;">Please select a case to view its documents.</p></div></div>
<div id="tab-users" class="ct-tab-panel"><div class="filter-container"><div><label for="users-role-filter">Filter by Role:</label><select id="users-role-filter"></select></div></div><div class="results-container"><p style="padding:15px;color:#666;">Please select a case to view its users.</p></div></div>
<div id="tab-refund" class="ct-tab-panel">
<div class="filter-container">
<div><label for="refund-reported-filter">Filter by Reported:</label><select id="refund-reported-filter"></select></div>
<button id="toggle-refund-btn" class="action-btn" style="margin-left:auto">Collapse All</button>
<button id="refund-download-btn" class="action-btn download-doc">Download Excel</button>
</div>
<div class="results-container"><p style="padding:15px;color:#666;">Please use the 'Review Refund' action on a relevant case.</p></div>
<div class="results-container"><p style="padding:15px;color:#666;">Select a refund case and click "Refund Review" in the header or row.</p></div>
</div>
</div>
</div>
@@ -96,7 +98,7 @@
}
// --- RENDER FUNCTIONS ---
function renderMyCasesTable() {const responseArea=document.querySelector("#tab-my-cases .results-container"),filterValue=document.getElementById("cases-status-filter").value,filteredCases="all"===filterValue?allMyCases:allMyCases.filter(e=>e.CaseStatus===filterValue);if(document.getElementById("toggle-cases-btn").textContent="Collapse All",0===filteredCases.length)return void(responseArea.innerHTML='<p style="padding:15px;color:#666;">No cases match the selected filter.</p>');filteredCases.sort((e,t)=>{const o=(e.CaseTypeName||"").localeCompare(t.CaseTypeName||"");return 0!==o?o:(t.CaseNumber||"").localeCompare(e.CaseNumber||"",void 0,{numeric:!0})});const table=createTable(["Case Number","Taxpayer Name","Case Type","Status","Created Date","Actions"]),tbody=document.createElement("tbody");let currentGroup="";let groupIndex=0;filteredCases.forEach(e=>{if(e.CaseTypeName!==currentGroup){currentGroup=e.CaseTypeName;groupIndex++;tbody.innerHTML+=`<tr class="group-header expanded" data-group-id="my-cases-group-${groupIndex}"><td colspan="6"><span class="toggle-icon"></span>${currentGroup||"Uncategorized"}</td></tr>`}const t=document.createElement("tr");t.className=`group-member my-cases-group-${groupIndex}`;const o=e.AggregateIdentifier;t.dataset.id=o,o===selectedCaseId&&t.classList.add("selected");const a=new Date(e.CreatedDate).toLocaleDateString("id-ID"),s=o&&"string"==typeof o&&""!==o.trim(),r=s?"":'disabled title="Action unavailable: Case ID is missing"';let d="";e.CaseTypeName===REFUND_CASE_TYPE_NAME&&(d=`<button class="action-btn review-refund-case" data-id="${o}">Review Refund</button>`),t.innerHTML=`
function renderMyCasesTable() {const responseArea=document.querySelector("#tab-my-cases .results-container"),filterValue=document.getElementById("cases-status-filter").value,filteredCases="all"===filterValue?allMyCases:allMyCases.filter(e=>e.CaseStatus===filterValue);if(document.getElementById("toggle-cases-btn").textContent="Collapse All",0===filteredCases.length)return void(responseArea.innerHTML='<p style="padding:15px;color:#666;">No cases match the selected filter.</p>');filteredCases.sort((e,t)=>{const o=(e.CaseTypeName||"").localeCompare(t.CaseTypeName||"");return 0!==o?o:(t.CaseNumber||"").localeCompare(e.CaseNumber||"",void 0,{numeric:!0})});const table=createTable(["Case Number","Taxpayer Name","Case Type","Status","Created Date","Actions"]),tbody=document.createElement("tbody");let currentGroup="";let groupIndex=0;filteredCases.forEach(e=>{if(e.CaseTypeName!==currentGroup){currentGroup=e.CaseTypeName;groupIndex++;tbody.innerHTML+=`<tr class="group-header expanded" data-group-id="my-cases-group-${groupIndex}"><td colspan="6"><span class="toggle-icon"></span>${currentGroup||"Uncategorized"}</td></tr>`}const t=document.createElement("tr");t.className=`group-member my-cases-group-${groupIndex}`;const o=e.AggregateIdentifier;t.dataset.id=o,o===selectedCaseId&&t.classList.add("selected");const a=new Date(e.CreatedDate).toLocaleDateString("id-ID"),s=o&&"string"==typeof o&&""!==o.trim(),r=s?"":'disabled title="Action unavailable: Case ID is missing"';let d="";e.CaseTypeName===REFUND_CASE_TYPE_NAME&&(d=`<button class="action-btn review-refund-case" data-id="${o}">Refund Review</button>`),t.innerHTML=`
<td>${e.CaseNumber||"N/A"}</td>
<td>${e.MainTaxpayerName||"N/A"}</td>
<td>${e.CaseTypeName||"N/A"}</td>
@@ -107,7 +109,7 @@
<button class="action-btn view-docs" data-id="${o}" ${r}>View Docs</button>
<button class="action-btn view-users" data-id="${o}" ${r}>View Users</button>
${d}
</td>`,tbody.appendChild(t)}),table.appendChild(tbody),responseArea.innerHTML="",responseArea.appendChild(table),tbody.addEventListener("click",handleGroupToggle),tbody.addEventListener("click",handleCaseAction)}
</td>`,tbody.appendChild(t)}),table.appendChild(tbody),responseArea.innerHTML="",responseArea.appendChild(table),tbody.addEventListener("click",handleGroupToggle),tbody.addEventListener("click",handleCaseSelection)}
function renderCaseDocumentsTable() {const responseArea=document.querySelector("#tab-docs .results-container"),filterValue=document.getElementById("docs-status-filter").value,filteredDocs="all"===filterValue?allCaseDocuments:allCaseDocuments.filter(e=>e.DocumentStatus===filterValue);if(document.getElementById("toggle-docs-btn").textContent="Collapse All",0===filteredDocs.length)return void(responseArea.innerHTML='<p style="padding:15px;color:#666;">No documents found or match the selected filter.</p>');filteredDocs.sort((e,t)=>(e.DocumentTypeCode||"").localeCompare(t.DocumentTypeCode||""));const table=createTable(["Letter Number","File Name","Status","Date","Actions"]),tbody=document.createElement("tbody");let currentGroup="";let groupIndex=0;filteredDocs.forEach(e=>{if(e.DocumentTypeCode!==currentGroup){currentGroup=e.DocumentTypeCode;groupIndex++;tbody.innerHTML+=`<tr class="group-header expanded" data-group-id="docs-group-${groupIndex}"><td colspan="5"><span class="toggle-icon"></span>${currentGroup||"Uncategorized"}</td></tr>`}const t=e.DocumentDate?new Date(e.DocumentDate).toLocaleDateString("id-ID"):"N/A";tbody.innerHTML+=`
<tr class="group-member docs-group-${groupIndex}">
<td>${e.LetterNumber||"N/A"}</td>
@@ -154,7 +156,52 @@
<p style="margin: 10px 0;">Please refresh the page to log in again.</p>
<button id="auth-refresh-btn" class="refresh-btn">Refresh Page</button>
</div>`:errorHtml=`<p style="color: #d9534f;padding:15px;"><b>An error occurred:</b><br>${error.message}</p>`,area.innerHTML=errorHtml;const refreshBtn=area.querySelector("#auth-refresh-btn");refreshBtn&&refreshBtn.addEventListener("click",()=>window.location.reload())}
function updateHeader(caseObject) {const titleEl=document.getElementById("ct-header-title"),subtitleEl=document.getElementById("ct-header-subtitle");caseObject?(titleEl.textContent=caseObject.MainTaxpayerName||"N/A",subtitleEl.textContent=caseObject.CaseNumber||"N/A"):(titleEl.textContent="No Case Selected",subtitleEl.textContent='Please select a case from the "My Cases" tab')}
function updateHeader(caseObject) {
const titleEl = document.getElementById('ct-header-title');
const subtitleEl = document.getElementById('ct-header-subtitle');
const actionsContainer = document.getElementById('ct-header-actions');
actionsContainer.innerHTML = ''; // Clear previous buttons
if (caseObject) {
titleEl.textContent = caseObject.MainTaxpayerName || 'N/A';
subtitleEl.textContent = caseObject.CaseNumber || 'N/A';
const caseId = caseObject.AggregateIdentifier;
const hasValidId = caseId && typeof caseId === 'string' && caseId.trim() !== '';
const disabledAttribute = hasValidId ? '' : 'disabled';
// Create buttons programmatically to attach listeners safely
const openBtn = document.createElement('a');
openBtn.href = `https://coretax.intranet.pajak.go.id/case-management/id-ID/case-overview/${caseId}`;
openBtn.className = 'action-btn open-case';
openBtn.textContent = 'Open';
if (!hasValidId) openBtn.disabled = true;
const docsBtn = document.createElement('button');
docsBtn.className = 'action-btn view-docs';
docsBtn.textContent = 'View Docs';
if (!hasValidId) docsBtn.disabled = true;
docsBtn.addEventListener('click', () => switchTab('tab-docs'));
const usersBtn = document.createElement('button');
usersBtn.className = 'action-btn view-users';
usersBtn.textContent = 'View Users';
if (!hasValidId) usersBtn.disabled = true;
usersBtn.addEventListener('click', () => switchTab('tab-users'));
actionsContainer.append(openBtn, docsBtn, usersBtn);
if (caseObject.CaseTypeName === REFUND_CASE_TYPE_NAME) {
const refundBtn = document.createElement('button');
refundBtn.className = 'action-btn review-refund-case';
refundBtn.textContent = 'Refund Review';
actionsContainer.appendChild(refundBtn);
refundBtn.addEventListener('click', () => startRefundReviewProcess(caseId, refundBtn));
}
} else {
titleEl.textContent = 'No Case Selected';
subtitleEl.textContent = 'Please select a case from the "My Cases" tab';
}
}
async function startRefundReviewProcess(caseId, button) {
const originalText = button.textContent;
button.textContent = '...';
@@ -177,29 +224,32 @@
}
}
function handleCaseAction(event){
const selectedRow=event.target.closest("tr");
if(!selectedRow||selectedRow.classList.contains("group-header"))return;
const caseId=selectedRow.dataset.id;
if(!caseId)return;
const selectedCase=allMyCases.find(e=>e.AggregateIdentifier===caseId);
function handleCaseSelection(event) {
const selectedRow = event.target.closest("tr");
if (!selectedRow || selectedRow.classList.contains("group-header")) return;
const caseId = selectedRow.dataset.id;
if (!caseId || caseId === selectedCaseId) return; // Don't re-process if the same row is clicked
const selectedCase = allMyCases.find(e => e.AggregateIdentifier === caseId);
updateHeader(selectedCase);
// Only reset dependent data if the selection actually changes
if (selectedCaseId !== caseId) {
selectedCaseId=caseId;
loadedDocsForCaseId=null;
loadedUsersForCaseId=null;
// --- FIX IS HERE ---
refundReviewData = [];
filteredRefundData = [];
document.querySelector('#tab-refund .results-container').innerHTML = `<p style="padding:15px;color:#666;">Please use the 'Review Refund' action on a relevant case.</p>`;
document.getElementById('refund-download-btn').disabled = true;
}
const allRows=selectedRow.closest("tbody").querySelectorAll("tr");
allRows.forEach(e=>e.classList.remove("selected"));
selectedCaseId = caseId;
loadedDocsForCaseId = null;
loadedUsersForCaseId = null;
refundReviewData = [];
filteredRefundData = [];
document.querySelector('#tab-refund .results-container').innerHTML = `<p style="padding:15px;color:#666;">Please use the 'Review Refund' action on a relevant case.</p>`;
document.getElementById('refund-download-btn').disabled = true;
const allRows = selectedRow.closest("tbody").querySelectorAll("tr");
allRows.forEach(e => e.classList.remove("selected"));
selectedRow.classList.add("selected");
const actionButton=event.target.closest(".action-btn");
actionButton&&(actionButton.matches(".view-docs")?switchTab("tab-docs"):actionButton.matches(".view-users")?switchTab("tab-users"):actionButton.matches(".review-refund-case")&&startRefundReviewProcess(caseId,actionButton));
const actionButton = event.target.closest(".action-btn");
if (actionButton) {
if (actionButton.matches(".view-docs")) { switchTab("tab-docs"); }
else if (actionButton.matches(".view-users")) { switchTab("tab-users"); }
else if (actionButton.matches(".review-refund-case")) { startRefundReviewProcess(caseId, actionButton); }
}
}
function handleDocumentAction(event) {
const target = event.target.closest('.action-btn');