2026-01-15 10:44:09 +07:00
|
|
|
document.addEventListener('alpine:init', () => {
|
|
|
|
|
Alpine.store('appState', {
|
|
|
|
|
loading: false,
|
|
|
|
|
sidebarOpen: false
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
Initial commit: Add CodeIgniter 4 QC application with full MVC structure
- CodeIgniter 4 framework setup with SQL Server database config
- Models: Control, Test, Dept, Result, Daily/ Monthly entry models
- Controllers: Dashboard, Control, Test, Dept, Entry, Report, API endpoints
- Views: CRUD pages with modal dialogs, dashboard, reports
- Database: Migrations for control test and daily/monthly result tables
- Legacy v1 PHP application preserved in /v1 directory
- Documentation: AGENTS.md, VIEWS_RULES.md for development guidelines
2026-01-14 16:49:27 +07:00
|
|
|
window.App = {
|
|
|
|
|
loading: false,
|
|
|
|
|
sidebarOpen: false,
|
|
|
|
|
|
|
|
|
|
init() {
|
|
|
|
|
this.setupSidebar();
|
|
|
|
|
this.setupKeyboardShortcuts();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
setupSidebar() {
|
|
|
|
|
const sidebar = document.getElementById('sidebar');
|
|
|
|
|
const backdrop = document.getElementById('sidebar-backdrop');
|
|
|
|
|
const toggleBtn = document.getElementById('sidebar-toggle');
|
|
|
|
|
|
|
|
|
|
if (toggleBtn) {
|
|
|
|
|
toggleBtn.addEventListener('click', () => {
|
|
|
|
|
this.sidebarOpen = !this.sidebarOpen;
|
2026-01-15 10:44:09 +07:00
|
|
|
if (window.Alpine) {
|
|
|
|
|
Alpine.store('appState').sidebarOpen = this.sidebarOpen;
|
|
|
|
|
}
|
Initial commit: Add CodeIgniter 4 QC application with full MVC structure
- CodeIgniter 4 framework setup with SQL Server database config
- Models: Control, Test, Dept, Result, Daily/ Monthly entry models
- Controllers: Dashboard, Control, Test, Dept, Entry, Report, API endpoints
- Views: CRUD pages with modal dialogs, dashboard, reports
- Database: Migrations for control test and daily/monthly result tables
- Legacy v1 PHP application preserved in /v1 directory
- Documentation: AGENTS.md, VIEWS_RULES.md for development guidelines
2026-01-14 16:49:27 +07:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (backdrop) {
|
|
|
|
|
backdrop.addEventListener('click', () => {
|
|
|
|
|
this.sidebarOpen = false;
|
2026-01-15 10:44:09 +07:00
|
|
|
if (window.Alpine) {
|
|
|
|
|
Alpine.store('appState').sidebarOpen = false;
|
|
|
|
|
}
|
Initial commit: Add CodeIgniter 4 QC application with full MVC structure
- CodeIgniter 4 framework setup with SQL Server database config
- Models: Control, Test, Dept, Result, Daily/ Monthly entry models
- Controllers: Dashboard, Control, Test, Dept, Entry, Report, API endpoints
- Views: CRUD pages with modal dialogs, dashboard, reports
- Database: Migrations for control test and daily/monthly result tables
- Legacy v1 PHP application preserved in /v1 directory
- Documentation: AGENTS.md, VIEWS_RULES.md for development guidelines
2026-01-14 16:49:27 +07:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
setupKeyboardShortcuts() {
|
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
|
|
|
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
const saveBtn = document.querySelector('[data-save-btn]');
|
|
|
|
|
if (saveBtn && confirm('Save changes?')) {
|
|
|
|
|
saveBtn.click();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (e.key === 'Escape') {
|
|
|
|
|
this.closeAllModals();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
closeAllModals() {
|
|
|
|
|
document.querySelectorAll('[x-data]').forEach(el => {
|
|
|
|
|
if (el._x_dataStack) {
|
|
|
|
|
const data = el._x_dataStack[0];
|
|
|
|
|
if (typeof data.open !== 'undefined') data.open = false;
|
|
|
|
|
if (typeof data.showModal !== 'undefined') data.showModal = false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showToast(message, type = 'success') {
|
|
|
|
|
Toastify({
|
|
|
|
|
text: message,
|
|
|
|
|
duration: 3000,
|
|
|
|
|
gravity: 'top',
|
|
|
|
|
position: 'right',
|
|
|
|
|
className: type === 'success' ? 'bg-green-500' : type === 'error' ? 'bg-red-500' : 'bg-blue-500',
|
|
|
|
|
stopOnFocus: true
|
|
|
|
|
}).showToast();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
confirmAction(message = 'Are you sure?') {
|
|
|
|
|
return confirm(message);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
confirmSave(message = 'Save changes?') {
|
|
|
|
|
return confirm(message);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
|
App.init();
|
|
|
|
|
});
|