File: //proc/self/cwd/wp-content/plugins/woodmart-plus/assets/admin/js/admin-pattern.js
(function($){
let patterns = adminPatternObject.patterns;
let createdVariables = [];
// Initialize
$(document).ready(function() {
renderPatterns();
$('#patternText').on('input', function() {
$('#charCount').text($(this).val().length);
});
$('#patternForm').on('submit', function(e) {
e.preventDefault();
savePattern();
});
$('#navList').click(() => showPage('list'));
$('#navCreate').click(() => showPage('create'));
$('.create_pattern--now').click(() => showPage('create'));
$('.add-variable-btn').click(() => openVariableModal());
$('.add-variable-from-modal').click(() => addVariable());
$('.close-variable-modal').click(() => closeVariableModal());
$('.leave-from-add-pattern').click(() => showPage('list'));
removeVariable();
insertVariable();
showDetails();
editPattern();
deletePattern();
closeDetailsModal();
});
// Page Navigation
function showPage(page,type='create',id='') {
$('.page').removeClass('update-pattern');
$('.page').removeClass('active');
$('.nav-btn').removeClass('active');
if (page === 'list') {
$('#listPage').addClass('active');
$('#navList').addClass('active');
} else {
$('#createPage').addClass('active');
$('#navCreate').addClass('active');
resetForm();
}
if( type === 'update' )
{
$('#createPage').addClass('update-pattern');
$('#patternForm').attr('data-pattern_code',id);
}
}
// Render Patterns
function renderPatterns() {
let tableHtml = '';
let cardHtml = '';
patterns.forEach(pattern => {
const statusClass = pattern.status === 'active' ? 'badge-green' : 'badge-red';
const statusText = pattern.status_fa;
const sharedClass = pattern.isShared;
// const sharedIcon = pattern.isShared
// ? '<svg fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg>'
// : '<svg fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/></svg>';
let is_updated = '';
let is_pending = '';
const variableTags = pattern.variables.map(v =>
`<span class="variable-tag">%${v.name}%</span>`
).join('');
if( 'pending' === pattern.pattern_state_revision )
{
is_updated = pattern.pattern_status_fa;
is_pending = 'pending';
}
// Table row
tableHtml += `
<tr>
<td style="font-weight: 600;">${pattern.title}</td>
<td><span class="badge badge-blue">${pattern.type}</span></td>
<td style="font-family: monospace; color: #6b7280;">${pattern.code}</td>
<td><div class="variables-container">${variableTags}</div></td>
<td style="color: #6b7280;">${pattern.updateDate}</td>
<td><div class="shared-icon">${sharedClass}</div></td>
<td><span class="badge ${statusClass}">${statusText}</span><span class="badge ${is_pending}">${is_updated}</span></td>
<td>
<div class="action-buttons">
<button data-pattern_id="${pattern.id}" class="action-btn view-pattern" title="جزئیات">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"/>
</svg>
</button>
<button data-pattern_id="${pattern.id}" class="action-btn edit-pattern" title="ویرایش">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
</button>
<button data-pattern_id="${pattern.id}" class="action-btn delete-pattern" title="حذف">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
</button>
</div>
</td>
</tr>
`;
// Card for mobile
cardHtml += `
<div class="pattern-card">
<div class="pattern-card-header">
<div>
<div class="pattern-card-title">${pattern.title}</div>
<div class="pattern-card-code">${pattern.code}</div>
</div>
<span class="badge ${statusClass}">${statusText}</span>
<span class="badge ${is_pending}">${is_updated}</span>
</div>
<div class="pattern-card-row">
<span class="pattern-card-label">نوع:</span>
<span class="badge badge-blue">${pattern.type}</span>
</div>
<div class="pattern-card-row" style="flex-wrap: wrap;">
<span class="pattern-card-label">متغیرها:</span>
<div class="variables-container">${variableTags}</div>
</div>
<div class="pattern-card-row">
<span class="pattern-card-label">تاریخ بروزرسانی:</span>
<span>${pattern.updateDate}</span>
</div>
<div class="pattern-card-row">
<span class="pattern-card-label">اشتراکی:</span>
<div class="shared-icon">${sharedClass}</div>
</div>
<div class="pattern-card-actions">
<button data-pattern_id="${pattern.id}" class="pattern-card-btn view-pattern">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
جزئیات
</button>
<button data-pattern_id="${pattern.id}" class="pattern-card-btn edit-pattern">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
</svg>
ویرایش
</button>
<button data-pattern_id="${pattern.id}" class="pattern-card-btn delete-pattern">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
</svg>
</button>
</div>
</div>
`;
});
$('#patternTableBody').html(tableHtml);
$('#patternCards').html(cardHtml);
}
// Variable Modal
function openVariableModal() {
$('#variableModal').addClass('show');
$('#variableName').val('').focus();
$('#variableType').val('text');
}
function closeVariableModal() {
$('#variableModal').removeClass('show');
}
function addVariable() {
const name = $('#variableName').val().trim();
const type = $('#variableType').val();
if (!name) {
showToast('لطفا نام متغیر را وارد کنید', 'error');
return;
}
if (createdVariables.find(v => v.name === name)) {
showToast('این متغیر قبلا اضافه شده است', 'error');
return;
}
createdVariables.push({ name, type });
renderVariables();
closeVariableModal();
showToast('متغیر با موفقیت اضافه شد');
}
function renderVariables() {
if (createdVariables.length === 0) {
$('#variablesList').html('<span class="no-variables" id="noVarText">هنوز متغیری اضافه نشده است</span>');
return;
}
const typeLabels = {
string: 'متن',
integer: 'عدد',
date: 'تاریخ',
phone: 'تلفن',
email: 'ایمیل',
url: 'لینک'
};
const html = createdVariables.map((v, index) => `
<div class="variable-item" data-for-insert="${v.name}" ">
<span>%${v.name}%</span>
<span class="variable-type">${typeLabels[v.type]}</span>
<button type="button" data-varialbe="${index}" class="variable-remove">
<svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
</button>
</div>
`).join('');
$('#variablesList').html(html);
}
function removeVariable() {
$(document).on('click','.variable-remove',function(e){
var index = $(this).attr('data-varialbe');
createdVariables.splice(index, 1);
renderVariables();
});
}
function insertVariable() {
$(document).on('click','.variable-item',function(e){
var $this = $(this);
var name = $this.attr('data-for-insert');
const textarea = document.getElementById('patternText');
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
const text = textarea.value;
const variable = `%${name}%`;
textarea.value = text.substring(0, start) + variable + text.substring(end);
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = start + variable.length;
$('#charCount').text(textarea.value.length);
});
}
// Details Modal
function showDetails() {
$(document).on('click','.view-pattern',function(e){
var $this = $(this);
var id = $this.attr('data-pattern_id');
const pattern = patterns.find(p => p.id === id);
if (!pattern) return;
const statusClass = pattern.status === 'active' ? 'badge-green' : 'badge-red';
const statusText = pattern.status === 'active' ? 'فعال' : 'غیرفعال';
const admin_comment = pattern.admin_comment;
const variableTags = pattern.variables.map(v =>
`<span class="variable-tag">%${v.name}%</span>`
).join('');
const html = `
<div class="detail-grid">
<div class="detail-item detail-full">
<div class="detail-label">علت رد / تایید</div>
<div class="variables-container" style="margin-top: 8px;">${admin_comment}</div>
</div>
<div class="detail-item">
<div class="detail-label">عنوان</div>
<div class="detail-value">${pattern.title}</div>
</div>
<div class="detail-item">
<div class="detail-label">کد پترن</div>
<div class="detail-value" style="font-family: monospace;">${pattern.code}</div>
</div>
<div class="detail-item">
<div class="detail-label">نوع</div>
<div class="detail-value"><span class="badge badge-blue">${pattern.type}</span></div>
</div>
<div class="detail-item">
<div class="detail-label">وضعیت</div>
<div class="detail-value"><span class="badge ${statusClass}">${statusText}</span></div>
</div>
<div class="detail-item detail-full">
<div class="detail-label">متغیرها</div>
<div class="variables-container" style="margin-top: 8px;">${variableTags}</div>
</div>
</div>
<div class="detail-text-box">
<div class="detail-text-label">متن پیامک</div>
<div class="detail-text-content">${pattern.text}</div>
</div>
<div class="detail-item" style="margin-bottom: 20px;">
<div class="detail-label">توضیحات</div>
<div class="detail-value" style="font-weight: 400; margin-top: 6px;">${pattern.description}</div>
</div>
<div class="detail-footer">
<span>تاریخ بروزرسانی: ${pattern.updateDate}</span>
</div>
`;
$('#detailsContent').html(html);
$('#detailsModal').addClass('show');
});
}
function closeDetailsModal(){
$(document).on('click','#detailsModal',function(e){
$('#detailsModal').removeClass('show');
});
}
// Edit Pattern
function editPattern() {
$(document).on('click','.edit-pattern',function(e){
var $this = $(this);
var id = $this.attr('data-pattern_id')
const pattern = patterns.find(p => p.id === id);
if (!pattern) return;
showPage('create','update',pattern.code);
$('#patternTitle').val(pattern.title);
$('#patternType').val(
pattern.type === 'تبلیغاتی' ? 'promotional' :
pattern.type === 'اطلاعرسانی' ? 'informational' :
pattern.type === 'تایید هویت' ? 'verification' : 'reminder'
);
$('#patternText').val(pattern.text);
$('#patternDescription').val(pattern.description);
$('#patternWebsite').val(pattern.website);
$('#isShared').prop('checked', pattern.isShared);
$('#isActive').prop('checked', pattern.status === 'active');
$('#charCount').text(pattern.text.length);
createdVariables = pattern.variables.map(v => ({ name: v.name, type: v.type }));
renderVariables();
});
}
// Delete Pattern
function deletePattern() {
$(document).on('click','.delete-pattern',function(e){
var $this = $(this);
var id = $this.attr('data-pattern_id');
var parrent = $this.parents('tr');
parrent.addClass("is-loading");
const pattern = patterns.find(p => p.id === id);
const pattern_code = pattern.code;
if (confirm('آیا از حذف این پترن اطمینان دارید؟')) {
$.ajax({
dataType : 'json', type:'POST', url : ajaxurl,
data:{
action : 'delete_pattern',
pattern_code : pattern_code,
nonce : adminPatternObject.nonce
},
success: function(response)
{
showToast(response.message);
patterns = patterns.filter(p => p.id !== id);
renderPatterns();
parrent.removeClass("is-loading");
},
error : function(error)
{
parrent.removeClass("is-loading");
showToast(error.responseJSON.message,'error');
}
});
}
});
}
// Save Pattern
function savePattern() {
const title = $('#patternTitle').val().trim();
const type = $('#patternType option:selected').text();
const text = $('#patternText').val().trim();
const description = $('#patternDescription').val().trim();
const isShared = $('#isShared').is(':checked');
const isActive = $('#isActive').is(':checked');
const website = $('#patternWebsite').val().trim();
const id = $('#patternForm').attr('data-pattern_code');
let action = 'generate_pattern';
if (!title || !text) {
showToast('لطفا فیلدهای ضروری را پر کنید', 'error');
return;
}
// پیدا کردن دکمه submit و اضافه کردن لودر
const $submitButton = $('#patternForm button[type="submit"]');
$submitButton.prop('disabled', true).addClass('loading');
let newPattern = {
title,
text,
description,
website ,
variables: createdVariables.map(v => ({
name: v.name,
type: v.type
}))
};
if( $('body .update-pattern').length )
{
action = 'update_pattern';
newPattern.id = id;
}
$.ajax({
dataType:'json', type : 'POST', url : ajaxurl,
data : {
action : action,
pattern : newPattern,
nonce : adminPatternObject.nonce
},
success:function(response)
{
console.log( response.data );
patterns.unshift(response.data);
renderPatterns();
showPage('list');
showToast( response.message );
},
error: function(error)
{
showToast(error.responseJSON.message,'error');
},
complete: function()
{
// فعال کردن دکمه و حذف لودر
$submitButton.prop('disabled', false).removeClass('loading');
}
});
}
// Reset Form
function resetForm() {
$('#patternForm')[0].reset();
createdVariables = [];
renderVariables();
$('#charCount').text('0');
}
// Toast
function showToast(message, type = 'success') {
const toast = $('#toast');
toast.removeClass('success error').addClass(type);
$('#toastMessage').text(message);
toast.addClass('show');
setTimeout(() => {
toast.removeClass('show');
}, 3000);
}
// Close modals on outside click
$(document).on('click', '.modal-overlay', function(e) {
if (e.target === this) {
$(this).removeClass('show');
}
});
// Close modals on Escape
$(document).on('keydown', function(e) {
if (e.key === 'Escape') {
$('.modal-overlay').removeClass('show');
}
});
})(jQuery);