const API_URL = '/api/v1/index.php?request=';
const state = {
user: JSON.parse(localStorage.getItem('user')) || null,
token: localStorage.getItem('token') || null,
};
const routes = {
'/': homePage,
'/login': loginPage,
'/learners': learnersPage,
'/assessments': assessmentsPage,
'/events': eventsPage,
'/collaboration': collaborationPage,
'/leaderboard': leaderboardPage,
'/super-admin': superAdminPage,
};
async function init() {
window.addEventListener('hashchange', router);
router();
updateNav();
}
function router() {
const hash = window.location.hash || '#/';
const path = hash.substring(1);
// Auth guard
if (!state.token && path !== '/login') {
window.location.hash = '#/login';
return;
}
const page = routes[path] || routes['/'];
page();
}
function updateNav() {
const navLinks = document.getElementById('nav-links');
if (!state.token) {
navLinks.innerHTML = `
Login
`;
return;
}
let html = `Dashboard`;
if (state.user.role === 'Super Admin') {
html += `Super Admin`;
}
html += `
Learners
Assessments
Events
Hub
Ranking
Logout
`;
navLinks.innerHTML = html;
document.getElementById('logout-btn').addEventListener('click', (e) => {
e.preventDefault();
logout();
});
}
function logout() {
localStorage.removeItem('token');
localStorage.removeItem('user');
state.token = null;
state.user = null;
window.location.hash = '#/login';
updateNav();
}
async function apiFetch(endpoint, options = {}) {
const url = API_URL + endpoint;
const defaultOptions = {
headers: {
'Content-Type': 'application/json',
...(state.token ? { 'Authorization': `Bearer ${state.token}` } : {})
}
};
const response = await fetch(url, { ...defaultOptions, ...options });
if (response.status === 401) {
logout();
throw new Error('Unauthorized');
}
const data = await response.json();
if (!response.ok) throw new Error(data.error || 'API Error');
return data;
}
function render(html) {
document.getElementById('content').innerHTML = html;
}
async function homePage() {
render(`
Welcome back, ${state.user.email}
You are logged in as ${state.user.role}.
`);
}
function loginPage() {
render(`
SOMS Platform
Demo Credentials
Super Admin: superadmin@system.com / password
Admin: admin@sowetohigh.edu.za / password
`);
document.getElementById('login-form').addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
try {
const data = await apiFetch('/auth/login', {
method: 'POST',
body: JSON.stringify({ email, password })
});
if (data.token) {
localStorage.setItem('token', data.token);
localStorage.setItem('user', JSON.stringify(data.user));
state.token = data.token;
state.user = data.user;
updateNav();
window.location.hash = '#/';
}
} catch (err) {
alert('Login failed: ' + err.message);
}
});
}
async function superAdminPage() {
render('');
try {
const stats = await apiFetch('/schools/stats');
const schools = await apiFetch('/schools');
let html = `
Super Admin Console
Global platform management
Total Schools
${stats.total_schools}
Total Learners
${stats.total_learners}
System Uptime
${stats.uptime}
Data Storage
${stats.storage}
| Name |
Province |
District |
Actions |
`;
schools.forEach(s => {
html += `
| ${s.name} |
${s.province} |
${s.district} |
|
`;
});
html += '
';
render(html);
} catch (err) {
render('Access Denied: Super Admin only
');
}
}
async function learnersPage() {
render('');
try {
const learners = await apiFetch('/learners');
let html = `
Learners
| Full Name |
Grade |
Student ID |
Actions |
`;
learners.forEach(l => {
html += `
| ${l.full_name} |
${l.grade} |
${l.student_id} |
|
`;
});
html += '
';
render(html);
} catch (err) {
render('Failed to load learners
');
}
}
async function assessmentsPage() {
render('');
try {
const assessments = await apiFetch('/assessments');
let html = `
Assessments
`;
assessments.forEach(a => {
html += `
${a.title || a.name}
${a.subject || a.grade} — ${a.type}
`;
});
html += '
';
render(html);
} catch (err) {
render('Failed to load assessments
');
}
}
async function eventsPage() {
render('');
try {
const events = await apiFetch('/events');
let html = `
School Calendar
`;
if (events.length === 0) html += '
No upcoming events.
';
events.forEach(e => {
html += `
${new Date(e.start_datetime).getDate()}
${new Date(e.start_datetime).toLocaleString('default', { month: 'short' })}
${e.title}
${new Date(e.start_datetime).toLocaleTimeString()} — ${e.location || 'No location'}
`;
});
html += '
';
render(html);
} catch (err) {
render('Failed to load events
');
}
}
async function collaborationPage() {
render('');
try {
const resources = await apiFetch('/collaboration/resources');
let html = `
Collaboration Hub
`;
resources.forEach(r => {
html += `
${r.title}
${r.is_public == 1 ? 'Public' : 'School Only'}
${r.description}
${r.teacher_email}
`;
});
html += '
';
render(html);
} catch (err) {
render('Failed to load resources
');
}
}
async function leaderboardPage() {
render('');
try {
const rankings = await apiFetch('/leaderboard');
let html = `
Student Rankings
| Rank |
Learner |
Performance |
Average |
`;
rankings.forEach((r, index) => {
const color = index === 0 ? 'text-warning' : (index === 1 ? 'text-secondary' : (index === 2 ? 'text-brown' : ''));
html += `
| #${index + 1} |
${r.full_name} |
|
${parseFloat(r.average_percent).toFixed(1)}% |
`;
});
html += '
';
render(html);
} catch (err) {
render('Failed to load leaderboard
');
}
}
init();