update
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
@use "modules/global-search";
|
||||
@use "modules/order-preview-modal";
|
||||
@use "modules/project-mappings";
|
||||
@use "modules/customer-risk-alert";
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@@ -278,6 +279,19 @@ details[open] > .sidebar__group-toggle .sidebar__toggle-arrow {
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar__badge {
|
||||
margin-left: auto;
|
||||
background: #f59e0b;
|
||||
color: #1f2937;
|
||||
font-size: 10.5px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
padding: 2px 6px;
|
||||
border-radius: 10px;
|
||||
min-width: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
||||
97
resources/scss/modules/_customer-risk-alert.scss
Normal file
97
resources/scss/modules/_customer-risk-alert.scss
Normal file
@@ -0,0 +1,97 @@
|
||||
// Customer return shipment alert — Phase 106
|
||||
// Banner w szczegolach zamowienia + badge na liscie zamowien + row highlight
|
||||
|
||||
.customer-risk-banner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 6px;
|
||||
background: #fff0f0;
|
||||
border: 1px solid #fecaca;
|
||||
border-left: 4px solid #d64545;
|
||||
color: #6b1f1f;
|
||||
font-size: 13px;
|
||||
|
||||
&__icon {
|
||||
flex-shrink: 0;
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
color: #d64545;
|
||||
}
|
||||
|
||||
&__body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&__text {
|
||||
margin: 0;
|
||||
font-weight: 600;
|
||||
color: #6b1f1f;
|
||||
}
|
||||
|
||||
&__list {
|
||||
margin-top: 6px;
|
||||
|
||||
summary {
|
||||
cursor: pointer;
|
||||
color: #9b2c2c;
|
||||
font-size: 12px;
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__table {
|
||||
width: 100%;
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
border-collapse: collapse;
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 4px 6px;
|
||||
border-bottom: 1px solid #f5d6d6;
|
||||
text-align: left;
|
||||
color: #3b0f0f;
|
||||
}
|
||||
|
||||
thead th {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.02em;
|
||||
color: #7a2323;
|
||||
background: #ffe3e3;
|
||||
}
|
||||
|
||||
tbody tr:last-child th,
|
||||
tbody tr:last-child td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #b91c1c;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Badge na liscie zamowien (przy buyer name)
|
||||
.risk-return-badge {
|
||||
display: inline-block;
|
||||
padding: 1px 6px;
|
||||
background: #d64545;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
border-radius: 3px;
|
||||
margin-left: 4px;
|
||||
cursor: default;
|
||||
vertical-align: middle;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
// Row highlight w liscie zamowien — subtelny czerwony pasek po lewej
|
||||
.table-list-table tbody tr.is-risk-return > td:first-child {
|
||||
border-left: 3px solid #d64545;
|
||||
}
|
||||
@@ -9,3 +9,15 @@
|
||||
border-radius: 3px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dsm-unmapped {
|
||||
border-left: 4px solid #f59e0b;
|
||||
|
||||
.section-title {
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
table tbody tr {
|
||||
background: rgba(245, 158, 11, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,8 +127,23 @@
|
||||
<a class="sidebar__sublink<?= $currentMenu === 'settings' && $currentSettings === 'printing' ? ' is-active' : '' ?>" href="/settings/printing">
|
||||
Drukowanie
|
||||
</a>
|
||||
<?php
|
||||
$dsmUnmappedCount = 0;
|
||||
try {
|
||||
$appInstance = \App\Core\Application::instance();
|
||||
if ($appInstance !== null) {
|
||||
$dsmRepo = new \App\Modules\Shipments\DeliveryStatusMappingRepository($appInstance->db());
|
||||
$dsmUnmappedCount = $dsmRepo->countAllUnmappedForBadge();
|
||||
}
|
||||
} catch (\Throwable) {
|
||||
$dsmUnmappedCount = 0;
|
||||
}
|
||||
?>
|
||||
<a class="sidebar__sublink<?= $currentMenu === 'settings' && $currentSettings === 'delivery-status-mappings' ? ' is-active' : '' ?>" href="/settings/delivery-status-mappings">
|
||||
Mapowanie statusów dostawy
|
||||
<?php if ($dsmUnmappedCount > 0): ?>
|
||||
<span class="sidebar__badge" title="Niezmapowane statusy"><?= (int) $dsmUnmappedCount ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<a class="sidebar__sublink<?= $currentMenu === 'settings' && $currentSettings === 'project-mappings' ? ' is-active' : '' ?>" href="/settings/project-mappings">
|
||||
<?= $e($t('navigation.project_mapping')) ?>
|
||||
|
||||
@@ -79,6 +79,50 @@ foreach ($addressesList as $address) {
|
||||
<button type="button" class="btn btn--secondary btn--disabled">Edytuj</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php $riskInfo = is_array($customerRiskInfo ?? null) ? $customerRiskInfo : ['count' => 0, 'orders' => [], 'text' => '']; ?>
|
||||
<?php if ((int) ($riskInfo['count'] ?? 0) >= 1): ?>
|
||||
<div class="customer-risk-banner mt-12" role="alert">
|
||||
<span class="customer-risk-banner__icon" aria-hidden="true">⚠</span>
|
||||
<div class="customer-risk-banner__body">
|
||||
<p class="customer-risk-banner__text"><?= $e((string) ($riskInfo['text'] ?? '')) ?></p>
|
||||
<?php $riskOrders = is_array($riskInfo['orders'] ?? null) ? $riskInfo['orders'] : []; ?>
|
||||
<?php if ($riskOrders !== []): ?>
|
||||
<details class="customer-risk-banner__list">
|
||||
<summary>Pokaz liste zamowien ze zwrotem (<?= count($riskOrders) ?>)</summary>
|
||||
<table class="customer-risk-banner__table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nr zamowienia</th>
|
||||
<th>Data</th>
|
||||
<th>Nr przesylki</th>
|
||||
<th>Przewoznik</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($riskOrders as $ro): ?>
|
||||
<?php
|
||||
$roId = (int) ($ro['order_id'] ?? 0);
|
||||
$roNumber = trim((string) ($ro['internal_order_number'] ?? ''));
|
||||
$roLabel = $roNumber !== '' ? $roNumber : ('#' . $roId);
|
||||
$roDate = trim((string) ($ro['ordered_at'] ?? ''));
|
||||
$roDateShort = $roDate !== '' ? substr($roDate, 0, 10) : '-';
|
||||
?>
|
||||
<tr>
|
||||
<td><a href="/orders/<?= $roId ?>" target="_blank" rel="noopener"><?= $e($roLabel) ?></a></td>
|
||||
<td><?= $e($roDateShort) ?></td>
|
||||
<td><?= $e((string) ($ro['tracking_number'] ?? '')) ?: '-' ?></td>
|
||||
<td><?= $e((string) ($ro['provider'] ?? '')) ?: '-' ?></td>
|
||||
<td><?= $e((string) ($ro['delivery_status_raw'] ?? '')) ?: 'returned' ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($flashSuccessMsg !== ''): ?>
|
||||
<div class="flash flash--success mt-12"><?= $e($flashSuccessMsg) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
$providersList = is_array($providers ?? null) ? $providers : [];
|
||||
$mappingsList = is_array($mappings ?? null) ? $mappings : [];
|
||||
$normalizedOptionsList = is_array($normalizedOptions ?? null) ? $normalizedOptions : [];
|
||||
$unmappedList = is_array($unmappedRawStatuses ?? null) ? $unmappedRawStatuses : [];
|
||||
$currentProvider = (string) ($provider ?? 'inpost');
|
||||
?>
|
||||
|
||||
@@ -18,6 +19,66 @@ $currentProvider = (string) ($provider ?? 'inpost');
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
|
||||
<?php if ($unmappedList !== []): ?>
|
||||
<section class="card mt-16 dsm-unmapped">
|
||||
<h2 class="section-title">Niezmapowane statusy wykryte w systemie (<?= count($unmappedList) ?>)</h2>
|
||||
<p class="muted mt-8">Statusy odebrane z API przewoźnika <strong><?= $e((string) ($providersList[$currentProvider] ?? $currentProvider)) ?></strong>, dla których nie ma jeszcze mapowania. Przypisz znormalizowany status, aby paczki przestały być oznaczane jako „Nieznany".</p>
|
||||
|
||||
<form action="/settings/delivery-status-mappings/save-bulk" method="post" class="mt-12">
|
||||
<input type="hidden" name="_token" value="<?= $e($csrfToken ?? '') ?>">
|
||||
<input type="hidden" name="provider" value="<?= $e($currentProvider) ?>">
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table class="table table--compact">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Status surowy</th>
|
||||
<th>Liczba paczek</th>
|
||||
<th>Ostatnio widziany</th>
|
||||
<th>Opis (własny)</th>
|
||||
<th>Status znormalizowany</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($unmappedList as $unmapped): ?>
|
||||
<?php
|
||||
$rawStatus = (string) ($unmapped['raw_status'] ?? '');
|
||||
$count = (int) ($unmapped['count'] ?? 0);
|
||||
$lastSeen = (string) ($unmapped['last_seen'] ?? '');
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<code class="dsm-raw-status"><?= $e($rawStatus) ?></code>
|
||||
<input type="hidden" name="raw_status[]" value="<?= $e($rawStatus) ?>">
|
||||
</td>
|
||||
<td><?= $count ?></td>
|
||||
<td><?= $e($lastSeen) ?></td>
|
||||
<td>
|
||||
<input type="text" name="description[]" class="form-control form-control--sm"
|
||||
value="<?= $e($rawStatus) ?>" maxlength="255">
|
||||
</td>
|
||||
<td>
|
||||
<select name="normalized_status[]" class="form-control form-control--sm" required>
|
||||
<?php foreach ($normalizedOptionsList as $optValue => $optLabel): ?>
|
||||
<option value="<?= $e($optValue) ?>"<?= $optValue === 'unknown' ? ' selected' : '' ?>>
|
||||
<?= $e($optLabel) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="form-actions mt-12">
|
||||
<button type="submit" class="btn btn--primary">Dodaj do mapowania</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="card mt-16">
|
||||
<nav class="content-tabs-nav" aria-label="Wybierz przewoźnika">
|
||||
<?php foreach ($providersList as $provKey => $provLabel): ?>
|
||||
|
||||
Reference in New Issue
Block a user