tinyqc/public/js/app.js
mahdahar 18b85815ce refactor: standardize codebase with BaseModel and new conventions
- Add BaseModel with automatic camel/snake case conversion
- Add stringcase_helper with camel_to_snake(), snake_to_camel() functions
- Update all models to extend BaseModel for consistent data handling
- Update API controllers with standardized JSON response format
- Remove legacy v1 PHP application directory
- Consolidate documentation into AGENTS.md, delete VIEWS_RULES.md
2026-01-15 10:44:09 +07:00

89 lines
2.5 KiB
JavaScript

document.addEventListener('alpine:init', () => {
Alpine.store('appState', {
loading: false,
sidebarOpen: false
});
});
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;
if (window.Alpine) {
Alpine.store('appState').sidebarOpen = this.sidebarOpen;
}
});
}
if (backdrop) {
backdrop.addEventListener('click', () => {
this.sidebarOpen = false;
if (window.Alpine) {
Alpine.store('appState').sidebarOpen = false;
}
});
}
},
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();
});