Remove all Alpine.js calls to fix memory leaks
- Replace reactive watchers with explicit method calls - Add setFilterKey() and setFilterTable() methods for manual updates - Update sort(), nextPage(), prevPage() to trigger computations - Update templates to use new setter methods - Compute derived data explicitly after data loading
This commit is contained in:
parent
e947fc74d4
commit
8d762261d4
@ -12,35 +12,35 @@
|
|||||||
|
|
||||||
<!-- Status Filters -->
|
<!-- Status Filters -->
|
||||||
<div class="join shadow-sm bg-base-100 rounded-lg">
|
<div class="join shadow-sm bg-base-100 rounded-lg">
|
||||||
<button @click="filterKey = 'Total'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Total' ? 'btn-active btn-neutral text-white' : 'btn-ghost'"
|
:class="filterKey === 'Total' ? 'btn-active btn-neutral text-white' : 'btn-ghost'"
|
||||||
class="btn btn-sm join-item">
|
class="btn btn-sm join-item">
|
||||||
All <span class="badge badge-sm badge-ghost ml-1" x-text="counters.Total"></span>
|
All <span class="badge badge-sm badge-ghost ml-1" x-text="counters.Total"></span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="filterKey = 'Pend'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Pend' ? 'btn-active btn-status-pend' : 'btn-ghost'"
|
:class="filterKey === 'Pend' ? 'btn-active btn-status-pend' : 'btn-ghost'"
|
||||||
class="btn btn-sm join-item">
|
class="btn btn-sm join-item">
|
||||||
Pending <span class="badge badge-sm badge-status-pend ml-1" x-text="counters.Pend"></span>
|
Pending <span class="badge badge-sm badge-status-pend ml-1" x-text="counters.Pend"></span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="filterKey = 'Coll'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Coll' ? 'btn-active btn-status-coll' : 'btn-ghost'"
|
:class="filterKey === 'Coll' ? 'btn-active btn-status-coll' : 'btn-ghost'"
|
||||||
class="btn btn-sm join-item">
|
class="btn btn-sm join-item">
|
||||||
Coll <span class="badge badge-sm badge-status-coll ml-1" x-text="counters.Coll"></span>
|
Coll <span class="badge badge-sm badge-status-coll ml-1" x-text="counters.Coll"></span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="filterKey = 'Recv'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Recv' ? 'btn-active btn-status-recv' : 'btn-ghost'" class="btn btn-sm join-item">
|
:class="filterKey === 'Recv' ? 'btn-active btn-status-recv' : 'btn-ghost'" class="btn btn-sm join-item">
|
||||||
Recv <span class="badge badge-sm badge-status-recv ml-1" x-text="counters.Recv"></span>
|
Recv <span class="badge badge-sm badge-status-recv ml-1" x-text="counters.Recv"></span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="filterKey = 'Inc'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Inc' ? 'btn-active btn-status-inc' : 'btn-ghost'" class="btn btn-sm join-item">
|
:class="filterKey === 'Inc' ? 'btn-active btn-status-inc' : 'btn-ghost'" class="btn btn-sm join-item">
|
||||||
Inc <span class="badge badge-sm badge-status-inc ml-1" x-text="counters.Inc"></span>
|
Inc <span class="badge badge-sm badge-status-inc ml-1" x-text="counters.Inc"></span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="filterKey = 'Fin'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Fin' ? 'btn-active btn-status-fin' : 'btn-ghost'"
|
:class="filterKey === 'Fin' ? 'btn-active btn-status-fin' : 'btn-ghost'"
|
||||||
class="btn btn-sm join-item">
|
class="btn btn-sm join-item">
|
||||||
Fin <span class="badge badge-sm badge-status-fin ml-1" x-text="counters.Fin"></span>
|
Fin <span class="badge badge-sm badge-status-fin ml-1" x-text="counters.Fin"></span>
|
||||||
</button>
|
</button>
|
||||||
<button @click="filterKey = 'Validated'"
|
<button @click="setFilterKey('$1')"
|
||||||
:class="filterKey === 'Validated' ? 'btn-active btn-primary text-white' : 'btn-ghost'"
|
:class="filterKey === 'Validated' ? 'btn-active btn-primary text-white' : 'btn-ghost'"
|
||||||
class="btn btn-sm join-item">
|
class="btn btn-sm join-item">
|
||||||
Val <span class="badge badge-sm badge-primary ml-1" x-text="validatedCount"></span>
|
Val <span class="badge badge-sm badge-primary ml-1" x-text="validatedCount"></span>
|
||||||
@ -70,7 +70,7 @@
|
|||||||
<div class="form-control w-full md:w-auto">
|
<div class="form-control w-full md:w-auto">
|
||||||
<label class='input input-sm input-bordered'>
|
<label class='input input-sm input-bordered'>
|
||||||
<i class="fa fa-filter"></i>
|
<i class="fa fa-filter"></i>
|
||||||
<input type="text" placeholder="Type to filter..." x-model="filterTable" />
|
<input type="text" placeholder="Type to filter..." x-model="filterTable" @input.debounce.300ms="setFilterTable(filterTable)" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -42,7 +42,7 @@
|
|||||||
<div class="form-control w-full md:w-auto">
|
<div class="form-control w-full md:w-auto">
|
||||||
<label class="input input-sm input-bordered">
|
<label class="input input-sm input-bordered">
|
||||||
<i class="fa fa-filter"></i>
|
<i class="fa fa-filter"></i>
|
||||||
<input type="text" placeholder="Type to filter..." x-model="filterTable" />
|
<input type="text" placeholder="Type to filter..." x-model="filterTable" @input.debounce.300ms="setFilterTable(filterTable)" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -61,14 +61,39 @@ document.addEventListener('alpine:init', () => {
|
|||||||
this.sortCol = col;
|
this.sortCol = col;
|
||||||
this.sortAsc = true;
|
this.sortAsc = true;
|
||||||
}
|
}
|
||||||
|
this.computeSorted();
|
||||||
|
this.computePaginated();
|
||||||
},
|
},
|
||||||
|
|
||||||
nextPage() {
|
nextPage() {
|
||||||
if (this.currentPage < this.totalPages) this.currentPage++;
|
if (this.currentPage < this.totalPages) {
|
||||||
|
this.currentPage++;
|
||||||
|
this.computePaginated();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
prevPage() {
|
prevPage() {
|
||||||
if (this.currentPage > 1) this.currentPage--;
|
if (this.currentPage > 1) {
|
||||||
|
this.currentPage--;
|
||||||
|
this.computePaginated();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setFilterKey(key) {
|
||||||
|
this.filterKey = key;
|
||||||
|
this.computeFiltered();
|
||||||
|
this.computeSorted();
|
||||||
|
this.computeTotalPages();
|
||||||
|
this.computePaginated();
|
||||||
|
},
|
||||||
|
|
||||||
|
setFilterTable(value) {
|
||||||
|
this.filterTable = value;
|
||||||
|
this.currentPage = 1;
|
||||||
|
this.computeFiltered();
|
||||||
|
this.computeSorted();
|
||||||
|
this.computeTotalPages();
|
||||||
|
this.computePaginated();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Compute methods - called only when dependencies change
|
// Compute methods - called only when dependencies change
|
||||||
@ -120,32 +145,6 @@ document.addEventListener('alpine:init', () => {
|
|||||||
const defaultPrinter = '<?= $config[session()->get("userrole")]["sampleDialog"]["defaultPrinter"] ?? "lab" ?>';
|
const defaultPrinter = '<?= $config[session()->get("userrole")]["sampleDialog"]["defaultPrinter"] ?? "lab" ?>';
|
||||||
this.selectedPrinter = defaultPrinter || 'lab';
|
this.selectedPrinter = defaultPrinter || 'lab';
|
||||||
|
|
||||||
// Watchers for reactive updates
|
|
||||||
this.$watch('list', () => {
|
|
||||||
this.computeFiltered();
|
|
||||||
this.computeValidatedCount();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$watch('filterKey', () => this.computeFiltered());
|
|
||||||
this.$watch('filterTable', () => {
|
|
||||||
this.currentPage = 1;
|
|
||||||
this.computeFiltered();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$watch('filtered', () => {
|
|
||||||
this.computeSorted();
|
|
||||||
this.computeTotalPages();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$watch('sortCol', () => this.computeSorted());
|
|
||||||
this.$watch('sortAsc', () => this.computeSorted());
|
|
||||||
this.$watch('sorted', () => this.computePaginated());
|
|
||||||
this.$watch('currentPage', () => this.computePaginated());
|
|
||||||
|
|
||||||
this.$watch('auditData', () => {
|
|
||||||
this.computeAuditEvents();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial load only - no auto-refresh
|
// Initial load only - no auto-refresh
|
||||||
this.fetchList();
|
this.fetchList();
|
||||||
},
|
},
|
||||||
@ -175,6 +174,9 @@ document.addEventListener('alpine:init', () => {
|
|||||||
let codeB = statusOrder[b.STATS] ?? 0;
|
let codeB = statusOrder[b.STATS] ?? 0;
|
||||||
return codeA - codeB;
|
return codeA - codeB;
|
||||||
});
|
});
|
||||||
|
// Compute derived data after list is loaded
|
||||||
|
this.computeFiltered();
|
||||||
|
this.computeValidatedCount();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -29,14 +29,31 @@ document.addEventListener('alpine:init', () => {
|
|||||||
this.sortCol = col;
|
this.sortCol = col;
|
||||||
this.sortAsc = true;
|
this.sortAsc = true;
|
||||||
}
|
}
|
||||||
|
this.computeUnvalidatedSorted();
|
||||||
|
this.computeUnvalidatedPaginated();
|
||||||
},
|
},
|
||||||
|
|
||||||
nextPage() {
|
nextPage() {
|
||||||
if (this.currentPage < this.unvalidatedTotalPages) this.currentPage++;
|
if (this.currentPage < this.unvalidatedTotalPages) {
|
||||||
|
this.currentPage++;
|
||||||
|
this.computeUnvalidatedPaginated();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
prevPage() {
|
prevPage() {
|
||||||
if (this.currentPage > 1) this.currentPage--;
|
if (this.currentPage > 1) {
|
||||||
|
this.currentPage--;
|
||||||
|
this.computeUnvalidatedPaginated();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setFilterTable(value) {
|
||||||
|
this.filterTable = value;
|
||||||
|
this.currentPage = 1;
|
||||||
|
this.computeUnvalidatedFiltered();
|
||||||
|
this.computeUnvalidatedSorted();
|
||||||
|
this.computeUnvalidatedTotalPages();
|
||||||
|
this.computeUnvalidatedPaginated();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Compute methods - called only when dependencies change
|
// Compute methods - called only when dependencies change
|
||||||
@ -82,35 +99,6 @@ document.addEventListener('alpine:init', () => {
|
|||||||
this.filter.date1 = this.today;
|
this.filter.date1 = this.today;
|
||||||
this.filter.date2 = this.today;
|
this.filter.date2 = this.today;
|
||||||
|
|
||||||
this.$watch('filterTable', () => {
|
|
||||||
this.currentPage = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Watchers for reactive updates
|
|
||||||
this.$watch('unvalidatedList', () => {
|
|
||||||
this.computeUnvalidatedFiltered();
|
|
||||||
this.computeUnvalidatedCount();
|
|
||||||
});
|
|
||||||
this.$watch('filterTable', () => {
|
|
||||||
this.computeUnvalidatedFiltered();
|
|
||||||
});
|
|
||||||
this.$watch('unvalidatedFiltered', () => {
|
|
||||||
this.computeUnvalidatedSorted();
|
|
||||||
this.computeUnvalidatedTotalPages();
|
|
||||||
});
|
|
||||||
this.$watch('sortCol', () => {
|
|
||||||
this.computeUnvalidatedSorted();
|
|
||||||
});
|
|
||||||
this.$watch('sortAsc', () => {
|
|
||||||
this.computeUnvalidatedSorted();
|
|
||||||
});
|
|
||||||
this.$watch('unvalidatedSorted', () => {
|
|
||||||
this.computeUnvalidatedPaginated();
|
|
||||||
});
|
|
||||||
this.$watch('currentPage', () => {
|
|
||||||
this.computeUnvalidatedPaginated();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial load only - no auto-refresh
|
// Initial load only - no auto-refresh
|
||||||
this.fetchUnvalidated();
|
this.fetchUnvalidated();
|
||||||
|
|
||||||
@ -137,6 +125,12 @@ document.addEventListener('alpine:init', () => {
|
|||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
}).then(res => res.json()).then(data => {
|
}).then(res => res.json()).then(data => {
|
||||||
this.unvalidatedList = data.data ?? [];
|
this.unvalidatedList = data.data ?? [];
|
||||||
|
// Compute derived data after list is loaded
|
||||||
|
this.computeUnvalidatedFiltered();
|
||||||
|
this.computeUnvalidatedCount();
|
||||||
|
this.computeUnvalidatedSorted();
|
||||||
|
this.computeUnvalidatedTotalPages();
|
||||||
|
this.computeUnvalidatedPaginated();
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user