async function loadTests() {loading=true;try{constparams={page: currentPage,perPage};if(selectedType)params.TestType=selectedType;if(searchQuery.trim())params.search=searchQuery.trim();constresponse=awaitfetchTests(params);letallTests=Array.isArray(response.data)?response.data:[];allTests=allTests.filter(test=>test.IsActive!=='0'&&test.IsActive!==0);tests=allTests;if(response.pagination){totalItems=response.pagination.total||0;totalPages=Math.ceil(totalItems/perPage)||1;}selectedRowIndex=-1;}catch(err){toastError(err.message||'Failed to load tests');tests=[];}finally{loading=false;}}
async function loadDisciplines() {try{constresponse=awaitfetchDisciplines();disciplines=Array.isArray(response.data)?response.data:[];}catch(err){disciplines=[];}}
async function loadDepartments() {try{constresponse=awaitfetchDepartments();departments=Array.isArray(response.data)?response.data:[];}catch(err){departments=[];}}
function handleKeydown(e) {if(e.key==='/'&&!modalOpen&&!deleteModalOpen){e.preventDefault();searchInputRef?.focus();return;}if(e.key==='Escape'){if(modalOpen)modalOpen=false;elseif(deleteModalOpen)deleteModalOpen=false;return;}if(!modalOpen&&!deleteModalOpen&&document.activeElement===document.body){constvisibleTests=getVisibleTests();if(e.key==='ArrowDown'&&selectedRowIndex<visibleTests.length-1)selectedRowIndex++;elseif(e.key==='ArrowUp'&&selectedRowIndex>0)selectedRowIndex--;elseif(e.key==='Enter'&&selectedRowIndex>=0)openEditModal(visibleTests[selectedRowIndex]);}}
function getVisibleTests() {returntests.filter(t=>t.IsActive!=='0'&&t.IsActive!==0);}
function getTestTypeConfig(type) {returntestTypeConfig[type]||testTypeConfig.TEST;}
function formatReferenceRange(test) {return'-';}
function openCreateModal() {modalMode='create';formData={TestSiteID: null,TestSiteCode:'',TestSiteName:'',TestType:'TEST',DisciplineID: null,DepartmentID: null,SeqScr:'0',SeqRpt:'0',VisibleScr: true,VisibleRpt: true,Unit:'',Formula:'',refnum:[],refthold:[],reftxt:[],refvset:[],refRangeType:'none'};modalOpen=true;}
if (canHaveFormula && !formData.Formula.trim()) {toastError('Formula is required for calculated tests');return;}
if (formData.refRangeType === 'num') {for(leti=0;i<formData.refnum.length;i++){consterrors=validateNumericRange(formData.refnum[i],i);if(errors.length>0){toastError(errors[0]);return;}}}
else if (formData.refRangeType === 'thold') {for(leti=0;i<formData.refthold.length;i++){consterrors=validateTholdRange(formData.refthold[i],i);if(errors.length>0){toastError(errors[0]);return;}}}
else if (formData.refRangeType === 'text') {for(leti=0;i<formData.reftxt.length;i++){consterrors=validateTextRange(formData.reftxt[i],i);if(errors.length>0){toastError(errors[0]);return;}}}
else if (formData.refRangeType === 'vset') {for(leti=0;i<formData.refvset.length;i++){consterrors=validateVsetRange(formData.refvset[i],i);if(errors.length>0){toastError(errors[0]);return;}}}
saving = true; try {constpayload={...formData};if(!canHaveUnit)deletepayload.Unit;if(!canHaveFormula)deletepayload.Formula;if(!canHaveRefRange){deletepayload.refnum;deletepayload.refthold;deletepayload.reftxt;deletepayload.refvset;}deletepayload.refRangeType;if(modalMode==='create'){awaitcreateTest(payload);toastSuccess('Test created successfully');}else{awaitupdateTest(payload);toastSuccess('Test updated successfully');}modalOpen=false;awaitloadTests();} catch (err) {toastError(err.message||'Failed to save test');} finally {saving=false;}
}
function openDeleteModal(row) {testToDelete=row;deleteModalOpen=true;}
async function handleDelete() {if(!testToDelete?.TestSiteID)return;deleting=true;try{awaitdeleteTest(testToDelete.TestSiteID);toastSuccess('Test deleted successfully');deleteModalOpen=false;testToDelete=null;awaitloadTests();}catch(err){toastError(err.message||'Failed to delete test');}finally{deleting=false;}}
function handleFilter() {currentPage=1;loadTests();}
function handleSearch() {currentPage=1;loadTests();}
function handlePageChange(newPage) {if(newPage>=1&&newPage<=totalPages){currentPage=newPage;selectedRowIndex=-1;loadTests();}}
function handleRowClick(index) {selectedRowIndex=index;}
function toggleGroup(testId) {if(expandedGroups.has(testId))expandedGroups.delete(testId);elseexpandedGroups.add(testId);expandedGroups=newSet(expandedGroups);}
<inputtype="text"placeholder="Search by code or name..."class="input input-bordered w-full pl-10"bind:value={searchQuery}bind:this={searchInputRef}onkeydown={(e)=>e.key==='Enter'&&handleSearch()}/>