feat(demo): update prototype to showcase authentic Windows and Android app screens
This commit is contained in:
1 parent
18abb9a6d8
commit
fca3a1f9d7
3 files changed
+473
-1722
No files matched your search
+148
-389
@@ -1,371 +1,149 @@
|
||||
/**
|
||||
* TIS-RMS Interactive Prototype Logic
|
||||
* Powers navigation, device switching, mock data filtering, and simulated workflows.
|
||||
* TIS-RMS Interactive Prototype Showcase
|
||||
* Drives real screen switching between actual screenshots and interactive dialogs.
|
||||
*/
|
||||
|
||||
// ── Mock Data ───────────────────────────────────────────────────
|
||||
const MOCK_STUDENTS = [
|
||||
{ id: 1, lrn: '109876543210', name: 'DELA CRUZ, Juan Santos', grade: 'Grade 10', section: 'Jacinto', sex: 'Male', status: 'Enrolled', age: 16, contact: '0917-123-4567', docs: 4 },
|
||||
{ id: 2, lrn: '109876543211', name: 'SANTOS, Maria Clara Perez', grade: 'Grade 9', section: 'Silang', sex: 'Female', status: 'Enrolled', age: 15, contact: '0918-234-5678', docs: 5 },
|
||||
{ id: 3, lrn: '109876543212', name: 'ALVAREZ, Gabriel Mendoza', grade: 'Grade 7', section: 'Rizal', sex: 'Male', status: 'Enrolled', age: 13, contact: '0919-345-6789', docs: 3 },
|
||||
{ id: 4, lrn: '109876543213', name: 'BAUTISTA, Chloe Anne Flores', grade: 'Grade 8', section: 'Aguinaldo', sex: 'Female', status: 'Enrolled', age: 14, contact: '0920-456-7890', docs: 4 },
|
||||
{ id: 5, lrn: '109876543214', name: 'RAMIREZ, Christian Paul Torres', grade: 'Grade 11', section: 'TVL-ICT', sex: 'Male', status: 'Enrolled', age: 17, contact: '0921-567-8901', docs: 5 },
|
||||
{ id: 6, lrn: '109876543215', name: 'VILLANUEVA, Princess Diane Gomez', grade: 'Grade 12', section: 'STEM A', sex: 'Female', status: 'Enrolled', age: 18, contact: '0922-678-9012', docs: 5 },
|
||||
{ id: 7, lrn: '109876543216', name: 'CASTILLO, Joshua Mark Reyes', grade: 'Grade 10', section: 'Tandang Sora', sex: 'Male', status: 'Enrolled', age: 16, contact: '0923-789-0123', docs: 4 },
|
||||
{ id: 8, lrn: '109876543217', name: 'MERCADO, Angel Mae Lim', grade: 'Grade 7', section: 'Bonifacio', sex: 'Female', status: 'Enrolled', age: 13, contact: '0924-890-1234', docs: 3 },
|
||||
const SCREENS = [
|
||||
{ id: 'dashboard', name: 'Dashboard', icon: '📊' },
|
||||
{ id: 'students', name: 'Students', icon: '👥' },
|
||||
{ id: 'documents', name: 'Documents', icon: '📁' },
|
||||
{ id: 'archives', name: 'Archives', icon: '📦' },
|
||||
{ id: 'reports', name: 'Reports', icon: '📈' },
|
||||
{ id: 'users', name: 'Users', icon: '👤' },
|
||||
{ id: 'history', name: 'History', icon: '🕒' },
|
||||
{ id: 'settings', name: 'Settings', icon: '⚙️' },
|
||||
];
|
||||
|
||||
const MOCK_DOCS = [
|
||||
{ name: 'PSA / NSO Birth Certificate', code: 'DOC-PSA', required: true, status: 'Verified', count: 1420 },
|
||||
{ name: 'SF10 / Form 137 (Permanent Record)', code: 'DOC-SF10', required: true, status: 'Verified', count: 1388 },
|
||||
{ name: 'SF9 / Form 138 (Report Card)', code: 'DOC-SF9', required: true, status: 'Verified', count: 1405 },
|
||||
{ name: 'Certificate of Good Moral Character', code: 'DOC-GMC', required: false, status: 'Complete', count: 1290 },
|
||||
{ name: '2x2 Recent ID Photo', code: 'DOC-PHOTO', required: true, status: 'Verified', count: 1482 },
|
||||
];
|
||||
|
||||
const MOCK_CLASSES = [
|
||||
{ grade: 'Grade 7', section: 'Rizal', adviser: 'Ms. Carmela Diaz', students: 46, max: 50 },
|
||||
{ grade: 'Grade 7', section: 'Bonifacio', adviser: 'Mr. Eduardo Ramos', students: 48, max: 50 },
|
||||
{ grade: 'Grade 8', section: 'Aguinaldo', adviser: 'Mrs. Leah Manalo', students: 45, max: 50 },
|
||||
{ grade: 'Grade 8', section: 'Luna', adviser: 'Mr. Kenneth Ortiz', students: 47, max: 50 },
|
||||
{ grade: 'Grade 9', section: 'Silang', adviser: 'Ms. Joanne Beltran', students: 44, max: 50 },
|
||||
{ grade: 'Grade 10', section: 'Jacinto', adviser: 'Mr. Roderick Tan', students: 49, max: 50 },
|
||||
{ grade: 'Grade 11', section: 'TVL-ICT', adviser: 'Engr. Mark Soriano', students: 42, max: 45 },
|
||||
{ grade: 'Grade 12', section: 'STEM A', adviser: 'Dr. Evelyn Cruz', students: 40, max: 45 },
|
||||
];
|
||||
|
||||
// ── Application State ──────────────────────────────────────────
|
||||
let currentDevice = 'windows';
|
||||
let currentDevice = 'windows'; // 'windows' | 'android'
|
||||
let currentScreen = 'dashboard';
|
||||
let currentTheme = 'light';
|
||||
let studentFilter = 'all';
|
||||
let searchQuery = '';
|
||||
|
||||
// ── Initialization ─────────────────────────────────────────────
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setupDeviceSwitcher();
|
||||
setupThemeToggle();
|
||||
setupNavigation();
|
||||
renderStudentsTable();
|
||||
renderMobileStudentsList();
|
||||
renderDocsList();
|
||||
renderClassesList();
|
||||
startClock();
|
||||
setupScreenPills();
|
||||
setupKeyboardNavigation();
|
||||
updateView();
|
||||
});
|
||||
|
||||
// ── Device Switcher ────────────────────────────────────────────
|
||||
// ── Device Switcher ───────────────────────────────────────────
|
||||
function setupDeviceSwitcher() {
|
||||
const winBtn = document.getElementById('btn-view-windows');
|
||||
const androidBtn = document.getElementById('btn-view-android');
|
||||
const winFrame = document.getElementById('desktop-frame');
|
||||
const phoneFrame = document.getElementById('phone-frame');
|
||||
|
||||
winBtn.addEventListener('click', () => {
|
||||
currentDevice = 'windows';
|
||||
winBtn.classList.add('active');
|
||||
androidBtn.classList.remove('active');
|
||||
winFrame.style.display = 'flex';
|
||||
phoneFrame.style.display = 'none';
|
||||
syncScreens();
|
||||
document.getElementById('desktop-window').style.display = 'flex';
|
||||
document.getElementById('phone-mockup').style.display = 'none';
|
||||
updateView();
|
||||
});
|
||||
|
||||
androidBtn.addEventListener('click', () => {
|
||||
currentDevice = 'android';
|
||||
androidBtn.classList.add('active');
|
||||
winBtn.classList.remove('active');
|
||||
winFrame.style.display = 'none';
|
||||
phoneFrame.style.display = 'flex';
|
||||
syncScreens();
|
||||
document.getElementById('desktop-window').style.display = 'none';
|
||||
document.getElementById('phone-mockup').style.display = 'flex';
|
||||
updateView();
|
||||
});
|
||||
}
|
||||
|
||||
// ── Theme Toggle ───────────────────────────────────────────────
|
||||
function setupThemeToggle() {
|
||||
const toggleBtn = document.getElementById('theme-toggle-btn');
|
||||
toggleBtn.addEventListener('click', () => {
|
||||
currentTheme = currentTheme === 'light' ? 'dark' : 'light';
|
||||
document.documentElement.setAttribute('data-theme', currentTheme);
|
||||
toggleBtn.innerHTML = currentTheme === 'light'
|
||||
? `<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>`
|
||||
: `<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>`;
|
||||
});
|
||||
}
|
||||
// ── Screen Selector Pills ─────────────────────────────────────
|
||||
function setupScreenPills() {
|
||||
const bar = document.getElementById('screen-selector-bar');
|
||||
if (!bar) return;
|
||||
|
||||
// ── Navigation ─────────────────────────────────────────────────
|
||||
function setupNavigation() {
|
||||
// Desktop sidebar clicks
|
||||
document.querySelectorAll('.win-nav-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const target = item.getAttribute('data-screen');
|
||||
if (target) navigateTo(target);
|
||||
});
|
||||
});
|
||||
|
||||
// Mobile bottom nav clicks
|
||||
document.querySelectorAll('.bottom-nav-item').forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
const target = item.getAttribute('data-screen');
|
||||
if (target) navigateTo(target);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function navigateTo(screenId) {
|
||||
currentScreen = screenId;
|
||||
syncScreens();
|
||||
}
|
||||
|
||||
function syncScreens() {
|
||||
// Update desktop sidebar active class
|
||||
document.querySelectorAll('.win-nav-item').forEach(el => {
|
||||
el.classList.toggle('active', el.getAttribute('data-screen') === currentScreen);
|
||||
});
|
||||
|
||||
// Update mobile bottom nav active class
|
||||
document.querySelectorAll('.bottom-nav-item').forEach(el => {
|
||||
el.classList.toggle('active', el.getAttribute('data-screen') === currentScreen);
|
||||
});
|
||||
|
||||
// Update desktop content views
|
||||
document.querySelectorAll('.win-screen-view').forEach(view => {
|
||||
view.style.display = view.id === `win-${currentScreen}` ? 'block' : 'none';
|
||||
});
|
||||
|
||||
// Update mobile content views
|
||||
document.querySelectorAll('.phone-screen-view').forEach(view => {
|
||||
view.style.display = view.id === `phone-${currentScreen}` ? 'block' : 'none';
|
||||
});
|
||||
|
||||
// Update breadcrumb titles
|
||||
const titles = {
|
||||
dashboard: 'Dashboard Overview',
|
||||
students: 'Students Directory',
|
||||
documents: 'Document Requirements',
|
||||
academic: 'Classes & Academic Structure',
|
||||
settings: 'System Settings & About'
|
||||
};
|
||||
|
||||
const winTitle = document.getElementById('win-breadcrumb-title');
|
||||
if (winTitle) winTitle.textContent = titles[currentScreen] || 'Dashboard';
|
||||
|
||||
const phoneTitle = document.getElementById('phone-header-title');
|
||||
if (phoneTitle) phoneTitle.textContent = titles[currentScreen] || 'TIS-RMS';
|
||||
}
|
||||
|
||||
// ── Students Table & Card Rendering ────────────────────────────
|
||||
function renderStudentsTable() {
|
||||
const tbody = document.getElementById('students-table-body');
|
||||
if (!tbody) return;
|
||||
|
||||
const filtered = filterStudentData();
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (filtered.length === 0) {
|
||||
tbody.innerHTML = `<tr><td colspan="7" style="text-align: center; padding: 32px; color: var(--win-text-muted);">No student records matched your search query.</td></tr>`;
|
||||
return;
|
||||
}
|
||||
|
||||
filtered.forEach(student => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.className = 'student-row-click';
|
||||
tr.innerHTML = `
|
||||
<td style="font-weight: 600;">${student.name}</td>
|
||||
<td style="font-family: monospace; color: var(--win-text-muted);">${student.lrn}</td>
|
||||
<td>${student.grade}</td>
|
||||
<td>${student.section}</td>
|
||||
<td>${student.sex}</td>
|
||||
<td><span class="status-badge badge-enrolled">${student.status}</span></td>
|
||||
<td>
|
||||
<button class="btn-secondary" style="height: 28px; padding: 0 10px; font-size: 11px;" onclick="openStudentModal(${student.id})">
|
||||
View Details
|
||||
</button>
|
||||
</td>
|
||||
`;
|
||||
tr.addEventListener('click', (e) => {
|
||||
if (e.target.tagName !== 'BUTTON') openStudentModal(student.id);
|
||||
});
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
function renderMobileStudentsList() {
|
||||
const container = document.getElementById('mobile-students-container');
|
||||
if (!container) return;
|
||||
|
||||
const filtered = filterStudentData();
|
||||
container.innerHTML = '';
|
||||
|
||||
if (filtered.length === 0) {
|
||||
container.innerHTML = `<div style="text-align:center; padding: 30px; color: var(--win-text-muted); font-size: 13px;">No student records found.</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
filtered.forEach(student => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'mobile-student-card';
|
||||
card.innerHTML = `
|
||||
<div class="m-student-header">
|
||||
<span class="m-student-name">${student.name}</span>
|
||||
<span class="status-badge badge-enrolled">${student.status}</span>
|
||||
</div>
|
||||
<div class="m-student-lrn">LRN: ${student.lrn}</div>
|
||||
<div class="m-student-footer">
|
||||
<span>${student.grade} - ${student.section}</span>
|
||||
<span style="color: var(--primary-green); font-weight: 600;">Details ›</span>
|
||||
</div>
|
||||
`;
|
||||
card.addEventListener('click', () => openStudentModal(student.id));
|
||||
container.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
function filterStudentData() {
|
||||
return MOCK_STUDENTS.filter(s => {
|
||||
const matchesSearch = s.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
s.lrn.includes(searchQuery) ||
|
||||
s.section.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
|
||||
if (studentFilter === 'all') return matchesSearch;
|
||||
if (studentFilter === 'male') return matchesSearch && s.sex === 'Male';
|
||||
if (studentFilter === 'female') return matchesSearch && s.sex === 'Female';
|
||||
return matchesSearch && s.grade.toLowerCase().includes(studentFilter.toLowerCase());
|
||||
});
|
||||
}
|
||||
|
||||
function setStudentFilter(filterVal, element) {
|
||||
studentFilter = filterVal;
|
||||
document.querySelectorAll('.filter-chips .chip').forEach(c => c.classList.remove('active'));
|
||||
if (element) element.classList.add('active');
|
||||
renderStudentsTable();
|
||||
renderMobileStudentsList();
|
||||
}
|
||||
|
||||
function onSearchInput(query) {
|
||||
searchQuery = query;
|
||||
renderStudentsTable();
|
||||
renderMobileStudentsList();
|
||||
}
|
||||
|
||||
// ── Documents Screen ───────────────────────────────────────────
|
||||
function renderDocsList() {
|
||||
const winContainer = document.getElementById('docs-grid-windows');
|
||||
const phoneContainer = document.getElementById('docs-list-phone');
|
||||
|
||||
if (winContainer) {
|
||||
winContainer.innerHTML = MOCK_DOCS.map(doc => `
|
||||
<div class="content-card" style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<div style="font-weight: 700; font-size: 14px; margin-bottom: 2px;">${doc.name}</div>
|
||||
<div style="font-size: 12px; color: var(--win-text-muted);">${doc.code} • ${doc.count} Verified Records</div>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span class="status-badge badge-complete">${doc.status}</span>
|
||||
<button class="btn-secondary" style="height: 32px; padding: 0 12px;" onclick="openDocPreviewModal('${doc.name}', '${doc.code}')">Preview Scan</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
if (phoneContainer) {
|
||||
phoneContainer.innerHTML = MOCK_DOCS.map(doc => `
|
||||
<div class="mobile-student-card" onclick="openDocPreviewModal('${doc.name}', '${doc.code}')">
|
||||
<div class="m-student-header">
|
||||
<span class="m-student-name" style="font-size: 13px;">${doc.name}</span>
|
||||
<span class="status-badge badge-complete">${doc.status}</span>
|
||||
</div>
|
||||
<div class="m-student-footer" style="margin-top: 6px;">
|
||||
<span>${doc.count} submissions</span>
|
||||
<span style="color: var(--primary-green); font-weight: 600;">View ›</span>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Academic Screen ────────────────────────────────────────────
|
||||
function renderClassesList() {
|
||||
const winContainer = document.getElementById('classes-grid-windows');
|
||||
const phoneContainer = document.getElementById('classes-list-phone');
|
||||
|
||||
const html = MOCK_CLASSES.map(cls => `
|
||||
<div class="content-card">
|
||||
<div class="card-header" style="margin-bottom: 8px;">
|
||||
<span style="font-size: 12px; font-weight: 700; color: var(--primary-green); text-transform: uppercase;">${cls.grade}</span>
|
||||
<span style="font-size: 11px; font-weight: 600; color: var(--win-text-muted);">${cls.students}/${cls.max} Students</span>
|
||||
</div>
|
||||
<div style="font-size: 16px; font-weight: 700; color: var(--win-text); margin-bottom: 4px;">Section ${cls.section}</div>
|
||||
<div style="font-size: 12px; color: var(--win-text-muted); margin-bottom: 12px;">Adviser: ${cls.adviser}</div>
|
||||
<div class="bar-track" style="height: 6px;">
|
||||
<div class="bar-fill" style="width: ${(cls.students / cls.max) * 100}%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
bar.innerHTML = SCREENS.map(s => `
|
||||
<button class="screen-pill ${s.id === currentScreen ? 'active' : ''}" data-screen="${s.id}" onclick="setScreen('${s.id}')">
|
||||
<span>${s.icon}</span>
|
||||
<span>${s.name}</span>
|
||||
</button>
|
||||
`).join('');
|
||||
|
||||
if (winContainer) winContainer.innerHTML = html;
|
||||
if (phoneContainer) phoneContainer.innerHTML = html;
|
||||
}
|
||||
|
||||
// ── Student Detail Modal ───────────────────────────────────────
|
||||
function openStudentModal(id) {
|
||||
const student = MOCK_STUDENTS.find(s => s.id === id);
|
||||
if (!student) return;
|
||||
|
||||
const modal = document.getElementById('student-modal');
|
||||
const body = document.getElementById('student-modal-body');
|
||||
|
||||
body.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--win-border);">
|
||||
<div style="width: 52px; height: 52px; border-radius: 50%; background: var(--primary-green); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 20px; font-weight: 700;">
|
||||
${student.name.charAt(0)}
|
||||
</div>
|
||||
<div>
|
||||
<h4 style="font-size: 16px; font-weight: 700;">${student.name}</h4>
|
||||
<span style="font-size: 12px; color: var(--win-text-muted);">LRN: ${student.lrn} • ${student.grade} - ${student.section}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="info-row"><span class="info-label">Gender:</span><span class="info-val">${student.sex}</span></div>
|
||||
<div class="info-row"><span class="info-label">Age:</span><span class="info-val">${student.age} years old</span></div>
|
||||
<div class="info-row"><span class="info-label">Enrollment Status:</span><span class="info-val"><span class="status-badge badge-enrolled">${student.status}</span></span></div>
|
||||
<div class="info-row"><span class="info-label">Parent / Guardian Contact:</span><span class="info-val">${student.contact}</span></div>
|
||||
<div class="info-row"><span class="info-label">School:</span><span class="info-val">Talipan National High School</span></div>
|
||||
|
||||
<div style="margin-top: 10px;">
|
||||
<h5 style="font-size: 13px; font-weight: 700; margin-bottom: 8px;">Submitted Document Requirements</h5>
|
||||
<div style="display: flex; flex-direction: column; gap: 6px;">
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; padding: 6px 10px; background: var(--win-surface-subtle); border-radius: 6px;">
|
||||
<span>PSA Birth Certificate</span>
|
||||
<span style="color: var(--primary-green); font-weight: 600;">✓ Verified</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; padding: 6px 10px; background: var(--win-surface-subtle); border-radius: 6px;">
|
||||
<span>Form 137 / SF10</span>
|
||||
<span style="color: var(--primary-green); font-weight: 600;">✓ Verified</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; padding: 6px 10px; background: var(--win-surface-subtle); border-radius: 6px;">
|
||||
<span>Form 138 / SF9</span>
|
||||
<span style="color: var(--primary-green); font-weight: 600;">✓ Verified</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modal.classList.add('active');
|
||||
function setScreen(screenId) {
|
||||
currentScreen = screenId;
|
||||
updateView();
|
||||
}
|
||||
|
||||
function openDocPreviewModal(name, code) {
|
||||
const modal = document.getElementById('doc-preview-modal');
|
||||
const title = document.getElementById('doc-preview-title');
|
||||
const codeEl = document.getElementById('doc-preview-code');
|
||||
function updateView() {
|
||||
// Update screen pills
|
||||
document.querySelectorAll('.screen-pill').forEach(pill => {
|
||||
pill.classList.toggle('active', pill.getAttribute('data-screen') === currentScreen);
|
||||
});
|
||||
|
||||
if (title) title.textContent = name;
|
||||
if (codeEl) codeEl.textContent = code;
|
||||
// Windows Desktop Image
|
||||
const winImg = document.getElementById('win-screen-img');
|
||||
if (winImg) {
|
||||
winImg.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
winImg.src = `screenshots/windows/${currentScreen}.webp`;
|
||||
winImg.style.opacity = '1';
|
||||
}, 120);
|
||||
}
|
||||
|
||||
modal.classList.add('active');
|
||||
// Android Mobile Image
|
||||
const phoneImg = document.getElementById('phone-screen-img');
|
||||
if (phoneImg) {
|
||||
phoneImg.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
phoneImg.src = `screenshots/android/${currentScreen}.webp`;
|
||||
phoneImg.style.opacity = '1';
|
||||
}, 120);
|
||||
}
|
||||
|
||||
// Update Dynamic Hotspots
|
||||
updateHotspots();
|
||||
}
|
||||
|
||||
// ── Dynamic Hotspots ──────────────────────────────────────────
|
||||
function updateHotspots() {
|
||||
const addStudentHotspot = document.getElementById('hotspot-add-student');
|
||||
const settingsUpdateHotspot = document.getElementById('hotspot-settings-update');
|
||||
|
||||
if (addStudentHotspot) {
|
||||
addStudentHotspot.style.display = currentScreen === 'students' ? 'block' : 'none';
|
||||
}
|
||||
|
||||
if (settingsUpdateHotspot) {
|
||||
settingsUpdateHotspot.style.display = currentScreen === 'settings' ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Keyboard Shortcuts (1-8 and Left/Right Arrows) ────────────
|
||||
function setupKeyboardNavigation() {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// 1-8 keys
|
||||
const num = parseInt(e.key);
|
||||
if (!isNaN(num) && num >= 1 && num <= SCREENS.length) {
|
||||
setScreen(SCREENS[num - 1].id);
|
||||
return;
|
||||
}
|
||||
|
||||
// Arrow keys
|
||||
const currentIndex = SCREENS.findIndex(s => s.id === currentScreen);
|
||||
if (e.key === 'ArrowRight') {
|
||||
const nextIndex = (currentIndex + 1) % SCREENS.length;
|
||||
setScreen(SCREENS[nextIndex].id);
|
||||
} else if (e.key === 'ArrowLeft') {
|
||||
const prevIndex = (currentIndex - 1 + SCREENS.length) % SCREENS.length;
|
||||
setScreen(SCREENS[prevIndex].id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Interactive Modals ─────────────────────────────────────────
|
||||
function openAddStudentModal() {
|
||||
const modal = document.getElementById('add-student-modal');
|
||||
modal.classList.add('active');
|
||||
if (modal) modal.classList.add('active');
|
||||
}
|
||||
|
||||
function openUpdateCheckModal() {
|
||||
const modal = document.getElementById('update-modal');
|
||||
if (modal) {
|
||||
modal.classList.add('active');
|
||||
simulateUpdateProcess();
|
||||
}
|
||||
}
|
||||
|
||||
function closeModal(id) {
|
||||
@@ -373,76 +151,57 @@ function closeModal(id) {
|
||||
if (modal) modal.classList.remove('active');
|
||||
}
|
||||
|
||||
// ── Settings Collapsible Sections ──────────────────────────────
|
||||
function toggleSettingsSection(id) {
|
||||
const body = document.getElementById(`settings-body-${id}`);
|
||||
const arrow = document.getElementById(`settings-arrow-${id}`);
|
||||
if (!body) return;
|
||||
|
||||
const isVisible = body.style.display !== 'none';
|
||||
body.style.display = isVisible ? 'none' : 'flex';
|
||||
if (arrow) {
|
||||
arrow.style.transform = isVisible ? 'rotate(0deg)' : 'rotate(180deg)';
|
||||
}
|
||||
}
|
||||
|
||||
// ── Check For Updates Simulation ───────────────────────────────
|
||||
function simulateUpdateCheck() {
|
||||
const btn = document.getElementById('btn-check-update');
|
||||
const btnText = document.getElementById('btn-check-update-text');
|
||||
const statusBanner = document.getElementById('update-status-banner');
|
||||
// ── Simulated Update Check Workflow ────────────────────────────
|
||||
function simulateUpdateProcess() {
|
||||
const statusEl = document.getElementById('update-modal-status');
|
||||
const actionBtn = document.getElementById('btn-download-action');
|
||||
const toast = document.getElementById('browser-download-toast');
|
||||
const toastText = document.getElementById('toast-filename');
|
||||
const toastFile = document.getElementById('toast-filename');
|
||||
|
||||
if (!btn) return;
|
||||
const isWin = currentDevice === 'windows';
|
||||
const arch = isWin ? 'x64 (64-bit)' : 'ARM64 (64-bit)';
|
||||
const file = isWin ? 'TIS_RMS_Setup_v1.0.24.exe' : 'TIS_RMS_64_v1.0.24.apk';
|
||||
|
||||
btn.disabled = true;
|
||||
btnText.textContent = 'Checking GitHub releases...';
|
||||
statusBanner.style.display = 'none';
|
||||
statusEl.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 10px; color: var(--accent-emerald);">
|
||||
<div style="width: 16px; height: 16px; border: 2px solid var(--accent-emerald); border-top-color: transparent; border-radius: 50%; animation: spin 0.8s linear infinite;"></div>
|
||||
<span>Querying GitHub releases for ${arch}...</span>
|
||||
</div>
|
||||
`;
|
||||
actionBtn.style.display = 'none';
|
||||
|
||||
setTimeout(() => {
|
||||
btn.disabled = false;
|
||||
btnText.textContent = 'Check for Updates';
|
||||
|
||||
// Architecture-matched file simulation
|
||||
const isWin = currentDevice === 'windows';
|
||||
const filename = isWin ? 'TIS_RMS_Setup_v1.0.24.exe' : 'TIS_RMS_64_v1.0.24.apk';
|
||||
const archLabel = isWin ? 'x64 (64-bit)' : 'ARM64 (64-bit)';
|
||||
|
||||
statusBanner.style.display = 'block';
|
||||
statusBanner.innerHTML = `
|
||||
<div style="display: flex; align-items: center; gap: 8px; font-weight: 600; color: var(--primary-green); margin-bottom: 4px;">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
||||
New Version Detected: v1.0.24 for ${archLabel}
|
||||
</div>
|
||||
<div style="font-size: 12px; color: var(--win-text);">
|
||||
Architecture matched: <strong>${filename}</strong>.<br/>
|
||||
Simulating launching download in device's default browser...
|
||||
statusEl.innerHTML = `
|
||||
<div style="background: rgba(25, 135, 84, 0.15); border: 1px solid rgba(25, 135, 84, 0.35); padding: 12px; border-radius: 8px;">
|
||||
<div style="font-weight: 700; color: var(--accent-emerald); margin-bottom: 4px;">
|
||||
✓ Update Detected: v1.0.24
|
||||
</div>
|
||||
<div style="font-size: 12px; color: #cbd5e1; line-height: 1.5;">
|
||||
Architecture: <strong>${arch}</strong><br/>
|
||||
Matched Asset: <strong>${file}</strong><br/>
|
||||
Opening direct link in default device browser...
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Show simulated default browser toast
|
||||
if (toast && toastText) {
|
||||
toastText.textContent = filename;
|
||||
toast.classList.add('active');
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('active');
|
||||
}, 5000);
|
||||
}
|
||||
}, 1200);
|
||||
actionBtn.style.display = 'inline-flex';
|
||||
actionBtn.onclick = () => {
|
||||
closeModal('update-modal');
|
||||
triggerDownloadToast(file);
|
||||
};
|
||||
|
||||
triggerDownloadToast(file);
|
||||
}, 1400);
|
||||
}
|
||||
|
||||
// ── Clock for Android Status Bar ───────────────────────────────
|
||||
function startClock() {
|
||||
function updateTime() {
|
||||
const el = document.getElementById('phone-time');
|
||||
if (!el) return;
|
||||
const now = new Date();
|
||||
let hours = now.getHours();
|
||||
let mins = now.getMinutes();
|
||||
mins = mins < 10 ? '0' + mins : mins;
|
||||
el.textContent = `${hours}:${mins}`;
|
||||
function triggerDownloadToast(filename) {
|
||||
const toast = document.getElementById('browser-download-toast');
|
||||
const toastFile = document.getElementById('toast-filename');
|
||||
if (toast && toastFile) {
|
||||
toastFile.textContent = filename;
|
||||
toast.classList.add('active');
|
||||
setTimeout(() => {
|
||||
toast.classList.remove('active');
|
||||
}, 5000);
|
||||
}
|
||||
updateTime();
|
||||
setInterval(updateTime, 30000);
|
||||
}
|
||||
+88
-547
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="light">
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@@ -15,583 +15,95 @@
|
||||
<header class="top-control-bar">
|
||||
<div class="brand-badge">
|
||||
<img src="assets/logo.png" alt="TIS Logo">
|
||||
<span>TIS-RMS Demo</span>
|
||||
<span>TIS-RMS Showcase</span>
|
||||
</div>
|
||||
|
||||
<!-- Viewport Switcher -->
|
||||
<!-- Device Switcher -->
|
||||
<div class="device-switcher" role="tablist">
|
||||
<button id="btn-view-windows" class="device-btn active" title="Switch to Windows Desktop layout">
|
||||
<button id="btn-view-windows" class="device-btn active" title="Switch to Windows Desktop app view">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801"/>
|
||||
</svg>
|
||||
<span>Windows Desktop</span>
|
||||
</button>
|
||||
|
||||
<button id="btn-view-android" class="device-btn" title="Switch to Android Mobile layout">
|
||||
<button id="btn-view-android" class="device-btn" title="Switch to Android Mobile app view">
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M17.523 15.3414c-.5511 0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.551 0 .9993.4482.9993.9993.0001.5511-.4483.9997-.9993.9997m-11.046 0c-.5511 0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.5511 0 .9993.4482.9993.9993 0 .5511-.4482.9997-.9993.9997m11.4045-6.02l1.9973-3.4592a.416.416 0 00-.1521-.5676.416.416 0 00-.5676.1521l-2.0223 3.503C15.5902 8.411 13.8533 8.081 12 8.081s-3.5902.33-5.1367.8687L4.841 5.4467a.4161.4161 0 00-.5677-.1521.4157.4157 0 00-.1521.5676l1.9973 3.4592C2.6889 11.1867.3432 14.6589 0 18.761h24c-.3432-4.1021-2.6889-7.5743-6.1185-9.4396"/>
|
||||
</svg>
|
||||
<span>Android Mobile</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Theme Switcher -->
|
||||
<button id="theme-toggle-btn" class="theme-toggle-btn" title="Toggle Light/Dark Theme">
|
||||
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
<!-- ── Main Viewport Area ────────────────────────────────────── -->
|
||||
<!-- ── Screen Selector Pill Bar ───────────────────────────────── -->
|
||||
<nav id="screen-selector-bar" class="screen-selector-bar">
|
||||
<!-- Injected via app.js -->
|
||||
</nav>
|
||||
|
||||
<!-- ── Viewport Area ─────────────────────────────────────────── -->
|
||||
<main class="viewport-container">
|
||||
|
||||
<!-- ==============================================================
|
||||
1. WINDOWS DESKTOP VIEW
|
||||
============================================================== -->
|
||||
<div id="desktop-frame" class="desktop-frame">
|
||||
<!-- 1. WINDOWS DESKTOP WINDOW FRAME -->
|
||||
<div id="desktop-window" class="desktop-window">
|
||||
<!-- Titlebar -->
|
||||
<div class="win-titlebar">
|
||||
<div class="win-title">
|
||||
<div class="win-titlebar-left">
|
||||
<img src="assets/logo.png" alt="Logo">
|
||||
<span>TIS Record Management System - Talipan National High School</span>
|
||||
<span>TIS Record Management System</span>
|
||||
</div>
|
||||
<div class="win-controls">
|
||||
<div class="win-window-controls">
|
||||
<span>—</span>
|
||||
<span>▢</span>
|
||||
<span class="close">✕</span>
|
||||
<span style="cursor: pointer;">✕</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="win-body">
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="win-sidebar">
|
||||
<div class="win-app-brand">
|
||||
<img src="assets/logo.png" alt="Logo">
|
||||
<div class="win-brand-text">
|
||||
<h3>TIS-RMS</h3>
|
||||
<span>Tiaong, Quezon</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stage with actual screenshot and clickable interactive hotspots -->
|
||||
<div class="win-stage">
|
||||
<img id="win-screen-img" class="win-screen-img" src="screenshots/windows/dashboard.webp" alt="Windows Screen">
|
||||
|
||||
<ul class="win-nav-list">
|
||||
<li class="win-nav-item active" data-screen="dashboard">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
|
||||
<span>Dashboard</span>
|
||||
</li>
|
||||
<li class="win-nav-item" data-screen="students">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M23 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg>
|
||||
<span>Students</span>
|
||||
<span class="badge">1,482</span>
|
||||
</li>
|
||||
<li class="win-nav-item" data-screen="documents">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
|
||||
<span>Documents</span>
|
||||
</li>
|
||||
<li class="win-nav-item" data-screen="academic">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M22 10v6M2 10l10-5 10 5-10 5z"></path><path d="M6 12v5c0 2 2 3 6 3s6-1 6-3v-5"></path></svg>
|
||||
<span>Academic</span>
|
||||
</li>
|
||||
<li class="win-nav-item" data-screen="settings">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
<span>Settings</span>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- Interactive Sidebar Hotspots (Clicking sidebar directly on screenshot navigates!) -->
|
||||
<div class="win-sidebar-hotspots">
|
||||
<div class="hotspot-sidebar-item hotspot-item-dashboard" title="Go to Dashboard" onclick="setScreen('dashboard')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-students" title="Go to Students Directory" onclick="setScreen('students')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-documents" title="Go to Documents" onclick="setScreen('documents')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-archives" title="Go to Archives" onclick="setScreen('archives')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-reports" title="Go to Reports" onclick="setScreen('reports')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-users" title="Go to Users Management" onclick="setScreen('users')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-history" title="Go to Audit History" onclick="setScreen('history')"></div>
|
||||
<div class="hotspot-sidebar-item hotspot-item-settings" title="Go to Settings" onclick="setScreen('settings')"></div>
|
||||
</div>
|
||||
|
||||
<div class="win-user-profile">
|
||||
<div class="avatar">AD</div>
|
||||
<div class="win-user-info">
|
||||
<h4>Admin User</h4>
|
||||
<span>System Registrar</span>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
<!-- Hotspot: Add Student on Students Screen -->
|
||||
<div id="hotspot-add-student" class="hotspot-add-student" title="Click to simulate Add Student modal" onclick="openAddStudentModal()" style="display: none;"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<section class="win-content">
|
||||
<!-- Top Bar -->
|
||||
<div class="win-topbar">
|
||||
<div class="win-breadcrumb">
|
||||
<span id="win-breadcrumb-title">Dashboard Overview</span>
|
||||
</div>
|
||||
<div class="win-topbar-actions">
|
||||
<div class="win-search-box">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<input type="text" placeholder="Search records (Ctrl+F)..." oninput="onSearchInput(this.value)">
|
||||
</div>
|
||||
<button class="btn-primary" onclick="openAddStudentModal()">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
||||
<span>Add Student</span>
|
||||
</button>
|
||||
<!-- Note: Bulk Import button is cleanly hidden on Windows app as requested! -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Scrollable Body Views -->
|
||||
<div class="win-scroll-area">
|
||||
|
||||
<!-- 1. Dashboard View -->
|
||||
<div id="win-dashboard" class="win-screen-view">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon green">👥</div>
|
||||
<div class="stat-info">
|
||||
<h5>Total Students</h5>
|
||||
<h2>1,482</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon blue">✔</div>
|
||||
<div class="stat-info">
|
||||
<h5>Enrolled</h5>
|
||||
<h2>1,420</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon amber">⇄</div>
|
||||
<div class="stat-info">
|
||||
<h5>Transferred</h5>
|
||||
<h2>38</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon rose">⊘</div>
|
||||
<div class="stat-info">
|
||||
<h5>Dropped Out</h5>
|
||||
<h2>24</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-top: 24px;">
|
||||
<div class="content-card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">Grade Level Distribution</span>
|
||||
<span style="font-size: 12px; color: var(--win-text-muted);">S.Y. 2026-2027</span>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">Grade 7</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 88%;"></div></div>
|
||||
<span class="bar-val">280</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">Grade 8</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 82%;"></div></div>
|
||||
<span class="bar-val">260</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">Grade 9</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 79%;"></div></div>
|
||||
<span class="bar-val">250</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">Grade 10</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 75%;"></div></div>
|
||||
<span class="bar-val">240</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">Grade 11</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 72%;"></div></div>
|
||||
<span class="bar-val">230</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">Grade 12</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 68%;"></div></div>
|
||||
<span class="bar-val">222</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-card">
|
||||
<div class="card-header">
|
||||
<span class="card-title">Recent Activity</span>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 14px; font-size: 13px;">
|
||||
<div style="border-left: 3px solid var(--primary-green); padding-left: 10px;">
|
||||
<div style="font-weight: 600;">Student Enrolled</div>
|
||||
<div style="font-size: 11px; color: var(--win-text-muted);">Juan Dela Cruz • Grade 10</div>
|
||||
</div>
|
||||
<div style="border-left: 3px solid var(--accent-cyan); padding-left: 10px;">
|
||||
<div style="font-weight: 600;">SF10 Verified</div>
|
||||
<div style="font-size: 11px; color: var(--win-text-muted);">Maria Clara Perez • Grade 9</div>
|
||||
</div>
|
||||
<div style="border-left: 3px solid var(--accent-amber); padding-left: 10px;">
|
||||
<div style="font-weight: 600;">Section Capacity Alert</div>
|
||||
<div style="font-size: 11px; color: var(--win-text-muted);">Grade 10 - Jacinto at 49/50</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Students View -->
|
||||
<div id="win-students" class="win-screen-view" style="display: none;">
|
||||
<div class="filter-chips">
|
||||
<button class="chip active" onclick="setStudentFilter('all', this)">All Students (1,482)</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 7', this)">Grade 7</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 8', this)">Grade 8</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 9', this)">Grade 9</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 10', this)">Grade 10</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 11', this)">Grade 11</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 12', this)">Grade 12</button>
|
||||
<button class="chip" onclick="setStudentFilter('male', this)">Male</button>
|
||||
<button class="chip" onclick="setStudentFilter('female', this)">Female</button>
|
||||
</div>
|
||||
|
||||
<div class="content-card" style="padding: 0; overflow: hidden;">
|
||||
<div class="table-responsive">
|
||||
<table class="tis-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Student Name</th>
|
||||
<th>LRN</th>
|
||||
<th>Grade</th>
|
||||
<th>Section</th>
|
||||
<th>Sex</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="students-table-body">
|
||||
<!-- Rendered via app.js -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Documents View -->
|
||||
<div id="win-documents" class="win-screen-view" style="display: none;">
|
||||
<div class="content-card" style="margin-bottom: 20px;">
|
||||
<h3 style="font-size: 15px; margin-bottom: 6px;">Document Verification Health</h3>
|
||||
<p style="font-size: 13px; color: var(--win-text-muted); margin-bottom: 14px;">Compliance progress for Learner Permanent Records (DepEd Form 137 / SF10).</p>
|
||||
<div class="bar-track" style="height: 14px;">
|
||||
<div class="bar-fill" style="width: 92%;"></div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 12px; margin-top: 8px; color: var(--win-text-muted);">
|
||||
<span>92% Verified (1,363 / 1,482 Students)</span>
|
||||
<span>119 Pending Verification</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="docs-grid-windows" style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<!-- Rendered via app.js -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Academic View -->
|
||||
<div id="win-academic" class="win-screen-view" style="display: none;">
|
||||
<div class="content-card" style="margin-bottom: 20px; background: linear-gradient(135deg, rgba(25, 135, 84, 0.12), rgba(6, 182, 212, 0.08)); border-color: rgba(25, 135, 84, 0.3);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<h3 style="font-size: 18px; font-weight: 800; color: var(--primary-green);">Academic Year 2026-2027</h3>
|
||||
<p style="font-size: 13px; color: var(--win-text-muted); margin-top: 2px;">Active Academic Period • DepEd Region IV-A CALABARZON</p>
|
||||
</div>
|
||||
<span class="status-badge badge-enrolled" style="font-size: 12px; padding: 6px 12px;">Active Term</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="classes-grid-windows" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px;">
|
||||
<!-- Rendered via app.js -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. Settings View -->
|
||||
<div id="win-settings" class="win-screen-view" style="display: none;">
|
||||
|
||||
<!-- Collapsible Card: About & App Updates (Exact feature implemented) -->
|
||||
<div class="settings-section">
|
||||
<div class="settings-header" onclick="toggleSettingsSection('about')">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span style="color: var(--primary-green);">ℹ</span>
|
||||
<span>About & App Updates</span>
|
||||
</div>
|
||||
<span id="settings-arrow-about" style="transition: transform 0.2s;">▼</span>
|
||||
</div>
|
||||
<div id="settings-body-about" class="settings-body">
|
||||
<div class="info-row"><span class="info-label">Application:</span><span class="info-val">Talipan Integrated School - RMS</span></div>
|
||||
<div class="info-row"><span class="info-label">Current Version:</span><span class="info-val">v1.0.23 (Build 24)</span></div>
|
||||
<div class="info-row"><span class="info-label">Platform:</span><span class="info-val">Windows x64 Desktop</span></div>
|
||||
<div class="info-row"><span class="info-label">Architecture:</span><span class="info-val">x64 (64-bit)</span></div>
|
||||
<div class="info-row"><span class="info-label">Institution:</span><span class="info-val">Talipan National High School</span></div>
|
||||
<div class="info-row"><span class="info-label">Developed By:</span><span class="info-val">Dalubhasaan ng Lungsod ng San Pablo (DLSP)</span></div>
|
||||
|
||||
<hr style="border: none; border-top: 1px solid var(--win-border); margin: 6px 0;">
|
||||
|
||||
<!-- Software Updates Section -->
|
||||
<div>
|
||||
<h4 style="font-size: 14px; font-weight: 700; margin-bottom: 4px;">Software Updates</h4>
|
||||
<p style="font-size: 12px; color: var(--win-text-muted); margin-bottom: 12px;">Checks latest GitHub release and matches machine architecture automatically.</p>
|
||||
|
||||
<div id="update-status-banner" style="display: none; padding: 12px; background: rgba(25, 135, 84, 0.1); border: 1px solid rgba(25, 135, 84, 0.3); border-radius: 8px; margin-bottom: 12px;"></div>
|
||||
|
||||
<button id="btn-check-update" class="btn-primary" onclick="simulateUpdateCheck()">
|
||||
<svg width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21.5 2v6h-6M21.34 15.57a10 10 0 1 1-.57-8.38l5.67-5.67"/></svg>
|
||||
<span id="btn-check-update-text">Check for Updates</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Collapsible Card: Appearance -->
|
||||
<div class="settings-section">
|
||||
<div class="settings-header" onclick="toggleSettingsSection('appearance')">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span style="color: var(--primary-green);">🎨</span>
|
||||
<span>Appearance & Sound</span>
|
||||
</div>
|
||||
<span id="settings-arrow-appearance" style="transition: transform 0.2s;">▼</span>
|
||||
</div>
|
||||
<div id="settings-body-appearance" class="settings-body">
|
||||
<div class="info-row"><span class="info-label">Interface Theme:</span><span class="info-val">Light / Dark Adaptive</span></div>
|
||||
<div class="info-row"><span class="info-label">Audio Feedback:</span><span class="info-val">Enabled (Chime on success)</span></div>
|
||||
<div class="info-row"><span class="info-label">Haptics:</span><span class="info-val">Enabled (Mobile vibrator)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Collapsible Card: Security -->
|
||||
<div class="settings-section">
|
||||
<div class="settings-header" onclick="toggleSettingsSection('security')">
|
||||
<div style="display: flex; align-items: center; gap: 12px;">
|
||||
<span style="color: var(--primary-green);">🔒</span>
|
||||
<span>Security & Account</span>
|
||||
</div>
|
||||
<span id="settings-arrow-security" style="transition: transform 0.2s;">▼</span>
|
||||
</div>
|
||||
<div id="settings-body-security" class="settings-body">
|
||||
<div class="info-row"><span class="info-label">User Role:</span><span class="info-val">Admin / Registrar</span></div>
|
||||
<div class="info-row"><span class="info-label">Active Session:</span><span class="info-val">Local Workstation (Active)</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- Hotspot: Check Updates on Settings Screen -->
|
||||
<div id="hotspot-settings-update" class="hotspot-settings-update" title="Click to test Check for Updates" onclick="openUpdateCheckModal()" style="display: none;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. ANDROID SMARTPHONE FRAME -->
|
||||
<div id="phone-mockup" class="phone-mockup" style="display: none;">
|
||||
<div class="phone-screen-container">
|
||||
<img id="phone-screen-img" class="phone-screen-img" src="screenshots/android/dashboard.webp" alt="Android Screen">
|
||||
|
||||
<!-- ==============================================================
|
||||
2. ANDROID MOBILE VIEW (Smartphone Frame Mockup)
|
||||
============================================================== -->
|
||||
<div id="phone-frame" class="phone-frame" style="display: none;">
|
||||
<!-- Dynamic Island / Speaker Notch -->
|
||||
<div class="phone-island"></div>
|
||||
|
||||
<!-- Android Status Bar -->
|
||||
<div class="phone-status-bar">
|
||||
<span id="phone-time">12:30</span>
|
||||
<div style="display: flex; align-items: center; gap: 6px;">
|
||||
<span>5G</span>
|
||||
<span>📶</span>
|
||||
<span>🔋</span>
|
||||
<!-- Hotspots for quick testing -->
|
||||
<div style="position: absolute; top: 12%; right: 5%; width: 50px; height: 50px; cursor: pointer;" title="Interactive Action" onclick="openAddStudentModal()"></div>
|
||||
<div style="position: absolute; bottom: 2%; left: 0; right: 0; height: 60px; display: flex;">
|
||||
<div style="flex: 1; cursor: pointer;" title="Dashboard" onclick="setScreen('dashboard')"></div>
|
||||
<div style="flex: 1; cursor: pointer;" title="Students" onclick="setScreen('students')"></div>
|
||||
<div style="flex: 1; cursor: pointer;" title="Documents" onclick="setScreen('documents')"></div>
|
||||
<div style="flex: 1; cursor: pointer;" title="Settings" onclick="setScreen('settings')"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Top App Header -->
|
||||
<div class="phone-app-header">
|
||||
<h3 id="phone-header-title">Dashboard Overview</h3>
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<span style="font-size: 18px; cursor: pointer;" onclick="openAddStudentModal()">➕</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phone Content Body -->
|
||||
<div class="phone-content">
|
||||
|
||||
<!-- Mobile: Dashboard -->
|
||||
<div id="phone-dashboard" class="phone-screen-view">
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon green">👥</div>
|
||||
<div class="stat-info">
|
||||
<h5>Students</h5>
|
||||
<h2>1,482</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon blue">✔</div>
|
||||
<div class="stat-info">
|
||||
<h5>Enrolled</h5>
|
||||
<h2>1,420</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon amber">⇄</div>
|
||||
<div class="stat-info">
|
||||
<h5>Transferred</h5>
|
||||
<h2>38</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon rose">⊘</div>
|
||||
<div class="stat-info">
|
||||
<h5>Dropped</h5>
|
||||
<h2>24</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-card" style="margin-top: 14px;">
|
||||
<div class="card-header">
|
||||
<span class="card-title">Enrollment per Grade</span>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">G7</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 88%;"></div></div>
|
||||
<span class="bar-val">280</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">G8</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 82%;"></div></div>
|
||||
<span class="bar-val">260</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">G9</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 79%;"></div></div>
|
||||
<span class="bar-val">250</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">G10</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 75%;"></div></div>
|
||||
<span class="bar-val">240</span>
|
||||
</div>
|
||||
<div class="bar-row">
|
||||
<span class="bar-label">SHS</span>
|
||||
<div class="bar-track"><div class="bar-fill" style="width: 70%;"></div></div>
|
||||
<span class="bar-val">452</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile: Students -->
|
||||
<div id="phone-students" class="phone-screen-view" style="display: none;">
|
||||
<div style="position: relative; margin-bottom: 10px;">
|
||||
<input type="text" placeholder="Search student name / LRN..." oninput="onSearchInput(this.value)" style="width: 100%; height: 38px; border-radius: 8px; border: 1px solid var(--win-border); background: var(--win-surface); color: var(--win-text); padding: 0 12px; font-size: 13px;">
|
||||
</div>
|
||||
<div class="filter-chips">
|
||||
<button class="chip active" onclick="setStudentFilter('all', this)">All</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 7', this)">G7</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 8', this)">G8</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 9', this)">G9</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 10', this)">G10</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 11', this)">G11</button>
|
||||
<button class="chip" onclick="setStudentFilter('Grade 12', this)">G12</button>
|
||||
</div>
|
||||
<div id="mobile-students-container" class="mobile-student-list">
|
||||
<!-- Rendered via app.js -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile: Documents -->
|
||||
<div id="phone-documents" class="phone-screen-view" style="display: none;">
|
||||
<div id="docs-list-phone" style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<!-- Rendered via app.js -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile: Academic -->
|
||||
<div id="phone-academic" class="phone-screen-view" style="display: none;">
|
||||
<div id="classes-list-phone" style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<!-- Rendered via app.js -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile: Settings -->
|
||||
<div id="phone-settings" class="phone-screen-view" style="display: none;">
|
||||
<div class="settings-section">
|
||||
<div class="settings-header">
|
||||
<span>About & App Updates</span>
|
||||
</div>
|
||||
<div class="settings-body" style="display: flex;">
|
||||
<div class="info-row"><span class="info-label">App:</span><span class="info-val">TIS-RMS Mobile</span></div>
|
||||
<div class="info-row"><span class="info-label">Version:</span><span class="info-val">v1.0.23 (Build 24)</span></div>
|
||||
<div class="info-row"><span class="info-label">Platform:</span><span class="info-val">Android</span></div>
|
||||
<div class="info-row"><span class="info-label">Architecture:</span><span class="info-val">ARM64 (64-bit)</span></div>
|
||||
<div class="info-row"><span class="info-label">Institution:</span><span class="info-val">Talipan NHS</span></div>
|
||||
<div class="info-row"><span class="info-label">Developed By:</span><span class="info-val">DLSP</span></div>
|
||||
|
||||
<button class="btn-primary" style="margin-top: 8px;" onclick="simulateUpdateCheck()">
|
||||
<span>Check for Updates</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Android Bottom Nav Bar -->
|
||||
<nav class="phone-bottom-nav">
|
||||
<div class="bottom-nav-item active" data-screen="dashboard">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
|
||||
<span>Home</span>
|
||||
</div>
|
||||
<div class="bottom-nav-item" data-screen="students">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle></svg>
|
||||
<span>Students</span>
|
||||
</div>
|
||||
<div class="bottom-nav-item" data-screen="documents">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>
|
||||
<span>Docs</span>
|
||||
</div>
|
||||
<div class="bottom-nav-item" data-screen="academic">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M22 10v6M2 10l10-5 10 5-10 5z"></path></svg>
|
||||
<span>Classes</span>
|
||||
</div>
|
||||
<div class="bottom-nav-item" data-screen="settings">
|
||||
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
<span>Settings</span>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<!-- ── Interactive Modals ────────────────────────────────────── -->
|
||||
|
||||
<!-- 1. Student Detail Modal -->
|
||||
<div id="student-modal" class="modal-overlay" onclick="if(event.target===this)closeModal('student-modal')">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-header">
|
||||
<h3>Student Information</h3>
|
||||
<button class="modal-close" onclick="closeModal('student-modal')">×</button>
|
||||
</div>
|
||||
<div id="student-modal-body" class="modal-body">
|
||||
<!-- Injected via app.js -->
|
||||
</div>
|
||||
<div style="padding: 14px 20px; border-top: 1px solid var(--win-border); display: flex; justify-content: flex-end; gap: 10px;">
|
||||
<button class="btn-secondary" onclick="closeModal('student-modal')">Close</button>
|
||||
<button class="btn-primary" onclick="closeModal('student-modal')">Print SF10</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Document Preview Modal -->
|
||||
<div id="doc-preview-modal" class="modal-overlay" onclick="if(event.target===this)closeModal('doc-preview-modal')">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-header">
|
||||
<h3 id="doc-preview-title">Document Preview</h3>
|
||||
<button class="modal-close" onclick="closeModal('doc-preview-modal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div style="background: var(--win-surface-subtle); border: 2px dashed var(--win-border); border-radius: 12px; height: 260px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; color: var(--win-text-muted);">
|
||||
<svg width="48" height="48" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line></svg>
|
||||
<div style="font-weight: 600; color: var(--win-text);">Simulated Scanned Document</div>
|
||||
<div id="doc-preview-code" style="font-size: 12px; font-family: monospace;">DOC-PSA</div>
|
||||
<div style="font-size: 11px;">Resolution: 300 DPI • OCR Confidence: 99.4%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 14px 20px; border-top: 1px solid var(--win-border); display: flex; justify-content: flex-end;">
|
||||
<button class="btn-secondary" onclick="closeModal('doc-preview-modal')">Close Preview</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Add Student Modal -->
|
||||
<!-- 1. Add Student Modal -->
|
||||
<div id="add-student-modal" class="modal-overlay" onclick="if(event.target===this)closeModal('add-student-modal')">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-header">
|
||||
@@ -599,37 +111,66 @@
|
||||
<button class="modal-close" onclick="closeModal('add-student-modal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p style="font-size: 13px; color: var(--win-text-muted);">Select standard registration or quick entry form:</p>
|
||||
|
||||
<p style="font-size: 13px; color: var(--text-muted); line-height: 1.5;">
|
||||
Select student registration method:
|
||||
</p>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<div class="content-card" style="cursor: pointer;" onclick="alert('Demo Mode: In the real app, this launches the multi-step student registration form.'); closeModal('add-student-modal');">
|
||||
<h4 style="font-size: 14px; font-weight: 700; margin-bottom: 2px;">Standard Form Entry</h4>
|
||||
<p style="font-size: 12px; color: var(--win-text-muted);">Fill out complete student profile, guardian contacts, and DepEd SF1 fields.</p>
|
||||
<div style="background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.1); border-radius: 10px; padding: 14px; cursor: pointer;" onclick="alert('Simulation: Launches the multi-step student enrollment form.'); closeModal('add-student-modal');">
|
||||
<h4 style="font-size: 14px; font-weight: 700; color: #fff;">Standard Stepper Form</h4>
|
||||
<p style="font-size: 12px; color: var(--text-muted); margin-top: 3px;">Full student biographical details, parent info, and LRN verification.</p>
|
||||
</div>
|
||||
|
||||
<div class="content-card" style="cursor: pointer;" onclick="alert('Demo Mode: In the real app, this prompts OCR scanning of PSA / SF10 records.'); closeModal('add-student-modal');">
|
||||
<h4 style="font-size: 14px; font-weight: 700; margin-bottom: 2px;">Document OCR Auto-Fill</h4>
|
||||
<p style="font-size: 12px; color: var(--win-text-muted);">Scan student certificate and automatically parse LRN, names, and birthday.</p>
|
||||
<div style="background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.1); border-radius: 10px; padding: 14px; cursor: pointer;" onclick="alert('Simulation: Launches OCR document scanning for automatic field extraction.'); closeModal('add-student-modal');">
|
||||
<h4 style="font-size: 14px; font-weight: 700; color: #fff;">Scan Document OCR</h4>
|
||||
<p style="font-size: 12px; color: var(--text-muted); margin-top: 3px;">Auto-extract student information directly from Birth Certificate or Form 137.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 14px 20px; border-top: 1px solid var(--win-border); display: flex; justify-content: flex-end;">
|
||||
<div style="padding: 14px 20px; border-top: 1px solid rgba(255, 255, 255, 0.1); display: flex; justify-content: flex-end;">
|
||||
<button class="btn-secondary" onclick="closeModal('add-student-modal')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Simulated Browser Download Toast -->
|
||||
<!-- 2. Software Update Check Modal -->
|
||||
<div id="update-modal" class="modal-overlay" onclick="if(event.target===this)closeModal('update-modal')">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-header">
|
||||
<h3>About & App Updates</h3>
|
||||
<button class="modal-close" onclick="closeModal('update-modal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="update-modal-status">
|
||||
<!-- Dynamically filled via app.js -->
|
||||
</div>
|
||||
</div>
|
||||
<div style="padding: 14px 20px; border-top: 1px solid rgba(255, 255, 255, 0.1); display: flex; justify-content: flex-end; gap: 10px;">
|
||||
<button class="btn-secondary" onclick="closeModal('update-modal')">Close</button>
|
||||
<button id="btn-download-action" class="btn-primary" style="display: none;">
|
||||
<span>Download in Browser</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Simulated Browser Download Toast -->
|
||||
<div id="browser-download-toast" class="browser-download-toast">
|
||||
<div class="toast-icon">
|
||||
<svg width="20" height="20" fill="none" stroke="#fff" stroke-width="2.5" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 13px; font-weight: 700;">Browser Download Launched</div>
|
||||
<div id="toast-filename" style="font-size: 11px; opacity: 0.85; font-family: monospace;">TIS_RMS_64_v1.0.24.apk</div>
|
||||
<div style="font-size: 13px; font-weight: 700;">Opening in Default Browser</div>
|
||||
<div id="toast-filename" style="font-size: 11px; opacity: 0.85; font-family: monospace;">TIS_RMS_Setup_v1.0.24.exe</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+237
-786
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user