552 lines
25 KiB
PHP
552 lines
25 KiB
PHP
<link href="https://cdn.quilljs.com/1.3.7/quill.snow.css" rel="stylesheet">
|
|
<style>
|
|
.wysiwyg-wrap { position: relative; z-index: 1; }
|
|
.wysiwyg-wrap .ql-toolbar { border-radius: 4px 4px 0 0; border-color: var(--c-border, #d1d5db); background: #f8fafc; }
|
|
.wysiwyg-wrap .ql-container { height: auto; border-radius: 0 0 4px 4px; border-color: var(--c-border, #d1d5db); font-size: 14px; font-family: inherit; }
|
|
.wysiwyg-wrap .ql-editor { min-height: var(--editor-min-height, 80px); }
|
|
</style>
|
|
|
|
<section class="card">
|
|
<h1><?= $e($t('products.edit.title', ['id' => (string) ($productId ?? 0)])) ?></h1>
|
|
<p class="muted"><?= $e($t('products.edit.description')) ?></p>
|
|
</section>
|
|
|
|
<section class="card mt-16">
|
|
<?php if (!empty($errors)): ?>
|
|
<div class="alert alert--danger" role="alert">
|
|
<?php foreach ((array) $errors as $error): ?>
|
|
<div><?= $e((string) $error) ?></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php $images = is_array($productImages ?? null) ? $productImages : []; ?>
|
|
<form class="product-form mt-16" method="post" action="/products/update" enctype="multipart/form-data">
|
|
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
|
<input type="hidden" name="id" value="<?= $e((string) ($productId ?? 0)) ?>">
|
|
|
|
<div class="form-grid">
|
|
<label class="form-field">
|
|
<span class="field-label">SKU</span>
|
|
<input class="form-control" type="text" name="sku" value="<?= $e((string) ($form['sku'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label">EAN</span>
|
|
<input class="form-control" type="text" name="ean" value="<?= $e((string) ($form['ean'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.type')) ?></span>
|
|
<select class="form-control" name="type">
|
|
<option value="simple"<?= (string) ($form['type'] ?? '') === 'simple' ? ' selected' : '' ?>><?= $e($t('products.type.simple')) ?></option>
|
|
<option value="variant_parent"<?= (string) ($form['type'] ?? '') === 'variant_parent' ? ' selected' : '' ?>><?= $e($t('products.type.variant_parent')) ?></option>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.status')) ?></span>
|
|
<select class="form-control" name="status">
|
|
<option value="1"<?= (string) ($form['status'] ?? '1') === '1' ? ' selected' : '' ?>><?= $e($t('products.status.active')) ?></option>
|
|
<option value="0"<?= (string) ($form['status'] ?? '1') === '0' ? ' selected' : '' ?>><?= $e($t('products.status.inactive')) ?></option>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.promoted')) ?></span>
|
|
<select class="form-control" name="promoted">
|
|
<option value="0"<?= (string) ($form['promoted'] ?? '0') === '0' ? ' selected' : '' ?>><?= $e($t('products.promoted.no')) ?></option>
|
|
<option value="1"<?= (string) ($form['promoted'] ?? '0') === '1' ? ' selected' : '' ?>><?= $e($t('products.promoted.yes')) ?></option>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.vat')) ?></span>
|
|
<input class="form-control" type="number" step="0.01" min="0" max="100" name="vat" value="<?= $e((string) ($form['vat'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.quantity')) ?></span>
|
|
<input class="form-control" type="number" step="0.001" min="0" name="quantity" value="<?= $e((string) ($form['quantity'] ?? '0')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.weight')) ?></span>
|
|
<input class="form-control" type="number" step="0.001" min="0" name="weight" value="<?= $e((string) ($form['weight'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.price_input_mode')) ?></span>
|
|
<select class="form-control" name="price_input_mode">
|
|
<option value="brutto"<?= (string) ($form['price_input_mode'] ?? 'brutto') === 'brutto' ? ' selected' : '' ?>><?= $e($t('products.price_mode.brutto')) ?></option>
|
|
<option value="netto"<?= (string) ($form['price_input_mode'] ?? 'brutto') === 'netto' ? ' selected' : '' ?>><?= $e($t('products.price_mode.netto')) ?></option>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.price_brutto')) ?></span>
|
|
<input class="form-control" type="number" step="0.01" min="0" name="price_brutto" value="<?= $e((string) ($form['price_brutto'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.price_netto')) ?></span>
|
|
<input class="form-control" type="number" step="0.01" min="0" name="price_netto" value="<?= $e((string) ($form['price_netto'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.price_brutto_promo')) ?></span>
|
|
<input class="form-control" type="number" step="0.01" min="0" name="price_brutto_promo" value="<?= $e((string) ($form['price_brutto_promo'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.price_netto_promo')) ?></span>
|
|
<input class="form-control" type="number" step="0.01" min="0" name="price_netto_promo" value="<?= $e((string) ($form['price_netto_promo'] ?? '')) ?>">
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-grid mt-16">
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.meta_title')) ?></span>
|
|
<input class="form-control" type="text" name="meta_title" value="<?= $e((string) ($form['meta_title'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.meta_description')) ?></span>
|
|
<input class="form-control" type="text" name="meta_description" value="<?= $e((string) ($form['meta_description'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.meta_keywords')) ?></span>
|
|
<input class="form-control" type="text" name="meta_keywords" value="<?= $e((string) ($form['meta_keywords'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.seo_link')) ?></span>
|
|
<input class="form-control" type="text" name="seo_link" value="<?= $e((string) ($form['seo_link'] ?? '')) ?>">
|
|
</label>
|
|
</div>
|
|
|
|
<?php
|
|
$activeIntegrations = is_array($activeIntegrations ?? null) ? $activeIntegrations : [];
|
|
$integrationTranslationsMap = is_array($integrationTranslationsMap ?? null) ? $integrationTranslationsMap : [];
|
|
?>
|
|
|
|
<div class="content-tabs-card mt-16">
|
|
<div class="content-tabs-nav" id="content-tabs-nav">
|
|
<button type="button" class="content-tab-btn is-active" data-tab="global">
|
|
<?= $e($t('products.content_tabs.global')) ?>
|
|
</button>
|
|
<?php foreach ($activeIntegrations as $integration): ?>
|
|
<?php $intId = (int) ($integration['id'] ?? 0); ?>
|
|
<?php if ($intId <= 0) continue; ?>
|
|
<button type="button" class="content-tab-btn" data-tab="integration-<?= $e((string) $intId) ?>">
|
|
<?= $e((string) ($integration['name'] ?? '#' . $intId)) ?>
|
|
</button>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<!-- GLOBAL TAB -->
|
|
<div class="content-tab-panel is-active" id="content-tab-global">
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.name')) ?> *</span>
|
|
<input class="form-control" type="text" name="name" required value="<?= $e((string) ($form['name'] ?? '')) ?>">
|
|
</label>
|
|
|
|
<div class="form-field mt-12">
|
|
<span class="field-label"><?= $e($t('products.fields.short_description')) ?></span>
|
|
<div class="wysiwyg-wrap">
|
|
<div id="editor-short-description"></div>
|
|
</div>
|
|
<textarea name="short_description" id="input-short-description" style="display:none"><?= $e((string) ($form['short_description'] ?? '')) ?></textarea>
|
|
</div>
|
|
|
|
<div class="form-field mt-12">
|
|
<span class="field-label"><?= $e($t('products.fields.description')) ?></span>
|
|
<div class="wysiwyg-wrap" style="--editor-min-height:180px">
|
|
<div id="editor-description"></div>
|
|
</div>
|
|
<textarea name="description" id="input-description" style="display:none"><?= $e((string) ($form['description'] ?? '')) ?></textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- PER-INTEGRATION TABS -->
|
|
<?php foreach ($activeIntegrations as $integration): ?>
|
|
<?php
|
|
$intId = (int) ($integration['id'] ?? 0);
|
|
if ($intId <= 0) continue;
|
|
$intData = $integrationTranslationsMap[$intId] ?? [];
|
|
$intName = isset($intData['name']) ? (string) $intData['name'] : '';
|
|
$intShort = isset($intData['short_description']) ? (string) $intData['short_description'] : '';
|
|
$intDesc = isset($intData['description']) ? (string) $intData['description'] : '';
|
|
?>
|
|
<div class="content-tab-panel" id="content-tab-integration-<?= $e((string) $intId) ?>">
|
|
<p class="muted" style="margin-bottom:8px">
|
|
Puste pole = używana wartość globalna.
|
|
</p>
|
|
|
|
<label class="form-field">
|
|
<span class="field-label"><?= $e($t('products.fields.name')) ?></span>
|
|
<input class="form-control" type="text"
|
|
name="integration_content[<?= $e((string) $intId) ?>][name]"
|
|
value="<?= $e($intName) ?>">
|
|
</label>
|
|
|
|
<div class="form-field mt-12">
|
|
<span class="field-label"><?= $e($t('products.fields.short_description')) ?></span>
|
|
<div class="wysiwyg-wrap">
|
|
<div id="editor-int-short-<?= $e((string) $intId) ?>"></div>
|
|
</div>
|
|
<textarea name="integration_content[<?= $e((string) $intId) ?>][short_description]"
|
|
id="input-int-short-<?= $e((string) $intId) ?>"
|
|
style="display:none"><?= $e($intShort) ?></textarea>
|
|
</div>
|
|
|
|
<div class="form-field mt-12">
|
|
<span class="field-label"><?= $e($t('products.fields.description')) ?></span>
|
|
<div class="wysiwyg-wrap" style="--editor-min-height:180px">
|
|
<div id="editor-int-desc-<?= $e((string) $intId) ?>"></div>
|
|
</div>
|
|
<textarea name="integration_content[<?= $e((string) $intId) ?>][description]"
|
|
id="input-int-desc-<?= $e((string) $intId) ?>"
|
|
style="display:none"><?= $e($intDesc) ?></textarea>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<section class="card mt-16">
|
|
<h3><?= $e($t('products.images.title')) ?></h3>
|
|
<p class="muted"><?= $e($t('products.images.description')) ?></p>
|
|
<input type="hidden" id="product-image-csrf" value="<?= $e($csrfToken ?? '') ?>">
|
|
|
|
<div class="product-images-grid mt-12" id="product-images-grid" data-product-id="<?= $e((string) ($productId ?? 0)) ?>">
|
|
<?php foreach ($images as $image): ?>
|
|
<?php
|
|
$imageId = (int) ($image['id'] ?? 0);
|
|
$isMain = (int) ($image['is_main'] ?? 0) === 1;
|
|
$publicUrl = (string) ($image['public_url'] ?? '');
|
|
?>
|
|
<article
|
|
class="product-image-card<?= $isMain ? ' is-main' : '' ?>"
|
|
data-image-id="<?= $e((string) $imageId) ?>"
|
|
data-storage-path="<?= $e((string) ($image['storage_path'] ?? '')) ?>"
|
|
>
|
|
<div class="product-image-card__thumb-wrap">
|
|
<?php if ($publicUrl !== ''): ?>
|
|
<img class="product-image-card__thumb" src="<?= $e($publicUrl) ?>" alt="<?= $e((string) ($image['alt'] ?? '')) ?>">
|
|
<?php else: ?>
|
|
<div class="product-image-card__thumb is-empty">NO IMAGE</div>
|
|
<?php endif; ?>
|
|
<span class="product-image-card__badge"><?= $e($t('products.images.main')) ?></span>
|
|
</div>
|
|
<div class="product-image-card__meta"><?= $e((string) ($image['storage_path'] ?? '')) ?></div>
|
|
<div class="product-image-card__actions">
|
|
<button type="button" class="btn btn--secondary btn-set-main"<?= $isMain ? ' disabled' : '' ?>>
|
|
<?= $e($t('products.images.set_main')) ?>
|
|
</button>
|
|
<button type="button" class="btn btn--danger btn-delete-image">
|
|
<?= $e($t('products.images.remove')) ?>
|
|
</button>
|
|
</div>
|
|
</article>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<p class="muted mt-12" id="product-images-empty"<?= $images === [] ? '' : ' style="display:none;"' ?>>
|
|
<?= $e($t('products.images.empty')) ?>
|
|
</p>
|
|
|
|
<label class="form-field mt-16">
|
|
<span class="field-label"><?= $e($t('products.images.add_new')) ?></span>
|
|
<input class="form-control" type="file" id="product-image-upload" name="new_images[]" accept=".jpg,.jpeg,.png,.webp,.gif,image/*" multiple>
|
|
</label>
|
|
<p class="muted" id="product-image-upload-status"></p>
|
|
<p class="muted"><?= $e($t('products.images.main_hint')) ?></p>
|
|
</section>
|
|
|
|
<div class="form-actions mt-16">
|
|
<button class="btn btn--primary" type="submit"><?= $e($t('products.actions.save')) ?></button>
|
|
<a class="btn btn--secondary" href="/products"><?= $e($t('products.actions.back')) ?></a>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
|
|
<script>
|
|
(function() {
|
|
var grid = document.getElementById('product-images-grid');
|
|
var emptyState = document.getElementById('product-images-empty');
|
|
var uploadInput = document.getElementById('product-image-upload');
|
|
var uploadStatus = document.getElementById('product-image-upload-status');
|
|
var tokenInput = document.getElementById('product-image-csrf');
|
|
if (!grid || !uploadInput || !tokenInput) return;
|
|
|
|
var productId = grid.getAttribute('data-product-id');
|
|
var csrfToken = tokenInput.value || '';
|
|
var txtSetMain = <?= json_encode((string) $t('products.images.set_main'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtRemove = <?= json_encode((string) $t('products.images.remove'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtMain = <?= json_encode((string) $t('products.images.main'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtUploadPending = <?= json_encode((string) $t('products.images.uploading'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtUploadOk = <?= json_encode((string) $t('products.images.uploaded_ok'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtDeleteConfirm = <?= json_encode((string) $t('products.images.confirm_delete'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtConfirmTitle = <?= json_encode((string) $t('products.images.confirm_title'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtConfirmYes = <?= json_encode((string) $t('products.images.confirm_yes'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
var txtConfirmNo = <?= json_encode((string) $t('products.images.confirm_no'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
|
|
|
|
function refreshMainState(mainId) {
|
|
var cards = grid.querySelectorAll('.product-image-card');
|
|
cards.forEach(function(card) {
|
|
var cardId = Number(card.getAttribute('data-image-id') || 0);
|
|
var isMain = cardId === mainId;
|
|
card.classList.toggle('is-main', isMain);
|
|
var setMainBtn = card.querySelector('.btn-set-main');
|
|
if (setMainBtn) setMainBtn.disabled = isMain;
|
|
});
|
|
}
|
|
|
|
function updateEmptyState() {
|
|
if (!emptyState) return;
|
|
emptyState.style.display = grid.querySelector('.product-image-card') ? 'none' : '';
|
|
}
|
|
|
|
function buildCard(image) {
|
|
var article = document.createElement('article');
|
|
article.className = 'product-image-card' + (Number(image.is_main) === 1 ? ' is-main' : '');
|
|
article.setAttribute('data-image-id', String(image.id));
|
|
article.setAttribute('data-storage-path', String(image.storage_path || ''));
|
|
|
|
var thumbWrap = document.createElement('div');
|
|
thumbWrap.className = 'product-image-card__thumb-wrap';
|
|
|
|
if (image.public_url) {
|
|
var img = document.createElement('img');
|
|
img.className = 'product-image-card__thumb';
|
|
img.src = image.public_url;
|
|
img.alt = image.alt || '';
|
|
thumbWrap.appendChild(img);
|
|
} else {
|
|
var noimg = document.createElement('div');
|
|
noimg.className = 'product-image-card__thumb is-empty';
|
|
noimg.textContent = 'NO IMAGE';
|
|
thumbWrap.appendChild(noimg);
|
|
}
|
|
|
|
var badge = document.createElement('span');
|
|
badge.className = 'product-image-card__badge';
|
|
badge.textContent = txtMain;
|
|
thumbWrap.appendChild(badge);
|
|
|
|
var meta = document.createElement('div');
|
|
meta.className = 'product-image-card__meta';
|
|
meta.textContent = image.storage_path || '';
|
|
|
|
var actions = document.createElement('div');
|
|
actions.className = 'product-image-card__actions';
|
|
|
|
var setMainBtn = document.createElement('button');
|
|
setMainBtn.type = 'button';
|
|
setMainBtn.className = 'btn btn--secondary btn-set-main';
|
|
setMainBtn.textContent = txtSetMain;
|
|
if (Number(image.is_main) === 1) setMainBtn.disabled = true;
|
|
|
|
var removeBtn = document.createElement('button');
|
|
removeBtn.type = 'button';
|
|
removeBtn.className = 'btn btn--danger btn-delete-image';
|
|
removeBtn.textContent = txtRemove;
|
|
|
|
actions.appendChild(setMainBtn);
|
|
actions.appendChild(removeBtn);
|
|
article.appendChild(thumbWrap);
|
|
article.appendChild(meta);
|
|
article.appendChild(actions);
|
|
|
|
return article;
|
|
}
|
|
|
|
async function postForm(url, data) {
|
|
var response = await fetch(url, { method: 'POST', body: data, credentials: 'same-origin' });
|
|
var payload = await response.json();
|
|
if (!response.ok || payload.ok !== true) {
|
|
throw new Error(payload.message || 'Blad operacji.');
|
|
}
|
|
return payload;
|
|
}
|
|
|
|
uploadInput.addEventListener('change', async function() {
|
|
if (!uploadInput.files || uploadInput.files.length === 0) return;
|
|
var formData = new FormData();
|
|
formData.append('_token', csrfToken);
|
|
formData.append('id', String(productId));
|
|
Array.prototype.forEach.call(uploadInput.files, function(file) {
|
|
formData.append('new_images[]', file);
|
|
});
|
|
|
|
uploadStatus.textContent = txtUploadPending;
|
|
uploadInput.disabled = true;
|
|
try {
|
|
var result = await postForm('/products/images/upload', formData);
|
|
(result.images || []).forEach(function(image) {
|
|
grid.appendChild(buildCard(image));
|
|
if (Number(image.is_main) === 1) refreshMainState(Number(image.id));
|
|
});
|
|
uploadStatus.textContent = txtUploadOk;
|
|
if (result.message) uploadStatus.textContent += ' ' + result.message;
|
|
updateEmptyState();
|
|
} catch (error) {
|
|
uploadStatus.textContent = error.message || 'Blad uploadu.';
|
|
} finally {
|
|
uploadInput.value = '';
|
|
uploadInput.disabled = false;
|
|
}
|
|
});
|
|
|
|
grid.addEventListener('click', async function(event) {
|
|
var target = event.target;
|
|
if (!target || !(target instanceof HTMLElement)) return;
|
|
var card = target.closest('.product-image-card');
|
|
if (!card) return;
|
|
var imageId = Number(card.getAttribute('data-image-id') || 0);
|
|
if (imageId <= 0) return;
|
|
|
|
if (target.classList.contains('btn-set-main')) {
|
|
if (target.disabled) return;
|
|
var dataMain = new FormData();
|
|
dataMain.append('_token', csrfToken);
|
|
dataMain.append('id', String(productId));
|
|
dataMain.append('image_id', String(imageId));
|
|
|
|
target.disabled = true;
|
|
try {
|
|
await postForm('/products/images/set-main', dataMain);
|
|
refreshMainState(imageId);
|
|
} catch (error) {
|
|
target.disabled = false;
|
|
if (window.OrderProAlerts && typeof window.OrderProAlerts.alert === 'function') {
|
|
window.OrderProAlerts.alert({ title: 'Blad', message: error.message || 'Blad operacji.', danger: true });
|
|
} else if (uploadStatus) {
|
|
uploadStatus.textContent = error.message || 'Blad operacji.';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (target.classList.contains('btn-delete-image')) {
|
|
var confirmDelete = async function() {
|
|
var dataDelete = new FormData();
|
|
dataDelete.append('_token', csrfToken);
|
|
dataDelete.append('id', String(productId));
|
|
dataDelete.append('image_id', String(imageId));
|
|
var result = await postForm('/products/images/delete', dataDelete);
|
|
card.remove();
|
|
if (Number(result.main_image_id || 0) > 0) {
|
|
refreshMainState(Number(result.main_image_id));
|
|
}
|
|
updateEmptyState();
|
|
};
|
|
|
|
if (window.OrderProAlerts && typeof window.OrderProAlerts.confirm === 'function') {
|
|
var accepted = await window.OrderProAlerts.confirm({
|
|
title: txtConfirmTitle,
|
|
message: txtDeleteConfirm,
|
|
confirmLabel: txtConfirmYes,
|
|
cancelLabel: txtConfirmNo,
|
|
danger: true
|
|
});
|
|
if (!accepted) return;
|
|
try { await confirmDelete(); } catch (error) {
|
|
window.OrderProAlerts.alert({ title: 'Blad', message: error.message || 'Blad operacji.', danger: true });
|
|
}
|
|
} else {
|
|
try { await confirmDelete(); } catch (error) {
|
|
if (uploadStatus) uploadStatus.textContent = error.message || 'Blad operacji.';
|
|
}
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
|
|
<script src="https://cdn.quilljs.com/1.3.7/quill.min.js"></script>
|
|
<script>
|
|
(function() {
|
|
var toolbarShort = [
|
|
['bold', 'italic', 'underline'],
|
|
[{ list: 'bullet' }],
|
|
['link', 'clean']
|
|
];
|
|
var toolbarFull = [
|
|
[{ header: [1, 2, 3, false] }],
|
|
['bold', 'italic', 'underline', 'strike'],
|
|
[{ list: 'ordered' }, { list: 'bullet' }],
|
|
['link', 'clean']
|
|
];
|
|
|
|
var shortInput = document.getElementById('input-short-description');
|
|
var descInput = document.getElementById('input-description');
|
|
|
|
var quillShort = new Quill('#editor-short-description', { theme: 'snow', modules: { toolbar: toolbarShort } });
|
|
var quillDesc = new Quill('#editor-description', { theme: 'snow', modules: { toolbar: toolbarFull } });
|
|
|
|
if (shortInput && shortInput.value) quillShort.clipboard.dangerouslyPasteHTML(shortInput.value);
|
|
if (descInput && descInput.value) quillDesc.clipboard.dangerouslyPasteHTML(descInput.value);
|
|
|
|
// --- per-integration editors ---
|
|
var intEditors = []; // array of {shortQuill, descQuill, shortInput, descInput}
|
|
|
|
document.querySelectorAll('[id^="editor-int-short-"]').forEach(function(el) {
|
|
var suffix = el.id.replace('editor-int-short-', '');
|
|
var shortEl = el;
|
|
var descEl = document.getElementById('editor-int-desc-' + suffix);
|
|
var shortInp = document.getElementById('input-int-short-' + suffix);
|
|
var descInp = document.getElementById('input-int-desc-' + suffix);
|
|
|
|
if (!shortEl || !descEl || !shortInp || !descInp) return;
|
|
|
|
var qShort = new Quill(shortEl, { theme: 'snow', modules: { toolbar: toolbarShort } });
|
|
var qDesc = new Quill(descEl, { theme: 'snow', modules: { toolbar: toolbarFull } });
|
|
|
|
if (shortInp.value) qShort.clipboard.dangerouslyPasteHTML(shortInp.value);
|
|
if (descInp.value) qDesc.clipboard.dangerouslyPasteHTML(descInp.value);
|
|
|
|
intEditors.push({ shortQuill: qShort, descQuill: qDesc, shortInput: shortInp, descInput: descInp });
|
|
});
|
|
|
|
var form = document.querySelector('.product-form');
|
|
if (form) {
|
|
form.addEventListener('submit', function() {
|
|
if (shortInput) shortInput.value = quillShort.root.innerHTML;
|
|
if (descInput) descInput.value = quillDesc.root.innerHTML;
|
|
intEditors.forEach(function(e) {
|
|
e.shortInput.value = e.shortQuill.root.innerHTML;
|
|
e.descInput.value = e.descQuill.root.innerHTML;
|
|
});
|
|
});
|
|
}
|
|
})();
|
|
</script>
|
|
|
|
<script>
|
|
(function() {
|
|
var nav = document.getElementById('content-tabs-nav');
|
|
if (!nav) return;
|
|
|
|
nav.addEventListener('click', function(e) {
|
|
var btn = e.target.closest('.content-tab-btn');
|
|
if (!btn) return;
|
|
|
|
var tabId = btn.getAttribute('data-tab');
|
|
if (!tabId) return;
|
|
|
|
// deactivate all
|
|
nav.querySelectorAll('.content-tab-btn').forEach(function(b) {
|
|
b.classList.remove('is-active');
|
|
});
|
|
document.querySelectorAll('.content-tab-panel').forEach(function(p) {
|
|
p.classList.remove('is-active');
|
|
});
|
|
|
|
// activate selected
|
|
btn.classList.add('is-active');
|
|
var panel = document.getElementById('content-tab-' + tabId);
|
|
if (panel) panel.classList.add('is-active');
|
|
});
|
|
})();
|
|
</script>
|