ver. 0.271 - ShopAttribute refactor + update package

This commit is contained in:
2026-02-14 21:12:17 +01:00
parent 34e23338da
commit e51ac7f82b
27 changed files with 2367 additions and 726 deletions

View File

@@ -1,138 +1,274 @@
<div class="panel panel-widget draft-widget" value-numer="<?= $this -> i;?>">
<?php
$attribute = is_array($this->attribute ?? null) ? $this->attribute : [];
$values = is_array($this->values ?? null) ? $this->values : [];
$languages = is_array($this->languages ?? null) ? $this->languages : [];
$defaultLanguageId = (string)($this->defaultLanguageId ?? '');
$activeLanguages = [];
foreach ($languages as $language) {
if ((int)($language['status'] ?? 0) === 1) {
$activeLanguages[] = $language;
}
}
if ($defaultLanguageId === '' && !empty($activeLanguages[0]['id'])) {
$defaultLanguageId = (string)$activeLanguages[0]['id'];
}
$attributeName = '';
if ($defaultLanguageId !== '' && isset($attribute['languages'][$defaultLanguageId]['name'])) {
$attributeName = trim((string)$attribute['languages'][$defaultLanguageId]['name']);
}
if ($attributeName === '' && is_array($attribute['languages'] ?? null)) {
foreach ($attribute['languages'] as $languageData) {
$candidateName = trim((string)($languageData['name'] ?? ''));
if ($candidateName !== '') {
$attributeName = $candidateName;
break;
}
}
}
if ($attributeName === '') {
$attributeName = 'ID: ' . (int)($attribute['id'] ?? 0);
}
$rowCounter = 0;
$initialRowsHtml = '';
if (!empty($values)) {
foreach ($values as $value) {
++$rowCounter;
$rowKey = 'existing-' . (int)($value['id'] ?? 0);
$initialRowsHtml .= \Tpl::view('shop-attribute/_partials/value-row', [
'rowKey' => $rowKey,
'value' => $value,
'languages' => $activeLanguages,
'defaultLanguageId' => $defaultLanguageId,
]);
}
} else {
$rowCounter = 1;
$initialRowsHtml .= \Tpl::view('shop-attribute/_partials/value-row', [
'rowKey' => 'new-1',
'value' => ['id' => 0, 'is_default' => 1, 'impact_on_the_price' => null, 'languages' => []],
'languages' => $activeLanguages,
'defaultLanguageId' => $defaultLanguageId,
]);
}
$newRowTemplate = \Tpl::view('shop-attribute/_partials/value-row', [
'rowKey' => '__ROW_KEY__',
'value' => ['id' => 0, 'is_default' => 0, 'impact_on_the_price' => null, 'languages' => []],
'languages' => $activeLanguages,
'defaultLanguageId' => $defaultLanguageId,
]);
?>
<div class="panel panel-widget draft-widget">
<div class="panel-heading with-buttons">
<span class="panel-title">Edycja wartości dla cechy: <?= $this -> attribute['languages']['pl']['name'];?></span>
<span class="panel-title">Wartosci cechy: <?= htmlspecialchars($attributeName, ENT_QUOTES, 'UTF-8'); ?></span>
<div class="buttons">
<a class="btn btn-success btn-save" href="#">
<a class="btn btn-success js-values-save" href="#">
<i class="fa fa-save"></i> zapisz
</a>
<a class="btn btn-dark" href="/admin/shop_attribute/view_list/">
<a class="btn btn-dark" href="/admin/shop_attribute/list/">
<i class="fa fa-ban"></i> wstecz
</a>
</div>
</div>
<div class="panel-body p20">
<button class="btn btn-success mb10 btn-value-add">
<i class="fa fa-plus-circle mr5"></i>Dodaj wartość
</button>
<div class="values-content">
<?
if ( $this -> values ):
foreach ( $this -> values as $value ):
echo \Tpl::view( 'shop-attribute/_partials/value', [
'i' => ++$i,
'value' => $value,
'languages' => $this -> languages,
'attribute' => $this -> attribute
] );
endforeach;
endif;
?>
<div class="mb10">
<button type="button" class="btn btn-success js-value-add">
<i class="fa fa-plus-circle mr5"></i>Dodaj wartosc
</button>
</div>
<div class="alert alert-info">
<strong>Wskazowka:</strong> zaznacz jedna wartosc domyslna i uzupelnij nazwe w jezyku domyslnym.
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped" id="attribute-values-table">
<thead>
<tr>
<th class="text-center" style="width: 90px;">Domyslna</th>
<th style="width: 180px;">Wplyw na cene</th>
<th>Nazwy w jezykach</th>
<th class="text-center" style="width: 100px;">Akcje</th>
</tr>
</thead>
<tbody id="attribute-values-body">
<?= $initialRowsHtml; ?>
</tbody>
</table>
</div>
</div>
</div>
<script type="text/javascript">
$(function ()
{
disable_menu();
$(function() {
disable_menu();
$( 'body' ).on( 'click', '.btn-save', function()
{
var values = jQuery( '.dashboard-page' ).find( 'input, select, textarea' ).serializeObject();
var attributeId = <?= (int)($attribute['id'] ?? 0); ?>;
var defaultLanguageId = <?= json_encode($defaultLanguageId); ?>;
var rowCounter = <?= (int)$rowCounter; ?>;
var newRowTemplate = <?= json_encode($newRowTemplate); ?>;
jQuery.ajax({
type: 'POST',
cache: false,
url: '/admin/shop_attribute/values_save/',
data: {
values: JSON.stringify( values ),
attribute_id: <?= $this -> attribute['id'];?>,
},
beforeSend: function() {
jQuery( '#overlay' ).show();
},
success: function( response ) {
var data = jQuery.parseJSON( response );
jQuery( '#overlay' ).hide();
if ( data.status === 'ok' )
{
var msg = "Zapisano wartości atrybutu";
alert_message( msg );
}
else
{
if ( data.msg )
var msg = data.msg;
else
var msg = "Przepraszamy. Podczas wczytywania danych wystąpił błąd. Prosimy spróbować ponownie.";
create_error( msg );
}
}
});
});
function showError(message) {
if (typeof create_error === 'function') {
create_error(message);
return;
}
alert(message);
}
$( 'body').on( 'click', '.btn-value-add', function ()
{
var maxVal = Math.max.apply(null, $('div[value-number]').map(function() {
var val = parseInt($(this).attr('value-number'));
return isNaN(val) ? 0 : val; // Jeżeli wartość nie jest liczbą, zwróć 0
}).get());
function showSuccess(message) {
if (typeof alert_message === 'function') {
alert_message(message);
return;
}
alert(message);
}
if (!isFinite(maxVal)) {
maxVal = 0;
function addRow() {
rowCounter += 1;
var rowKey = 'new-' + rowCounter;
var rowHtml = newRowTemplate.split('__ROW_KEY__').join(rowKey);
$('#attribute-values-body').append(rowHtml);
if ($('input[name="default_row_key"]:checked').length === 0) {
$('input[name="default_row_key"][value="' + rowKey + '"]').prop('checked', true);
}
}
function collectRows() {
var defaultRowKey = $('input[name="default_row_key"]:checked').val() || '';
var rows = [];
$('#attribute-values-body .attribute-value-row').each(function() {
var $row = $(this);
var rowKey = String($row.data('rowKey') || '');
var valueId = parseInt($row.find('.js-value-id').val(), 10);
if (isNaN(valueId)) {
valueId = 0;
}
$.ajax({
url: '/admin/shop_attribute/attribute_value_tpl/',
type: 'POST',
data: {
i: maxVal + 1,
value: null,
languages: <?= json_encode( $this -> languages );?>,
attribute: <?= json_encode( $this -> attribute );?>
},
success: function( response )
{
$('.values-content').append(response);
var impactOnPrice = $.trim(String($row.find('.js-impact-on-price').val() || ''));
var translations = {};
$row.find('.js-value-name').each(function() {
var $input = $(this);
var langId = String($input.data('langId') || '');
if (langId === '') {
return;
}
translations[langId] = {
name: $.trim(String($input.val() || '')),
value: ''
};
});
rows.push({
id: valueId,
row_key: rowKey,
is_default: rowKey !== '' && rowKey === defaultRowKey,
impact_on_the_price: impactOnPrice,
translations: translations
});
});
$( 'body' ).on( 'click', '.btn-value-remove', function()
{
var button = $( this );
$.alert({
title: 'Potwierdź',
content: 'Na pewno chcesz usunąć wybraną wartość?',
type: 'orange',
closeIcon: true,
closeIconClass: 'fa fa-close',
typeAnimated: true,
animation: 'opacity',
autoClose: 'confirm|10000',
useBootstrap: false,
theme: 'modern',
autoClose: 'cancel|10000',
icon: 'fa fa-exclamation',
buttons:
{
confirm:
{
text: 'TAK usuń',
btnClass: 'btn-orange',
keys: ['enter'],
action: function()
{
button.closest( '.panel' ).remove();
}
},
cancel:
{
text: 'anuluj',
btnClass: 'btn-blue',
action: function() {}
}
return rows;
}
function validateRows(rows) {
if (!Array.isArray(rows) || rows.length === 0) {
return 'Dodaj co najmniej jedna wartosc cechy.';
}
var defaultCount = 0;
var decimalRegex = /^-?[0-9]+([.,][0-9]{1,4})?$/;
for (var i = 0; i < rows.length; i += 1) {
var row = rows[i] || {};
if (row.is_default) {
defaultCount += 1;
}
var translations = row.translations || {};
var defaultLang = translations[defaultLanguageId] || {};
var defaultName = $.trim(String(defaultLang.name || ''));
if (defaultName === '') {
return 'Wiersz nr ' + (i + 1) + ': nazwa w jezyku domyslnym jest wymagana.';
}
var impact = $.trim(String(row.impact_on_the_price || ''));
if (impact !== '' && !decimalRegex.test(impact)) {
return 'Wiersz nr ' + (i + 1) + ': nieprawidlowy format "wplyw na cene".';
}
}
if (defaultCount !== 1) {
return 'Wybierz dokladnie jedna wartosc domyslna.';
}
return '';
}
$('body').on('click', '.js-value-add', function() {
addRow();
});
$('body').on('click', '.js-value-remove', function() {
var $row = $(this).closest('.attribute-value-row');
if ($('#attribute-values-body .attribute-value-row').length <= 1) {
showError('Musi pozostac przynajmniej jeden wiersz wartosci.');
return;
}
$row.remove();
if ($('input[name="default_row_key"]:checked').length === 0) {
$('#attribute-values-body .attribute-value-row:first .js-default-row').prop('checked', true);
}
});
$('body').on('click', '.js-values-save', function(e) {
e.preventDefault();
var rows = collectRows();
var validationError = validateRows(rows);
if (validationError !== '') {
showError(validationError);
return;
}
$.ajax({
type: 'POST',
cache: false,
url: '/admin/shop_attribute/values_save/id=' + attributeId,
dataType: 'json',
data: {
payload: JSON.stringify({ rows: rows })
},
beforeSend: function() {
$('#overlay').show();
},
success: function(response) {
$('#overlay').hide();
if (response && response.status === 'ok') {
showSuccess('Wartosci cechy zostaly zapisane.');
return;
}
});
var message = (response && response.msg) ? response.msg : 'Wystapil blad podczas zapisu danych.';
showError(message);
},
error: function() {
$('#overlay').hide();
showError('Wystapil blad polaczenia podczas zapisu danych.');
}
});
});
});
</script>