// widgets/StudentTableWidget.ts import { Widget } from '../components/Widget'; import { createElement, navigateTo } from '../utils/utils'; import { globalAPI, ApiResponse, StudentListData } from '../api/api'; export class StudentTableWidget extends Widget { private students: StudentListData[] = []; private yearFilter: string = 'all'; private courseFilter: string = 'all'; private availableYears: string[] = ['all', '1', '2', '3', '4']; private availableCourses: string[] = ['all', 'Math', 'Science', 'History', 'English']; constructor() { super(); this.fetchStudentData(); } async fetchStudentData() { try { const response: ApiResponse = await globalAPI.getStudentList(); if (response.success && response.data) { this.students = response.data; this.render(); } else { console.error("Failed to fetch student list"); } } catch (error) { console.error("Error fetching student list:", error); } } render(): HTMLElement { this.container.innerHTML = ''; const header = createElement('div'); header.classList.add('widget-header'); header.textContent = 'Manage Students'; this.container.appendChild(header); const widgetBody = createElement('div'); widgetBody.classList.add('widget-body'); // Filters const filtersRow = createElement('div'); filtersRow.classList.add('row', 'mb-3', 'g-3', 'align-items-center'); // Year Level Filter const yearFilterCol = createElement('div'); yearFilterCol.classList.add('col-auto'); const yearFilterLabel = createElement('label') as HTMLLabelElement; // Cast first yearFilterLabel.classList.add('col-form-label', 'me-2'); yearFilterLabel.htmlFor = 'yearLevelFilter'; // Set htmlFor as property yearFilterLabel.textContent = 'Year Level:'; const yearFilterSelect = createElement('select') as HTMLSelectElement; yearFilterSelect.classList.add('form-select'); yearFilterSelect.id = 'yearLevelFilter'; this.availableYears.forEach(year => { const option = createElement('option'); option.value = year; option.textContent = year === 'all' ? 'All Years' : `Year ${year}`; yearFilterSelect.appendChild(option); }); yearFilterSelect.value = this.yearFilter; yearFilterSelect.addEventListener('change', (e) => { this.yearFilter = (e.target as HTMLSelectElement).value; this.renderTable(widgetBody); }); yearFilterCol.appendChild(yearFilterLabel); yearFilterCol.appendChild(yearFilterSelect); filtersRow.appendChild(yearFilterCol); // Course Filter const courseFilterCol = createElement('div'); courseFilterCol.classList.add('col-auto'); const courseFilterLabel = createElement('label') as HTMLLabelElement; // Cast first courseFilterLabel.classList.add('col-form-label', 'me-2'); courseFilterLabel.htmlFor = 'courseFilter'; // Set htmlFor as property courseFilterLabel.textContent = 'Course:'; const courseFilterSelect = createElement('select') as HTMLSelectElement; courseFilterSelect.classList.add('form-select'); courseFilterSelect.id = 'courseFilter'; this.availableCourses.forEach(course => { const option = createElement('option'); option.value = course; option.textContent = course === 'all' ? 'All Courses' : course; courseFilterSelect.appendChild(option); }); courseFilterSelect.value = this.courseFilter; courseFilterSelect.addEventListener('change', (e) => { this.courseFilter = (e.target as HTMLSelectElement).value; this.renderTable(widgetBody); }); courseFilterCol.appendChild(courseFilterLabel); courseFilterCol.appendChild(courseFilterSelect); filtersRow.appendChild(courseFilterCol); widgetBody.appendChild(filtersRow); // Table Container const tableContainer = createElement('div'); widgetBody.appendChild(tableContainer); this.renderTable(tableContainer); // "Add" button and Batch Add const addButtonRow = createElement('div'); addButtonRow.classList.add('row', 'mt-3', 'justify-content-between', 'align-items-center'); const addButtonCol = createElement('div'); addButtonCol.classList.add('col-auto'); const addButton = createElement('button'); addButton.classList.add('btn', 'btn-success', 'btn-sm', 'me-2'); addButton.textContent = 'Add Student'; addButtonCol.appendChild(addButton); addButtonRow.appendChild(addButtonCol); const batchAddCol = createElement('div'); batchAddCol.classList.add('col-auto'); const batchAddLink = createElement('a'); batchAddLink.href = '#/batch-add-students'; batchAddLink.textContent = 'Batch Add Students'; batchAddCol.appendChild(batchAddLink); addButtonRow.appendChild(batchAddCol); widgetBody.appendChild(addButtonRow); this.container.appendChild(widgetBody); return this.container; } private renderTable(container: HTMLElement) { container.innerHTML = ''; const table = createElement('table'); table.classList.add('table', 'table-striped', 'table-bordered'); const thead = createElement('thead'); thead.innerHTML = ` ID Name Year Level Courses Actions `; table.appendChild(thead); const tbody = createElement('tbody'); const filteredStudents = this.students.filter(student => { const yearMatch = this.yearFilter === 'all' || student.yearLevel === this.yearFilter; const courseMatch = this.courseFilter === 'all' || student.courses.includes(this.courseFilter); return yearMatch && courseMatch; }); filteredStudents.forEach(student => { const row = createElement('tr'); row.innerHTML = ` ${student.id} ${student.name} ${student.yearLevel} ${student.courses.join(', ')} `; tbody.appendChild(row); }); table.appendChild(tbody); container.appendChild(table); this.attachTableEventListeners(table); } private attachTableEventListeners(table: HTMLTableElement) { table.querySelectorAll('.view-profile-btn').forEach(button => { button.addEventListener('click', (event) => { const studentId = (event.target as HTMLElement).dataset.studentId; if (studentId) { navigateTo(`/profile?studentId=${studentId}`); } }); }); table.querySelectorAll('.enroll-btn').forEach(button => { button.addEventListener('click', (event) => { const studentId = (event.target as HTMLElement).dataset.studentId; if (studentId) { alert(`Enroll functionality for student ID ${studentId} - Not fully implemented in prototype.`); } }); }); } }