<div class="data-table-container">
<div class="table-header">
<h2>Employee Directory</h2>
<div class="table-controls">
<div class="search-box">
<input type="text" id="searchInput" placeholder="Search employees..." />
<span class="search-icon">π</span>
</div>
<div class="filter-dropdown">
<select id="departmentFilter">
<option value="">All Departments</option>
<option value="Engineering">Engineering</option>
<option value="Marketing">Marketing</option>
<option value="Sales">Sales</option>
<option value="HR">HR</option>
</select>
</div>
</div>
</div>
<div class="table-wrapper">
<table class="data-table" id="employeeTable">
<thead>
<tr>
<th data-sort="name">Name <span class="sort-icon">β</span></th>
<th data-sort="department">Department <span class="sort-icon">β</span></th>
<th data-sort="position">Position <span class="sort-icon">β</span></th>
<th data-sort="salary">Salary <span class="sort-icon">β</span></th>
<th data-sort="joinDate">Join Date <span class="sort-icon">β</span></th>
</tr>
</thead>
<tbody>
<tr>
<td>John Smith</td>
<td>Engineering</td>
<td>Senior Developer</td>
<td>$95,000</td>
<td>2020-05-15</td>
</tr>
<tr>
<td>Sarah Johnson</td>
<td>Marketing</td>
<td>Marketing Manager</td>
<td>$78,000</td>
<td>2019-03-22</td>
</tr>
<tr>
<td>Mike Davis</td>
<td>Sales</td>
<td>Sales Representative</td>
<td>$65,000</td>
<td>2021-08-10</td>
</tr>
<tr>
<td>Emily Wilson</td>
<td>HR</td>
<td>HR Specialist</td>
<td>$72,000</td>
<td>2020-11-05</td>
</tr>
<tr>
<td>David Brown</td>
<td>Engineering</td>
<td>Frontend Developer</td>
<td>$88,000</td>
<td>2021-01-18</td>
</tr>
<tr>
<td>Lisa Anderson</td>
<td>Marketing</td>
<td>Content Creator</td>
<td>$58,000</td>
<td>2022-04-12</td>
</tr>
</tbody>
</table>
</div>
<div class="table-footer">
<div class="pagination">
<button class="pagination-btn" id="prevPage">Previous</button>
<span class="pagination-info">
Page <span id="currentPage">1</span> of <span id="totalPages">1</span>
</span>
<button class="pagination-btn" id="nextPage">Next</button>
</div>
</div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
.data-table-container {
font-family: 'Inter', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
overflow: hidden;
padding: 30px;
max-width: 1200px;
margin: 0 auto;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
flex-wrap: wrap;
gap: 20px;
}
.table-header h2 {
color: white;
font-size: 28px;
font-weight: 700;
margin: 0;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
.table-controls {
display: flex;
gap: 15px;
align-items: center;
flex-wrap: wrap;
}
.search-box {
position: relative;
display: flex;
align-items: center;
}
.search-box input {
padding: 12px 45px 12px 15px;
border: none;
border-radius: 25px;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
font-size: 14px;
font-weight: 500;
width: 250px;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.search-box input:focus {
outline: none;
background: white;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.search-icon {
position: absolute;
right: 15px;
font-size: 16px;
color: #666;
pointer-events: none;
}
.filter-dropdown select {
padding: 12px 15px;
border: none;
border-radius: 25px;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.filter-dropdown select:focus {
outline: none;
background: white;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.table-wrapper {
background: rgba(255, 255, 255, 0.95);
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
}
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.data-table thead {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.data-table th {
padding: 18px 15px;
text-align: left;
font-weight: 600;
color: white;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
user-select: none;
}
.data-table th:hover {
background: rgba(255, 255, 255, 0.1);
}
.sort-icon {
margin-left: 8px;
opacity: 0.7;
transition: all 0.3s ease;
}
.data-table th.sorted .sort-icon {
opacity: 1;
transform: scale(1.2);
}
.data-table tbody tr {
transition: all 0.3s ease;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.data-table tbody tr:hover {
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.data-table td {
padding: 15px;
color: #333;
font-weight: 500;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
}
.table-footer {
margin-top: 25px;
display: flex;
justify-content: center;
}
.pagination {
display: flex;
align-items: center;
gap: 15px;
background: rgba(255, 255, 255, 0.9);
padding: 12px 25px;
border-radius: 25px;
backdrop-filter: blur(10px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
}
.pagination-btn {
padding: 10px 20px;
border: none;
border-radius: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
}
.pagination-btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
}
.pagination-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.pagination-info {
color: #333;
font-weight: 600;
font-size: 14px;
}
@media (max-width: 768px) {
.data-table-container {
padding: 20px;
}
.table-header {
flex-direction: column;
align-items: stretch;
}
.table-controls {
justify-content: center;
}
.search-box input {
width: 200px;
}
.data-table {
font-size: 12px;
}
.data-table th,
.data-table td {
padding: 10px 8px;
}
}
class DataTable {
constructor() {
this.data = [
{ name: 'John Smith', department: 'Engineering', position: 'Senior Developer', salary: 95000, joinDate: '2020-05-15' },
{ name: 'Sarah Johnson', department: 'Marketing', position: 'Marketing Manager', salary: 78000, joinDate: '2019-03-22' },
{ name: 'Mike Davis', department: 'Sales', position: 'Sales Representative', salary: 65000, joinDate: '2021-08-10' },
{ name: 'Emily Wilson', department: 'HR', position: 'HR Specialist', salary: 72000, joinDate: '2020-11-05' },
{ name: 'David Brown', department: 'Engineering', position: 'Frontend Developer', salary: 88000, joinDate: '2021-01-18' },
{ name: 'Lisa Anderson', department: 'Marketing', position: 'Content Creator', salary: 58000, joinDate: '2022-04-12' },
{ name: 'Robert Taylor', department: 'Engineering', position: 'Backend Developer', salary: 92000, joinDate: '2020-09-30' },
{ name: 'Jennifer White', department: 'Sales', position: 'Sales Manager', salary: 85000, joinDate: '2019-07-14' },
{ name: 'Michael Garcia', department: 'HR', position: 'HR Manager', salary: 90000, joinDate: '2018-12-03' },
{ name: 'Amanda Martinez', department: 'Marketing', position: 'Digital Marketing Specialist', salary: 62000, joinDate: '2021-11-20' }
];
this.filteredData = [...this.data];
this.currentSort = { field: null, direction: 'asc' };
this.currentPage = 1;
this.itemsPerPage = 5;
this.init();
}
init() {
this.setupEventListeners();
this.renderTable();
this.updatePagination();
}
setupEventListeners() {
// Search functionality
const searchInput = document.getElementById('searchInput');
searchInput.addEventListener('input', (e) => {
this.filterData(e.target.value, document.getElementById('departmentFilter').value);
});
// Department filter
const departmentFilter = document.getElementById('departmentFilter');
departmentFilter.addEventListener('change', (e) => {
this.filterData(document.getElementById('searchInput').value, e.target.value);
});
// Sorting
const headers = document.querySelectorAll('[data-sort]');
headers.forEach(header => {
header.addEventListener('click', () => {
this.sortData(header.dataset.sort);
});
});
// Pagination
document.getElementById('prevPage').addEventListener('click', () => {
if (this.currentPage > 1) {
this.currentPage--;
this.renderTable();
this.updatePagination();
}
});
document.getElementById('nextPage').addEventListener('click', () => {
const totalPages = Math.ceil(this.filteredData.length / this.itemsPerPage);
if (this.currentPage < totalPages) {
this.currentPage++;
this.renderTable();
this.updatePagination();
}
});
}
filterData(searchTerm, department) {
this.filteredData = this.data.filter(item => {
const matchesSearch = searchTerm === '' ||
Object.values(item).some(value =>
value.toString().toLowerCase().includes(searchTerm.toLowerCase())
);
const matchesDepartment = department === '' || item.department === department;
return matchesSearch && matchesDepartment;
});
this.currentPage = 1;
this.renderTable();
this.updatePagination();
}
sortData(field) {
const direction = this.currentSort.field === field && this.currentSort.direction === 'asc' ? 'desc' : 'asc';
this.filteredData.sort((a, b) => {
let aValue = a[field];
let bValue = b[field];
// Handle different data types
if (field === 'salary') {
aValue = parseInt(aValue);
bValue = parseInt(bValue);
} else if (field === 'joinDate') {
aValue = new Date(aValue);
bValue = new Date(bValue);
} else {
aValue = aValue.toString().toLowerCase();
bValue = bValue.toString().toLowerCase();
}
if (direction === 'asc') {
return aValue > bValue ? 1 : -1;
} else {
return aValue < bValue ? 1 : -1;
}
});
this.currentSort = { field, direction };
this.updateSortIcons();
this.renderTable();
}
updateSortIcons() {
// Reset all sort icons
document.querySelectorAll('[data-sort]').forEach(header => {
header.classList.remove('sorted');
const icon = header.querySelector('.sort-icon');
icon.textContent = 'β';
});
// Update current sort icon
if (this.currentSort.field) {
const currentHeader = document.querySelector(`[data-sort="${this.currentSort.field}"]`);
currentHeader.classList.add('sorted');
const icon = currentHeader.querySelector('.sort-icon');
icon.textContent = this.currentSort.direction === 'asc' ? 'β' : 'β';
}
}
renderTable() {
const tbody = document.querySelector('#employeeTable tbody');
const startIndex = (this.currentPage - 1) * this.itemsPerPage;
const endIndex = startIndex + this.itemsPerPage;
const pageData = this.filteredData.slice(startIndex, endIndex);
tbody.innerHTML = pageData.map(item => `
<tr>
<td>${item.name}</td>
<td>${item.department}</td>
<td>${item.position}</td>
<td>$${item.salary.toLocaleString()}</td>
<td>${item.joinDate}</td>
</tr>
`).join('');
}
updatePagination() {
const totalPages = Math.ceil(this.filteredData.length / this.itemsPerPage);
document.getElementById('currentPage').textContent = this.currentPage;
document.getElementById('totalPages').textContent = totalPages;
document.getElementById('prevPage').disabled = this.currentPage === 1;
document.getElementById('nextPage').disabled = this.currentPage === totalPages || totalPages === 0;
}
}
// Initialize the data table when the page loads
document.addEventListener('DOMContentLoaded', () => {
new DataTable();
});