// Main JavaScript for Peer Standard School of Maids
// API Configuration
const API_BASE_URL = '/api';
let authToken = localStorage.getItem('authToken');
// API Helper Functions
const api = {
async request(endpoint, options = {}) {
const url = `${API_BASE_URL}${endpoint}`;
const config = {
headers: {
'Content-Type': 'application/json',
...(authToken && { 'Authorization': `Bearer ${authToken}` }),
...options.headers,
},
...options,
};
try {
const response = await fetch(url, config);
const data = await response.json();
if (!response.ok) {
throw new Error(data.detail || 'An error occurred');
}
return data;
} catch (error) {
console.error('API Error:', error);
showNotification(error.message, 'error');
throw error;
}
},
async get(endpoint) {
return this.request(endpoint, { method: 'GET' });
},
async post(endpoint, data) {
return this.request(endpoint, {
method: 'POST',
body: JSON.stringify(data),
});
},
async put(endpoint, data) {
return this.request(endpoint, {
method: 'PUT',
body: JSON.stringify(data),
});
},
async delete(endpoint) {
return this.request(endpoint, { method: 'DELETE' });
},
// Authentication
async login(username, password) {
const response = await this.post('/token/', { username, password });
authToken = response.access;
localStorage.setItem('authToken', authToken);
return response;
},
async logout() {
authToken = null;
localStorage.removeItem('authToken');
},
// User Management
async getCurrentUser() {
return this.get('/accounts/users/me/');
},
async updateProfile(data) {
return this.put('/accounts/users/update_profile/', data);
},
// Courses
async getCourses(params = {}) {
const queryString = new URLSearchParams(params).toString();
return this.get(`/courses/courses/${queryString ? '?' + queryString : ''}`);
},
async getCourse(id) {
return this.get(`/courses/courses/${id}/`);
},
// Students
async getStudents(params = {}) {
const queryString = new URLSearchParams(params).toString();
return this.get(`/students/students/${queryString ? '?' + queryString : ''}`);
},
async getMyCourses() {
return this.get('/students/students/me/enrollments/');
},
// Employers
async getJobPostings(params = {}) {
const queryString = new URLSearchParams(params).toString();
return this.get(`/employers/job-postings/${queryString ? '?' + queryString : ''}`);
},
async applyForJob(jobId, data) {
return this.post(`/employers/job-postings/${jobId}/apply/`, data);
},
// Certificates
async getMyCertificates() {
return this.get('/certifications/certificates/');
},
async verifyCertificate(code) {
return this.get(`/certifications/certificates/verify/?code=${code}`);
}
};
document.addEventListener('DOMContentLoaded', function() {
// Mobile menu toggle
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if (mobileMenuButton && mobileMenu) {
mobileMenuButton.addEventListener('click', function() {
const icon = this.querySelector('i');
if (mobileMenu.classList.contains('hidden')) {
mobileMenu.classList.remove('hidden');
icon.classList.remove('fa-bars');
icon.classList.add('fa-times');
} else {
mobileMenu.classList.add('hidden');
icon.classList.remove('fa-times');
icon.classList.add('fa-bars');
}
});
// Close mobile menu when clicking outside
document.addEventListener('click', function(event) {
if (!mobileMenu.contains(event.target) && !mobileMenuButton.contains(event.target)) {
mobileMenu.classList.add('hidden');
const icon = mobileMenuButton.querySelector('i');
icon.classList.remove('fa-times');
icon.classList.add('fa-bars');
}
});
}
// Auto-hide alerts after 5 seconds
setTimeout(function() {
const alerts = document.querySelectorAll('[role="alert"]');
alerts.forEach(function(alert) {
alert.style.opacity = '0';
setTimeout(() => alert.remove(), 300);
});
}, 5000);
// Add loading state to forms
var forms = document.querySelectorAll('form');
forms.forEach(function(form) {
form.addEventListener('submit', function() {
var submitBtn = form.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.innerHTML = ' Processing...';
submitBtn.disabled = true;
}
});
});
// Smooth scrolling for anchor links
var anchorLinks = document.querySelectorAll('a[href^="#"]');
anchorLinks.forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
var target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Add animation classes to elements when they come into view
var observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
var observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add('fade-in');
}
});
}, observerOptions);
// Observe elements for animation
var animateElements = document.querySelectorAll('.card, .stat-item, .feature-icon');
animateElements.forEach(function(el) {
observer.observe(el);
});
// Dashboard specific functionality
if (document.body.classList.contains('dashboard-page')) {
// Auto-refresh dashboard data every 5 minutes
setInterval(function() {
// You can implement AJAX calls here to refresh dashboard data
console.log('Dashboard data refresh triggered');
}, 300000);
}
// Form validation enhancement
var inputs = document.querySelectorAll('input, select, textarea');
inputs.forEach(function(input) {
input.addEventListener('blur', function() {
validateField(this);
});
});
function validateField(field) {
var isValid = field.checkValidity();
var feedback = field.parentNode.querySelector('.invalid-feedback');
if (!isValid) {
field.classList.add('is-invalid');
if (feedback) {
feedback.style.display = 'block';
}
} else {
field.classList.remove('is-invalid');
field.classList.add('is-valid');
if (feedback) {
feedback.style.display = 'none';
}
}
}
// Search functionality
var searchInputs = document.querySelectorAll('.search-input');
searchInputs.forEach(function(input) {
input.addEventListener('input', function() {
var searchTerm = this.value.toLowerCase();
var targetSelector = this.dataset.target;
var items = document.querySelectorAll(targetSelector);
items.forEach(function(item) {
var text = item.textContent.toLowerCase();
if (text.includes(searchTerm)) {
item.style.display = '';
} else {
item.style.display = 'none';
}
});
});
});
// Confirmation dialogs
var deleteButtons = document.querySelectorAll('.btn-delete');
deleteButtons.forEach(function(button) {
button.addEventListener('click', function(e) {
if (!confirm('Are you sure you want to delete this item?')) {
e.preventDefault();
}
});
});
// File upload preview
var fileInputs = document.querySelectorAll('input[type="file"]');
fileInputs.forEach(function(input) {
input.addEventListener('change', function() {
var file = this.files[0];
if (file) {
var preview = this.parentNode.querySelector('.file-preview');
if (preview) {
if (file.type.startsWith('image/')) {
var reader = new FileReader();
reader.onload = function(e) {
preview.innerHTML = '';
};
reader.readAsDataURL(file);
} else {
preview.innerHTML = '
File: ' + file.name + '
'; } } } }); }); // Print functionality var printButtons = document.querySelectorAll('.btn-print'); printButtons.forEach(function(button) { button.addEventListener('click', function() { window.print(); }); }); // Copy to clipboard functionality var copyButtons = document.querySelectorAll('.btn-copy'); copyButtons.forEach(function(button) { button.addEventListener('click', function() { var text = this.dataset.copy; navigator.clipboard.writeText(text).then(function() { // Show success message var toast = document.createElement('div'); toast.className = 'toast align-items-center text-white bg-success border-0'; toast.innerHTML = '