feat: integrate Tagify for multi-tag support and add a new view-note modal across the application

This commit is contained in:
root
2026-03-29 16:25:45 +07:00
parent f4f842d658
commit 8dedb57692
8 changed files with 408 additions and 106 deletions

View File

@@ -34,6 +34,61 @@
setTimeout(() => t.classList.remove('show'), 3000);
}
// ── Custom Alert / Confirm ─────────────────────────────────────────────
function appAlert(msg) {
return new Promise(resolve => {
let modal = document.getElementById('app-alert-modal');
if(!modal) {
modal = document.createElement('div');
modal.id = 'app-alert-modal';
modal.className = 'modal-overlay';
modal.style.zIndex = '10005';
modal.innerHTML = `
<div class="modal-content" style="max-width:320px; text-align:center;">
<h3 style="margin-bottom:1rem; font-size:1.1rem;">Notice</h3>
<p style="margin-bottom:1.5rem; font-size:0.9rem; color:var(--text);" id="app-alert-msg"></p>
<button class="btn" style="width:100%;" id="app-alert-ok">OK</button>
</div>`;
document.body.appendChild(modal);
}
document.getElementById('app-alert-msg').textContent = msg;
modal.classList.add('active');
document.getElementById('app-alert-ok').onclick = () => { modal.classList.remove('active'); resolve(true); };
});
}
window.alert = function(msg) { appAlert(msg); };
function appConfirm(msg) {
return new Promise(resolve => {
let modal = document.getElementById('app-confirm-modal');
if(!modal) {
modal = document.createElement('div');
modal.id = 'app-confirm-modal';
modal.className = 'modal-overlay';
modal.style.zIndex = '10005';
modal.innerHTML = `
<div class="modal-content" style="max-width:350px;">
<h3 style="margin-bottom:0.75rem; font-size:1.1rem; text-align:center;">Confirmation</h3>
<p style="margin-bottom:1.5rem; font-size:0.95rem; color:var(--text); text-align:center; line-height:1.4;" id="app-confirm-msg"></p>
<div style="display:flex; gap:0.5rem;">
<button class="btn btn-secondary" style="flex:1;" id="app-confirm-no">Cancel</button>
<button class="btn btn-danger" style="flex:1;" id="app-confirm-yes">Confirm</button>
</div>
</div>`;
document.body.appendChild(modal);
}
document.getElementById('app-confirm-msg').textContent = msg;
modal.classList.add('active');
document.getElementById('app-confirm-no').onclick = () => { modal.classList.remove('active'); resolve(false); };
document.getElementById('app-confirm-yes').onclick = () => { modal.classList.remove('active'); resolve(true); };
});
}
function appConfirmUrl(event, url, msg) {
event.preventDefault();
appConfirm(msg).then(yes => { if(yes) window.location.href = url; });
}
// ── Sidebar Collapse ──────────────────────────────────────────────────
function toggleSidebar() {
const collapsed = document.body.classList.toggle('sidebar-collapsed');
@@ -87,6 +142,19 @@
document.getElementById('change-pw-modal').classList.add('active');
});
<?php endif; ?>
// ── Tagify globally ───────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
if(typeof Tagify !== 'undefined' && window.APP_GLOBAL_TAGS) {
document.querySelectorAll('.tagify-input').forEach(el => {
new Tagify(el, {
whitelist: window.APP_GLOBAL_TAGS,
dropdown: { maxItems: 20, classname: "tags-look", enabled: 0, closeOnSelect: false },
originalInputValueFormat: valuesArr => valuesArr.map(item => item.value).join(',')
});
});
}
});
</script>
</body>
</html>