var IeBomTreeEditor = (function () {
var $root, bomId, storeUrl, moveUrl, updateBase, deleteBase;
var applyTemplateUrl, saveTemplateUrl, deleteTemplateUrl, duplicateUrl;
var selectedParentId = null, selectedParentName = '';
var selectedLineId = null;
var clipboardBranchId = null, clipboardBranchName = '';
var THEME_STORAGE_KEY = 'ie_bom_tree_theme';
var THEME_DEFAULT_KEY = 'ie_bom_tree_theme_default';
var COLLAPSE_STORAGE_KEY = 'ie_bom_tree_collapsed';
var CLIPBOARD_STORAGE_KEY = 'ie_bom_tree_clipboard';
var themeLabels = {};
var defaultThemeId = '18';
function init() {
$root = $('#ie_structure_editor');
if (!$root.length) return;
bomId = $root.data('bom-id');
storeUrl = $root.data('store-url');
moveUrl = $root.data('move-url');
updateBase = $root.data('update-url');
deleteBase = $root.data('delete-url');
applyTemplateUrl = $root.data('apply-template-url');
saveTemplateUrl = $root.data('save-template-url');
deleteTemplateUrl = $root.data('delete-template-url');
duplicateUrl = $root.data('duplicate-url');
$('#ie_bom_nestable').nestable({ maxDepth: 20, group: 1 });
// Prevent drag when clicking action buttons and toggles
$root.on('mousedown click', '.ie-node-actions .btn, .ie-node-actions, .ie-btn-toggle-branch', function (e) {
e.stopPropagation();
});
$('#ie_save_tree').on('click', saveTree);
$('#ie_add_root_node').on('click', function () {
resetForm(null);
setTemplateParent(null, '');
});
$('#ie_node_form').on('submit', submitNode);
$root.on('click', '.ie-btn-add-child', function () {
var id = $(this).data('id');
var name = $(this).data('name') || '';
resetForm(id);
setTemplateParent(id, name);
});
$root.on('click', '.ie-btn-edit-node', function () {
var id = $(this).data('id');
loadNodeForEdit(id);
selectedLineId = id;
});
$root.on('click', '.ie-btn-delete-node', function () {
deleteNode($(this).data('id'));
});
$root.on('click', '.ie-btn-select-parent', function () {
setTemplateParent($(this).data('id'), $(this).data('name') || '');
selectedLineId = $(this).data('id');
toastr.info('والد الگو: ' + ($(this).data('name') || ''));
});
$root.on('click', '.ie-btn-bulk-child', function () {
var id = $(this).data('id');
var name = $(this).data('name') || '';
setTemplateParent(id, name);
selectedLineId = id;
$('#ie_builtin_template').val('air_section_children').trigger('change');
$('html, body').animate({ scrollTop: $('#ie_apply_builtin_template').offset().top - 80 }, 300);
});
$('#ie_builtin_template').on('change', function () {
var desc = $(this).find(':selected').data('desc') || '';
$('#ie_template_desc').text(desc);
});
$('#ie_apply_builtin_template').on('click', function () {
var key = $('#ie_builtin_template').val();
if (!key) {
toastr.warning('یک الگوی آماده انتخاب کنید');
return;
}
applyTemplate(key);
});
$('#ie_apply_saved_template').on('click', function () {
var key = $('#ie_saved_template').val();
if (!key) {
toastr.warning('الگوی ذخیرهشدهای انتخاب نشده');
return;
}
applyTemplate(key);
});
$('#ie_delete_saved_template').on('click', deleteSavedTemplate);
$('#ie_save_template_btn').on('click', saveTemplate);
$root.on('click', '.ie-btn-toggle-branch', function (e) {
e.preventDefault();
e.stopPropagation();
toggleBranch($(this).closest('.dd-item'), true);
});
$root.on('click', '.ie-btn-copy-branch', function (e) {
e.stopPropagation();
copyBranch($(this).data('id'), $(this).data('name') || '');
});
$root.on('click', '.ie-btn-paste-branch', function (e) {
e.stopPropagation();
pasteBranch($(this).data('id'), $(this).data('name') || '');
});
$('#ie_expand_all').on('click', function () { setAllBranches(true); });
$('#ie_collapse_all').on('click', function () { setAllBranches(false); });
$('#ie_paste_to_root').on('click', function () { pasteBranch(null, 'ریشه درخت'); });
$('#ie_clear_clipboard').on('click', clearClipboard);
loadClipboard();
initBranchCollapse();
initThemePicker();
}
function branchStorageKey() {
return COLLAPSE_STORAGE_KEY + '_' + (bomId || '0');
}
function getCollapsedIds() {
try {
return JSON.parse(localStorage.getItem(branchStorageKey()) || '[]');
} catch (e) {
return [];
}
}
function saveCollapsedIds(ids) {
localStorage.setItem(branchStorageKey(), JSON.stringify(ids));
}
function initBranchCollapse() {
var collapsed = getCollapsedIds();
$('.dd-item[data-has-children="1"]').each(function () {
var id = String($(this).data('id'));
if (collapsed.indexOf(id) !== -1) {
setBranchCollapsed($(this), true, false);
} else {
setBranchExpanded($(this), false);
}
});
}
function toggleBranch($item, persist) {
if ($item.hasClass('ie-branch-collapsed')) {
setBranchExpanded($item, persist);
} else {
setBranchCollapsed($item, true, persist);
}
}
function setBranchCollapsed($item, animate, persist) {
var $children = $item.children('.ie-branch-children');
var $btn = $item.find('> .ie-dd-handle .ie-btn-toggle-branch i');
$item.addClass('ie-branch-collapsed');
$btn.removeClass('fa-minus').addClass('fa-plus');
if (animate) {
$children.stop(true, true).slideUp(160);
} else {
$children.hide();
}
if (persist) {
var ids = getCollapsedIds();
var id = String($item.data('id'));
if (ids.indexOf(id) === -1) ids.push(id);
saveCollapsedIds(ids);
}
}
function setBranchExpanded($item, persist) {
var $children = $item.children('.ie-branch-children');
var $btn = $item.find('> .ie-dd-handle .ie-btn-toggle-branch i');
$item.removeClass('ie-branch-collapsed');
$btn.removeClass('fa-plus').addClass('fa-minus');
$children.stop(true, true).slideDown(160);
if (persist) {
var ids = getCollapsedIds().filter(function (id) {
return id !== String($item.data('id'));
});
saveCollapsedIds(ids);
}
}
function setAllBranches(expand) {
$('.dd-item[data-has-children="1"]').each(function () {
if (expand) {
setBranchExpanded($(this), false);
} else {
setBranchCollapsed($(this), true, false);
}
});
saveCollapsedIds(expand ? [] : $('.dd-item[data-has-children="1"]').map(function () {
return String($(this).data('id'));
}).get());
}
function loadClipboard() {
try {
var raw = localStorage.getItem(CLIPBOARD_STORAGE_KEY);
if (!raw) return;
var data = JSON.parse(raw);
if (data && data.bomId == bomId && data.lineId) {
clipboardBranchId = data.lineId;
clipboardBranchName = data.name || '';
updateClipboardBar();
}
} catch (e) { /* ignore */ }
}
function saveClipboard() {
if (!clipboardBranchId) {
localStorage.removeItem(CLIPBOARD_STORAGE_KEY);
return;
}
localStorage.setItem(CLIPBOARD_STORAGE_KEY, JSON.stringify({
bomId: bomId,
lineId: clipboardBranchId,
name: clipboardBranchName
}));
}
function updateClipboardBar() {
if (clipboardBranchId) {
$('#ie_clipboard_bar').show();
$('#ie_clipboard_label').text(clipboardBranchName || ('#' + clipboardBranchId));
$('.ie-btn-paste-branch').prop('disabled', false);
} else {
$('#ie_clipboard_bar').hide();
$('.ie-btn-paste-branch').prop('disabled', true);
}
}
function copyBranch(lineId, name) {
clipboardBranchId = lineId;
clipboardBranchName = name || '';
saveClipboard();
updateClipboardBar();
highlightNode(lineId);
if (typeof toastr !== 'undefined') {
toastr.info('شاخه کپی شد: ' + (name || lineId));
}
}
function clearClipboard() {
clipboardBranchId = null;
clipboardBranchName = '';
saveClipboard();
updateClipboardBar();
}
function pasteBranch(targetParentId, targetName) {
if (!clipboardBranchId) {
toastr.warning('ابتدا یک شاخه را کپی کنید');
return;
}
if (String(clipboardBranchId) === String(targetParentId)) {
toastr.warning('نمیتوان شاخه را روی خودش پیست کرد');
return;
}
var msg = 'پیست شاخه «' + (clipboardBranchName || clipboardBranchId) + '» زیر «' + (targetName || 'ریشه درخت') + '»؟';
if (!confirm(msg)) return;
$.ajax({
url: duplicateUrl,
method: 'POST',
data: {
_token: $('meta[name="csrf-token"]').attr('content'),
source_line_id: clipboardBranchId,
target_parent_line_id: targetParentId || null
},
success: function (res) {
if (res.success) {
toastr.success(res.msg);
location.reload();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در پیست شاخه');
}
});
}
function initThemePicker() {
var $wrapper = $('#ie_tree_wrapper');
var $select = $('#ie_tree_theme_select');
if (!$wrapper.length) return;
$('#ie_tree_theme_select option').each(function () {
themeLabels[$(this).val()] = $(this).text();
});
defaultThemeId = String(localStorage.getItem(THEME_DEFAULT_KEY) || '18');
var saved = localStorage.getItem(THEME_STORAGE_KEY) || defaultThemeId;
applyTheme(saved, false);
updateDefaultBadges();
$('.ie-theme-card').on('click', function (e) {
if ($(e.target).closest('.ie-theme-pin').length) return;
applyTheme($(this).data('theme'), true);
$('#ie_tree_theme_picker').collapse('hide');
});
$('.ie-theme-pin').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
setDefaultTheme($(this).data('theme'));
});
$('#ie_apply_default_theme').on('click', function () {
applyTheme(defaultThemeId, true);
});
$select.on('change', function () {
applyTheme($(this).val(), true);
});
}
function setDefaultTheme(themeId) {
themeId = String(themeId || '2');
defaultThemeId = themeId;
localStorage.setItem(THEME_DEFAULT_KEY, themeId);
updateDefaultBadges();
if (typeof toastr !== 'undefined') {
toastr.success('پیشفرض: ' + (themeLabels[themeId] || themeId));
}
}
function updateDefaultBadges() {
$('.ie-theme-card').removeClass('is-default');
$('.ie-theme-pin i').removeClass('fa-star').addClass('fa-star-o');
$('.ie-theme-card[data-theme="' + defaultThemeId + '"]').addClass('is-default');
$('.ie-theme-pin[data-theme="' + defaultThemeId + '"] i').removeClass('fa-star-o').addClass('fa-star');
$('#ie_default_theme_label').text(themeLabels[defaultThemeId] || defaultThemeId);
}
function applyTheme(themeId, persist) {
themeId = String(themeId || defaultThemeId || '18');
var $wrapper = $('#ie_tree_wrapper');
var baseClass = 'ie-tree-indented';
$wrapper.attr('class', baseClass + ' ie-tree-theme-' + themeId);
$('.ie-theme-card').removeClass('active');
$('.ie-theme-card[data-theme="' + themeId + '"]').addClass('active');
$('#ie_tree_theme_select').val(themeId);
$('#ie_current_theme_label').text(themeLabels[themeId] || themeId);
if (persist) {
localStorage.setItem(THEME_STORAGE_KEY, themeId);
if (typeof toastr !== 'undefined') {
toastr.info('دیزاین درخت: ' + (themeLabels[themeId] || themeId));
}
}
}
function setTemplateParent(id, name) {
selectedParentId = id || null;
selectedParentName = name || '';
$('#ie_template_parent_id').val(id || '');
$('#ie_template_parent_label').val(name || 'ریشه درخت (سطح خط تولید)');
highlightNode(id);
}
function highlightNode(lineId) {
$('.ie-dd-handle').removeClass('ie-node-selected');
if (lineId) {
$('.dd-item[data-id="' + lineId + '"] > .ie-dd-handle').addClass('ie-node-selected');
}
}
function applyTemplate(templateKey) {
if (!confirm('اعمال الگو زیر «' + (selectedParentName || 'ریشه درخت') + '»؟')) return;
$.ajax({
url: applyTemplateUrl,
method: 'POST',
data: {
_token: $('meta[name="csrf-token"]').attr('content'),
parent_line_id: selectedParentId,
template_key: templateKey
},
success: function (res) {
if (res.success) {
toastr.success(res.msg);
location.reload();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در اعمال الگو');
}
});
}
function saveTemplate() {
var lineId = selectedLineId || selectedParentId;
var name = $('#ie_save_template_name').val();
if (!lineId) {
toastr.warning('ابتدا یک شاخه را انتخاب کنید (دکمه هدف یا ویرایش)');
return;
}
if (!name) {
toastr.warning('نام الگو را وارد کنید');
return;
}
$.ajax({
url: saveTemplateUrl,
method: 'POST',
data: {
_token: $('meta[name="csrf-token"]').attr('content'),
bom_line_id: lineId,
name: name
},
success: function (res) {
if (res.success) {
toastr.success(res.msg);
location.reload();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در ذخیره الگو');
}
});
}
function deleteSavedTemplate() {
var key = $('#ie_saved_template').val();
if (!key || key.indexOf('saved:') !== 0) return;
var id = key.replace('saved:', '');
if (!confirm('حذف این الگوی ذخیرهشده؟')) return;
$.ajax({
url: deleteTemplateUrl + '/' + id,
method: 'DELETE',
data: { _token: $('meta[name="csrf-token"]').attr('content') },
success: function (res) {
if (res.success) {
toastr.success(res.msg);
location.reload();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || 'خطا در حذف');
}
});
}
function nestableData() {
return $('#ie_bom_nestable').nestable('serialize');
}
function saveTree() {
$.ajax({
url: moveUrl,
method: 'POST',
data: {
_token: $('meta[name="csrf-token"]').attr('content'),
nestable: nestableData()
},
success: function (res) {
if (res.success) {
toastr.success(res.msg);
location.reload();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در ذخیره درخت');
}
});
}
function resetForm(parentId) {
$('#ie_node_form')[0].reset();
$('#ie_parent_line_id').val(parentId || '');
$('#ie_bom_line_id').val('');
$('#ie_item_name').prop('disabled', false);
$('#ie_item_master_id').val('').trigger('change');
$('#ie_panel_title').text(parentId ? 'افزودن زیرمجموعه' : 'افزودن ریشه درخت');
$('#ie_submit_node').html(' افزودن به درخت');
}
function submitNode(e) {
e.preventDefault();
var lineId = $('#ie_bom_line_id').val();
var data = $('#ie_node_form').serializeArray();
data.push({ name: '_token', value: $('meta[name="csrf-token"]').attr('content') });
var url = storeUrl;
var method = 'POST';
if (lineId) {
url = updateBase + '/' + lineId;
method = 'PUT';
}
$.ajax({
url: url,
method: method,
data: $.param(data),
success: function (res) {
if (res.success) {
toastr.success(res.msg);
if (res.integration_messages) {
res.integration_messages.forEach(function (m) {
if (m.type === 'warning' && typeof toastr.warning === 'function') {
toastr.warning(m.text, '', { timeOut: 8000 });
} else if (m.type === 'success' && typeof toastr.info === 'function') {
toastr.info(m.text);
}
});
}
location.reload();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا');
}
});
}
function loadNodeForEdit(lineId) {
var $item = $('.dd-item[data-id="' + lineId + '"]');
if (!$item.length) return;
$('#ie_bom_line_id').val(lineId);
$('#ie_parent_line_id').val('');
$('#ie_panel_title').text('ویرایش گره');
$('#ie_submit_node').html(' ذخیره تغییرات');
$('#ie_item_name').prop('disabled', true);
$('#ie_item_master_id').val($item.data('item-master-id') || '').trigger('change');
$('#ie_item_name').val($item.data('item-name') || '');
$('#ie_item_type').val($item.data('item-type') || 'part');
$('#ie_quantity').val($item.data('quantity') || 1);
$('#ie_position_code').val($item.data('position-code') || '');
$('#ie_find_number').val($item.data('find-number') || '');
$('#ie_variation_id').val($item.data('variation-id') || '');
$('#ie_item_code').val('');
$('#ie_search_product').val('');
setTemplateParent(lineId, $item.data('item-name') || '');
}
function deleteNode(lineId) {
if (!confirm('حذف این گره و تمام زیرمجموعههایش؟')) return;
$.ajax({
url: deleteBase + '/' + lineId,
method: 'DELETE',
data: { _token: $('meta[name="csrf-token"]').attr('content') },
success: function (res) {
if (res.success) {
toastr.success(res.msg);
$('.dd-item[data-id="' + lineId + '"]').remove();
}
},
error: function (xhr) {
toastr.error(xhr.responseJSON?.msg || xhr.responseJSON?.message || 'خطا در حذف');
}
});
}
return { init: init };
})();