Files
2026-09-18 19:30:05 +07:00

178 lines
7.5 KiB
JavaScript

/* templates.js — Halaman manajemen template pesan */
(function () {
'use strict';
var $ = function (s, r) { return (r || document).querySelector(s); };
function esc(v) { return UI.escape(v); }
function sampleContext() {
return {
nama: 'Budi Santoso',
posisi: 'Staff Administrasi',
perusahaan: Store.get().settings.perusahaan || 'E-recruitment',
status: 'Interview',
tanggal: '22 September 2025',
hari: 'Senin',
tanggal_lengkap: 'Senin, 22 September 2025',
tanggal_melamar: '10 September 2025',
jam: '10:00',
metode: 'Online',
lokasi: 'Google Meet',
pewawancara: 'Andi Wijaya',
hr: Store.get().settings.hr || 'HRD',
jabatan_hr: Store.get().settings.jabatanHr || ''
};
}
function init() {
Store.init();
render();
$('#btnAddTpl').addEventListener('click', function () { openForm(null); });
}
function statusName(id) {
var s = Store.statusById(id);
return s ? s.nama : null;
}
function render() {
var list = Store.get().templates;
var wrap = $('#tplList');
if (!list.length) {
wrap.innerHTML = '';
$('#tplEmpty').classList.remove('hidden');
return;
}
$('#tplEmpty').classList.add('hidden');
wrap.innerHTML = list.map(function (t) {
var st = statusName(t.statusId);
var meta = [];
var jenisLabel = t.jenis === 'reminder' ? 'Reminder' : (t.jenis === 'pewawancara' ? 'Pewawancara' : 'Umum');
var jenisWarna = t.jenis === 'reminder' ? '#d97706' : (t.jenis === 'pewawancara' ? '#7c3aed' : '#2563eb');
meta.push('<span class="badge" style="background:' + jenisWarna + '">' + jenisLabel + '</span>');
if (st) meta.push('<span class="muted small">Status: ' + esc(st) + '</span>');
meta.push('<span class="' + (t.isActive ? '' : 'muted') + ' small">' + (t.isActive ? 'Aktif' : 'Nonaktif') + '</span>');
return '<div class="template-item">' +
'<div class="ti-head">' +
'<div><strong>' + esc(t.nama) + '</strong><div class="mt1">' + meta.join(' ') + '</div></div>' +
'<div class="actions">' +
'<button class="btn btn-ghost btn-sm" data-tpl-toggle="' + t.id + '">' + (t.isActive ? 'Nonaktifkan' : 'Aktifkan') + '</button>' +
'<button class="btn btn-ghost btn-sm" data-tpl-edit="' + t.id + '">Edit</button>' +
'<button class="btn btn-danger btn-sm" data-tpl-del="' + t.id + '">Hapus</button>' +
'</div>' +
'</div>' +
'<pre>' + esc(t.isi) + '</pre>' +
'</div>';
}).join('');
}
function statusOptions(selected) {
return '<option value="">- Tidak terkait status -</option>' +
Store.sortedStatuses().map(function (s) {
return '<option value="' + esc(s.id) + '"' + (s.id === selected ? ' selected' : '') + '>' + esc(s.nama) + '</option>';
}).join('');
}
function openForm(id) {
var t = id ? Store.templateById(id) : null;
var chips = WA.PLACEHOLDERS.map(function (p) {
return '<span class="chip" data-ins="' + p + '">{{' + p + '}}</span>';
}).join('');
var body =
'<div class="grid cols-2">' +
'<div class="field"><label for="t-nama">Nama template *</label><input type="text" id="t-nama" value="' + esc(t ? t.nama : '') + '"></div>' +
'<div class="field"><label for="t-jenis">Jenis</label><select id="t-jenis">' +
'<option value="umum"' + (t && t.jenis === 'umum' ? ' selected' : '') + '>Umum</option>' +
'<option value="reminder"' + (t && t.jenis === 'reminder' ? ' selected' : '') + '>Reminder Interview (Pelamar)</option>' +
'<option value="pewawancara"' + (t && t.jenis === 'pewawancara' ? ' selected' : '') + '>Reminder Interview (Pewawancara)</option>' +
'</select></div>' +
'</div>' +
'<div class="grid cols-2">' +
'<div class="field"><label for="t-status">Terkait status</label><select id="t-status">' + statusOptions(t ? t.statusId : '') + '</select></div>' +
'<div class="field"><label for="t-active">Status template</label><select id="t-active">' +
'<option value="1"' + (!t || t.isActive ? ' selected' : '') + '>Aktif</option>' +
'<option value="0"' + (t && !t.isActive ? ' selected' : '') + '>Nonaktif</option>' +
'</select></div>' +
'</div>' +
'<div class="field"><label>Placeholder (klik untuk menyisipkan)</label><div class="placeholder-btns">' + chips + '</div></div>' +
'<div class="field"><label for="t-isi">Isi pesan *</label><textarea id="t-isi" style="min-height:200px">' + esc(t ? t.isi : '') + '</textarea></div>' +
'<div class="field"><label>Preview (contoh data)</label><div class="preview-box" id="t-preview"></div></div>';
var footer =
'<button class="btn btn-ghost" type="button" data-close>Batal</button>' +
'<button class="btn btn-primary" type="button" id="saveTpl">' + (id ? 'Simpan Perubahan' : 'Tambah Template') + '</button>';
UI.openModal({
title: id ? 'Edit Template' : 'Tambah Template',
size: 'lg',
body: body,
footer: footer,
onMount: function (el) {
var isi = el.querySelector('#t-isi');
var prev = el.querySelector('#t-preview');
function update() { prev.textContent = WA.render(isi.value, sampleContext()); }
isi.addEventListener('input', update);
update();
el.querySelectorAll('[data-ins]').forEach(function (chip) {
chip.addEventListener('click', function () {
var text = '{{' + chip.getAttribute('data-ins') + '}}';
var start = isi.selectionStart, end = isi.selectionEnd;
isi.value = isi.value.slice(0, start) + text + isi.value.slice(end);
isi.selectionStart = isi.selectionEnd = start + text.length;
isi.focus();
update();
});
});
el.querySelector('[data-close]').addEventListener('click', UI.closeModal);
el.querySelector('#saveTpl').addEventListener('click', function () {
var nama = el.querySelector('#t-nama').value.trim();
var isiVal = isi.value;
if (!nama) { UI.toast('Nama template wajib diisi.', 'err'); return; }
if (!isiVal.trim()) { UI.toast('Isi pesan wajib diisi.', 'err'); return; }
var data = {
nama: nama,
jenis: el.querySelector('#t-jenis').value,
statusId: el.querySelector('#t-status').value || null,
isActive: el.querySelector('#t-active').value === '1',
isi: isiVal
};
if (id) { Store.updateTemplate(id, data); UI.toast('Template diperbarui.', 'ok'); }
else { Store.addTemplate(data); UI.toast('Template ditambahkan.', 'ok'); }
UI.closeModal();
render();
});
}
});
}
document.addEventListener('click', function (e) {
var edit = e.target.closest('[data-tpl-edit]');
if (edit) { openForm(edit.getAttribute('data-tpl-edit')); return; }
var del = e.target.closest('[data-tpl-del]');
if (del) {
var t = Store.templateById(del.getAttribute('data-tpl-del'));
if (t && UI.confirmDialog('Hapus template "' + t.nama + '"?')) {
Store.deleteTemplate(t.id);
UI.toast('Template dihapus.', 'ok');
render();
}
return;
}
var tog = e.target.closest('[data-tpl-toggle]');
if (tog) {
var tt = Store.templateById(tog.getAttribute('data-tpl-toggle'));
if (tt) { Store.updateTemplate(tt.id, { isActive: !tt.isActive }); render(); }
}
});
document.addEventListener('DOMContentLoaded', init);
})();