- Nowa tabela sms_templates (name + body + is_active) + minimalny CRUD.
- /settings/sms-templates: lista + formularz z paleta zmiennych (pill chips).
- Wydzielono Sms\SmsVariableResolver ze wspolna logika placeholderow;
Email\VariableResolver staje sie cienka fasada — EmailSendingService bez zmian.
- Dropdown "Wybierz szablon" w zakladce SMS na /orders/{id} z fetch
GET /orders/{id}/sms/template + OrderProAlerts.confirm przy nadpisaniu.
- Stopka SMSPLANET dalej doklejana wylacznie przez SmsConversationService
(Phase 122 contract preserved).
- Sidebar Ustawien: nowy link "Szablony SMS".
Migration: 20260512_000112_create_sms_templates.sql (CREATE TABLE).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
3.0 KiB
JavaScript
97 lines
3.0 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
if (window.__smsTemplatePickerBound) return;
|
|
window.__smsTemplatePickerBound = true;
|
|
|
|
function findTarget(picker) {
|
|
var targetId = picker.getAttribute('data-message-target');
|
|
if (!targetId) return null;
|
|
return document.getElementById(targetId);
|
|
}
|
|
|
|
function applyBody(textarea, body) {
|
|
textarea.value = body;
|
|
textarea.dispatchEvent(new Event('input', { bubbles: true }));
|
|
textarea.focus();
|
|
}
|
|
|
|
function bind(picker) {
|
|
if (picker.dataset.smsPickerBound === '1') return;
|
|
picker.dataset.smsPickerBound = '1';
|
|
|
|
picker.addEventListener('change', function () {
|
|
var templateId = parseInt(picker.value, 10);
|
|
var orderId = parseInt(picker.getAttribute('data-order-id'), 10);
|
|
if (!templateId || !orderId) {
|
|
return;
|
|
}
|
|
var textarea = findTarget(picker);
|
|
if (!textarea) {
|
|
picker.value = '';
|
|
return;
|
|
}
|
|
|
|
var doFetch = function () {
|
|
picker.disabled = true;
|
|
fetch('/orders/' + orderId + '/sms/template?template_id=' + templateId, {
|
|
headers: { 'Accept': 'application/json' },
|
|
credentials: 'same-origin'
|
|
})
|
|
.then(function (r) { return r.json(); })
|
|
.then(function (data) {
|
|
if (data && data.ok && typeof data.body === 'string') {
|
|
applyBody(textarea, data.body);
|
|
} else if (window.OrderProAlerts && window.OrderProAlerts.alert) {
|
|
window.OrderProAlerts.alert({
|
|
title: 'Nie udalo sie wczytac szablonu',
|
|
message: (data && data.error) ? String(data.error) : 'Sprobuj ponownie.'
|
|
});
|
|
}
|
|
})
|
|
.catch(function () {})
|
|
.finally(function () {
|
|
picker.disabled = false;
|
|
picker.value = '';
|
|
});
|
|
};
|
|
|
|
var current = (textarea.value || '').trim();
|
|
if (current === '') {
|
|
doFetch();
|
|
return;
|
|
}
|
|
|
|
if (window.OrderProAlerts && typeof window.OrderProAlerts.confirm === 'function') {
|
|
var triggered = false;
|
|
var run = function () { if (!triggered) { triggered = true; doFetch(); } };
|
|
var result = window.OrderProAlerts.confirm({
|
|
title: 'Zamiana tresci',
|
|
message: 'Tekst w polu wiadomosci zostanie nadpisany trescia szablonu. Kontynuowac?',
|
|
confirmLabel: 'Wstaw szablon',
|
|
danger: false,
|
|
onConfirm: run,
|
|
onCancel: function () { picker.value = ''; }
|
|
});
|
|
if (result && typeof result.then === 'function') {
|
|
result.then(function (ok) { if (ok) run(); else picker.value = ''; });
|
|
}
|
|
} else if (window.confirm('Tekst w polu wiadomosci zostanie nadpisany. Kontynuowac?')) {
|
|
doFetch();
|
|
} else {
|
|
picker.value = '';
|
|
}
|
|
});
|
|
}
|
|
|
|
function init() {
|
|
document.querySelectorAll('[data-sms-template-picker]').forEach(bind);
|
|
}
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
})();
|