178 lines
7.5 KiB
JavaScript
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);
|
|
})();
|