feat(28-shipment-tracking-ui): badge'e statusow dostawy, linki sledzenia, ustawienia interwalu trackingu
- Kolorowe badge'e statusow dostawy w tabelach paczek (show.php + prepare.php) - Link sledzenia z carrier detection (InPost, Apaczka, Orlen, Allegro, Google fallback) - Sekcja Status dostawy w boksie Platnosc i wysylka - Ustawienie interwalu trackingu crona (5-120 min) w zakladce Ustawienia - Tekstowe mapowania statusow Apaczka API (NEW, CONFIRMED, etc.) - Fix: use-statements ApaczkaShipmentService (pre-existing bug) - Fix: pickup date normalization (next day po 16:00) - Fix: przycisk Pobierz etykiete (POST zamiast link do prepare) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,155 +19,190 @@ $pastTotal = max(0, (int) ($pastPagination['total'] ?? 0));
|
||||
<div class="alert alert--success mt-12" role="status"><?= $e((string) $successMessage) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3 class="section-title mt-16"><?= $e($t('settings.cron.run_on_web_title')) ?></h3>
|
||||
<p class="muted mt-12"><?= $e($t('settings.cron.run_on_web_description')) ?></p>
|
||||
<nav class="content-tabs-nav mt-12" aria-label="Zakładki crona">
|
||||
<button type="button" class="content-tab-btn is-active" data-tab-target="cron-tab-settings">Ustawienia</button>
|
||||
<button type="button" class="content-tab-btn" data-tab-target="cron-tab-schedules"><?= $e($t('settings.cron.schedules_title')) ?></button>
|
||||
</nav>
|
||||
|
||||
<form class="statuses-form mt-12" action="/settings/cron" method="post" novalidate>
|
||||
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
||||
<div class="content-tab-panel is-active" data-tab-panel="cron-tab-settings">
|
||||
<h3 class="section-title mt-16"><?= $e($t('settings.cron.run_on_web_title')) ?></h3>
|
||||
<p class="muted mt-12"><?= $e($t('settings.cron.run_on_web_description')) ?></p>
|
||||
|
||||
<label class="field-inline">
|
||||
<input type="hidden" name="cron_run_on_web" value="0">
|
||||
<input type="checkbox" name="cron_run_on_web" value="1"<?= !empty($runOnWeb) ? ' checked' : '' ?>>
|
||||
<span><?= $e($t('settings.cron.run_on_web_label')) ?></span>
|
||||
</label>
|
||||
<form class="statuses-form mt-12" action="/settings/cron" method="post" novalidate>
|
||||
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
||||
|
||||
<label class="form-field">
|
||||
<span class="field-label"><?= $e($t('settings.cron.web_limit')) ?></span>
|
||||
<input class="form-control" type="number" min="1" max="100" step="1" name="cron_web_limit" value="<?= $e((string) ($webLimit ?? 5)) ?>">
|
||||
</label>
|
||||
<label class="field-inline">
|
||||
<input type="hidden" name="cron_run_on_web" value="0">
|
||||
<input type="checkbox" name="cron_run_on_web" value="1"<?= !empty($runOnWeb) ? ' checked' : '' ?>>
|
||||
<span><?= $e($t('settings.cron.run_on_web_label')) ?></span>
|
||||
</label>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn--primary"><?= $e($t('settings.cron.actions.save')) ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<label class="form-field">
|
||||
<span class="field-label"><?= $e($t('settings.cron.web_limit')) ?></span>
|
||||
<input class="form-control" type="number" min="1" max="100" step="1" name="cron_web_limit" value="<?= $e((string) ($webLimit ?? 5)) ?>">
|
||||
</label>
|
||||
|
||||
<section class="card mt-16">
|
||||
<h3 class="section-title"><?= $e($t('settings.cron.schedules_title')) ?></h3>
|
||||
<div class="table-wrap mt-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= $e($t('settings.cron.fields.job_type')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.enabled')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.interval')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.priority')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.last_run_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.next_run_at')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($schedulesList === []): ?>
|
||||
<tr><td class="muted" colspan="6"><?= $e($t('settings.cron.empty_schedules')) ?></td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($schedulesList as $item): ?>
|
||||
<tr>
|
||||
<td><?= $e((string) ($item['job_type'] ?? '')) ?></td>
|
||||
<td><?= $e(!empty($item['enabled']) ? $t('settings.cron.enabled.yes') : $t('settings.cron.enabled.no')) ?></td>
|
||||
<td><?= $e((string) ($item['interval_seconds'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['priority'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['last_run_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['next_run_at'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<h3 class="section-title mt-16">Śledzenie przesyłek</h3>
|
||||
<label class="form-field">
|
||||
<span class="field-label">Interwał sprawdzania statusu (minuty)</span>
|
||||
<input class="form-control" type="number" min="5" max="120" step="1" name="tracking_interval_minutes" value="<?= $e((string) ($trackingIntervalMinutes ?? 15)) ?>">
|
||||
<small class="muted">Jak często system automatycznie sprawdza status dostawy przesyłek (5–120 min)</small>
|
||||
</label>
|
||||
|
||||
<section class="card mt-16">
|
||||
<h3 class="section-title"><?= $e($t('settings.cron.future_jobs_title')) ?></h3>
|
||||
<div class="table-wrap mt-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th><?= $e($t('settings.cron.fields.job_type')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.status')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.priority')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.scheduled_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.attempts')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.last_error')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($futureJobsList === []): ?>
|
||||
<tr><td class="muted" colspan="7"><?= $e($t('settings.cron.empty_future_jobs')) ?></td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($futureJobsList as $item): ?>
|
||||
<tr>
|
||||
<td><?= $e((string) ($item['id'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['job_type'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['status'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['priority'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['scheduled_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['attempts'] ?? 0) . '/' . (string) ($item['max_attempts'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['last_error'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="card mt-16">
|
||||
<h3 class="section-title"><?= $e($t('settings.cron.past_jobs_title')) ?></h3>
|
||||
<div class="table-wrap mt-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th><?= $e($t('settings.cron.fields.job_type')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.status')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.priority')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.scheduled_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.attempts')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.completed_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.last_error')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($pastJobsList === []): ?>
|
||||
<tr><td class="muted" colspan="8"><?= $e($t('settings.cron.empty_past_jobs')) ?></td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($pastJobsList as $item): ?>
|
||||
<tr>
|
||||
<td><?= $e((string) ($item['id'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['job_type'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['status'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['priority'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['scheduled_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['attempts'] ?? 0) . '/' . (string) ($item['max_attempts'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['completed_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['last_error'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php if ($pastTotalPages > 1): ?>
|
||||
<div class="table-list__footer">
|
||||
<div class="pagination">
|
||||
<a class="pagination__item<?= $pastPage <= 1 ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=1">«</a>
|
||||
<a class="pagination__item<?= $pastPage <= 1 ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=<?= $e((string) max(1, $pastPage - 1)) ?>">‹</a>
|
||||
|
||||
<?php $startPage = max(1, $pastPage - 2); ?>
|
||||
<?php $endPage = min($pastTotalPages, $pastPage + 2); ?>
|
||||
<?php for ($page = $startPage; $page <= $endPage; $page++): ?>
|
||||
<a class="pagination__item<?= $page === $pastPage ? ' is-active' : '' ?>" href="/settings/cron?past_page=<?= $e((string) $page) ?>">
|
||||
<?= $e((string) $page) ?>
|
||||
</a>
|
||||
<?php endfor; ?>
|
||||
|
||||
<a class="pagination__item<?= $pastPage >= $pastTotalPages ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=<?= $e((string) min($pastTotalPages, $pastPage + 1)) ?>">›</a>
|
||||
<a class="pagination__item<?= $pastPage >= $pastTotalPages ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=<?= $e((string) $pastTotalPages) ?>">»</a>
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn--primary"><?= $e($t('settings.cron.actions.save')) ?></button>
|
||||
</div>
|
||||
<div class="muted">
|
||||
<?= $e($t('settings.cron.pagination.summary', ['page' => (string) $pastPage, 'total_pages' => (string) $pastTotalPages, 'total' => (string) $pastTotal])) ?>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="content-tab-panel" data-tab-panel="cron-tab-schedules">
|
||||
<section class="mt-16">
|
||||
<h3 class="section-title"><?= $e($t('settings.cron.schedules_title')) ?></h3>
|
||||
<div class="table-wrap mt-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= $e($t('settings.cron.fields.job_type')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.enabled')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.interval')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.priority')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.last_run_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.next_run_at')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($schedulesList === []): ?>
|
||||
<tr><td class="muted" colspan="6"><?= $e($t('settings.cron.empty_schedules')) ?></td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($schedulesList as $item): ?>
|
||||
<tr>
|
||||
<td><?= $e((string) ($item['job_type'] ?? '')) ?></td>
|
||||
<td><?= $e(!empty($item['enabled']) ? $t('settings.cron.enabled.yes') : $t('settings.cron.enabled.no')) ?></td>
|
||||
<td><?= $e((string) ($item['interval_seconds'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['priority'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['last_run_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['next_run_at'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
<h3 class="section-title"><?= $e($t('settings.cron.future_jobs_title')) ?></h3>
|
||||
<div class="table-wrap mt-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th><?= $e($t('settings.cron.fields.job_type')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.status')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.priority')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.scheduled_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.attempts')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.last_error')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($futureJobsList === []): ?>
|
||||
<tr><td class="muted" colspan="7"><?= $e($t('settings.cron.empty_future_jobs')) ?></td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($futureJobsList as $item): ?>
|
||||
<tr>
|
||||
<td><?= $e((string) ($item['id'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['job_type'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['status'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['priority'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['scheduled_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['attempts'] ?? 0) . '/' . (string) ($item['max_attempts'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['last_error'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
<h3 class="section-title"><?= $e($t('settings.cron.past_jobs_title')) ?></h3>
|
||||
<div class="table-wrap mt-12">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th><?= $e($t('settings.cron.fields.job_type')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.status')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.priority')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.scheduled_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.attempts')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.completed_at')) ?></th>
|
||||
<th><?= $e($t('settings.cron.fields.last_error')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($pastJobsList === []): ?>
|
||||
<tr><td class="muted" colspan="8"><?= $e($t('settings.cron.empty_past_jobs')) ?></td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($pastJobsList as $item): ?>
|
||||
<tr>
|
||||
<td><?= $e((string) ($item['id'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['job_type'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['status'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['priority'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['scheduled_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['attempts'] ?? 0) . '/' . (string) ($item['max_attempts'] ?? 0)) ?></td>
|
||||
<td><?= $e((string) ($item['completed_at'] ?? '')) ?></td>
|
||||
<td><?= $e((string) ($item['last_error'] ?? '')) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php if ($pastTotalPages > 1): ?>
|
||||
<div class="table-list__footer">
|
||||
<div class="pagination">
|
||||
<a class="pagination__item<?= $pastPage <= 1 ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=1">«</a>
|
||||
<a class="pagination__item<?= $pastPage <= 1 ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=<?= $e((string) max(1, $pastPage - 1)) ?>">‹</a>
|
||||
|
||||
<?php $startPage = max(1, $pastPage - 2); ?>
|
||||
<?php $endPage = min($pastTotalPages, $pastPage + 2); ?>
|
||||
<?php for ($page = $startPage; $page <= $endPage; $page++): ?>
|
||||
<a class="pagination__item<?= $page === $pastPage ? ' is-active' : '' ?>" href="/settings/cron?past_page=<?= $e((string) $page) ?>">
|
||||
<?= $e((string) $page) ?>
|
||||
</a>
|
||||
<?php endfor; ?>
|
||||
|
||||
<a class="pagination__item<?= $pastPage >= $pastTotalPages ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=<?= $e((string) min($pastTotalPages, $pastPage + 1)) ?>">›</a>
|
||||
<a class="pagination__item<?= $pastPage >= $pastTotalPages ? ' is-disabled' : '' ?>" href="/settings/cron?past_page=<?= $e((string) $pastTotalPages) ?>">»</a>
|
||||
</div>
|
||||
<div class="muted">
|
||||
<?= $e($t('settings.cron.pagination.summary', ['page' => (string) $pastPage, 'total_pages' => (string) $pastTotalPages, 'total' => (string) $pastTotal])) ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var tabs = document.querySelectorAll('[data-tab-target]');
|
||||
var panels = document.querySelectorAll('[data-tab-panel]');
|
||||
if (tabs.length === 0 || panels.length === 0) return;
|
||||
|
||||
tabs.forEach(function (tab) {
|
||||
tab.addEventListener('click', function () {
|
||||
var target = tab.getAttribute('data-tab-target');
|
||||
tabs.forEach(function (node) { node.classList.remove('is-active'); });
|
||||
panels.forEach(function (panel) { panel.classList.remove('is-active'); });
|
||||
tab.classList.add('is-active');
|
||||
var panel = document.querySelector('[data-tab-panel="' + target + '"]');
|
||||
if (panel) panel.classList.add('is-active');
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user