<!-- expenseTrackerLWC.html -->
<template>
<div class="container">
<!-- Filter Section -->
<div class="filter-section">
<div class="slds-grid slds-gutters">
<!-- Picklist for object selection -->
<div class="slds-col">
<lightning-combobox
label="Select Object"
value={selectedObject}
options={objectOptions}
onchange={handleObjectChange}
></lightning-combobox>
</div>
<!-- Search input -->
<div class="slds-col">
<lightning-input
type="text"
label="Search"
value={searchKey}
onchange={handleSearchKeyChange}
></lightning-input>
</div>
</div>
</div>
<!-- Table Section -->
<div class="table-section">
<table class="slds-table slds-table_bordered slds-table_cell-buffer slds-table_col-bordered">
<thead>
<tr>
<th>Expense Code</th>
<th>Expense Type</th>
<th>Name</th>
<th>Link</th>
</tr>
</thead>
<tbody>
<template for:each={data} for:item="item" for:index="index">
<tr key={item.id}>
<td>{item.expenseCode}</td>
<td>{item.expenseType}</td>
<td>{item.name}</td>
<td>
<a href={item.link} target="_blank" rel="noopener noreferrer">
View Record
</a>
</td>
</tr>
</template>
</tbody>
</table>
</div>
<!-- Pagination Section -->
<div class="pagination-section">
<lightning-layout>
<lightning-layout-item size="6">
<!-- Previous button -->
<lightning-button-icon
icon-name="utility:left"
variant="bare"
onclick={handlePrevious}
disabled={currentPage === 1}
></lightning-button-icon>
</lightning-layout-item>
<lightning-layout-item size="6">
<!-- Next button -->
<lightning-button-icon
icon-name="utility:right"
variant="bare"
onclick={handleNext}
disabled={currentPage === totalPages}
></lightning-button-icon>
</lightning-layout-item>
</lightning-layout>
<!-- Picklist for records per page -->
<lightning-combobox
label="Records per Page"
value={pageSize}
options={pageSizeOptions}
onchange={handlePageSizeChange}
></lightning-combobox>
</div>
</div>
</template>
// expenseTrackerLWC.js
import { LightningElement, track, wire } from ‘lwc’;
import getExpenses from ‘@salesforce/apex/ExpenseTrackerController.getExpenses’;
export default class ExpenseTrackerLWC extends LightningElement {
@track data = []; // Data to display in the table
@track currentPage = 1;
@track pageSize = 10; // Number of records to display per page
@track totalRecords = 0;
@track selectedObject = ‘Account’; // Default selected object
@track searchKey = ”;
// Define options for the object picklist
objectOptions = [
{ label: ‘Account’, value: ‘Account’ },
{ label: ‘Opportunity’, value: ‘Opportunity’ },
{ label: ‘HR_Team__c’, value: ‘HR_Team__c’ }
];
// Define options for the records per page picklist
pageSizeOptions = [
{ label: ’10’, value: 10 },
{ label: ’25’, value: 25 },
{ label: ’50’, value: 50 }
];
// Fetch data from Apex on component initialization
@wire(getExpenses, {
pageNumber: ‘$currentPage’,
pageSize: ‘$pageSize’,
selectedObject: ‘$selectedObject’,
searchKey: ‘$searchKey’
})
wiredExpenses({ error, data }) {
if (data) {
this.data = data.records;
this.totalRecords = data.totalRecords;
} else if (error) {
// Handle error
}
}
// Handle object selection change
handleObjectChange(event) {
this.selectedObject = event.detail.value;
this.currentPage = 1; // Reset to the first page when changing objects
}
// Handle search input change
handleSearchKeyChange(event) {
this.searchKey = event.detail.value;
this.currentPage = 1; // Reset to the first page when searching
}
// Handle pagination – Next button
handleNext() {
if (this.currentPage < this.totalPages) {
this.currentPage++;
}
}
// Handle pagination – Previous button
handlePrevious() {
if (this.currentPage > 1) {
this.currentPage–;
}
}
// Handle records per page picklist change
handlePageSizeChange(event) {
this.pageSize = event.detail.value;
this.currentPage = 1; // Reset to the first page when changing page size
}
// Calculate total pages for pagination
get totalPages() {
return Math.ceil(this.totalRecords / this.pageSize);
}
}
public with sharing class ExpenseTrackerController { @AuraEnabled(cacheable=true) public static ExpenseDataWrapper getExpenses(Integer pageNumber, Integer pageSize, String selectedObject, String searchKey) { // Define a wrapper class to hold the results ExpenseDataWrapper result = new ExpenseDataWrapper(); // Determine the object to query based on selectedObject String objectToQuery = ‘Account’; if (selectedObject == ‘Opportunity’) { objectToQuery = ‘Opportunity’; } else if (selectedObject == ‘HR_Team__c’) { objectToQuery = ‘HR_Team__c’; } // Build the SOQL query String query = ‘SELECT Id, Expense_Code__c, Name, Link__c FROM ‘ + objectToQuery; // Apply search filter if searchKey is provided if (!String.isEmpty(searchKey)) { query += ‘ WHERE (Expense_Code__c LIKE :searchKey OR Name LIKE :searchKey)’; } // Execute the query with pagination result.records = Database.query(query + ‘ LIMIT :pageSize OFFSET :offset’); // Get the total count of records (without pagination) Integer totalCount = [SELECT COUNT() FROM ‘ + objectToQuery + ‘ WHERE (Expense_Code__c LIKE :searchKey OR Name LIKE :searchKey)’]; result.totalRecords = totalCount; return result; } // Wrapper class to hold query results and total record count public class ExpenseDataWrapper { @AuraEnabled public List<Expense__c> records { get; set; } @AuraEnabled public Integer totalRecords { get; set; } }}