Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4637cb867b | ||
|
|
3873849de1 | ||
|
|
f22ca71558 |
@@ -38,7 +38,7 @@
|
|||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
<key>UIRequiredDeviceCapabilities</key>
|
<key>UIRequiredDeviceCapabilities</key>
|
||||||
<array>
|
<array>
|
||||||
<string>armv7</string>
|
<string>arm64</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
|
|||||||
@@ -328,6 +328,47 @@ const getCustomerDetailItems = (scan) => {
|
|||||||
return items;
|
return items;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getLastWashDetailItem = (scan) => {
|
||||||
|
// TRU-78 / DRIFT 17: surface the "last washed" timestamp for a scanned
|
||||||
|
// license plate on the landing page so the operator can see at a glance
|
||||||
|
// when a trailer was last washed (DHL pick-up use case).
|
||||||
|
const lastWash = formatLastWashTimestamp(scan?.last_wash);
|
||||||
|
if (!lastWash) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: SessionUser.objects.global.language.last_wash || t('admin.pos.recent_washes'),
|
||||||
|
value: lastWash,
|
||||||
|
testKey: 'last-wash',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLastWashEmptyStateText = () => {
|
||||||
|
return t('admin.pos.never_washed');
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatLastWashTimestamp = (value) => {
|
||||||
|
if (!isMeaningfulValue(value)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedDate = new Date(String(value).replace(' ', 'T'));
|
||||||
|
if (Number.isNaN(parsedDate.getTime())) {
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new Intl.DateTimeFormat(locale.value || undefined, {
|
||||||
|
dateStyle: 'medium',
|
||||||
|
timeStyle: 'short',
|
||||||
|
}).format(parsedDate);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Unable to format last_wash timestamp', error);
|
||||||
|
return String(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const getVehicleDetailItems = (scan) => {
|
const getVehicleDetailItems = (scan) => {
|
||||||
const detailState = getPlateDetailState(scan.plate);
|
const detailState = getPlateDetailState(scan.plate);
|
||||||
if (detailState.status !== 'loaded') {
|
if (detailState.status !== 'loaded') {
|
||||||
@@ -493,19 +534,29 @@ setTimeout(() => {
|
|||||||
:data-testid="`pos-recent-scan-details-${scan.id}`"
|
:data-testid="`pos-recent-scan-details-${scan.id}`"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-if="getCustomerDetailItems(scan).length > 0"
|
v-if="getCustomerDetailItems(scan).length > 0 || getLastWashDetailItem(scan)"
|
||||||
class="pos-scan-details__grid pos-scan-details__grid--customer"
|
class="pos-scan-details__grid pos-scan-details__grid--customer"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="item in getCustomerDetailItems(scan)"
|
v-for="item in [...getCustomerDetailItems(scan), getLastWashDetailItem(scan)].filter(Boolean)"
|
||||||
:key="item.label"
|
:key="item.label"
|
||||||
class="pos-scan-detail-field"
|
class="pos-scan-detail-field"
|
||||||
|
:data-testid="`pos-recent-scan-detail-${scan.id}-${item.testKey || item.label}`"
|
||||||
>
|
>
|
||||||
<span class="pos-scan-detail-field__label">{{ item.label }}</span>
|
<span class="pos-scan-detail-field__label">{{ item.label }}</span>
|
||||||
<span class="pos-scan-detail-field__value">{{ item.value }}</span>
|
<span class="pos-scan-detail-field__value">{{ item.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p
|
||||||
|
v-if="!getLastWashDetailItem(scan) && scan.last_wash == null"
|
||||||
|
class="pos-scan-details__state"
|
||||||
|
:data-testid="`pos-recent-scan-never-washed-${scan.id}`"
|
||||||
|
>
|
||||||
|
<i class="fas fa-info-circle" aria-hidden="true"></i>
|
||||||
|
<span>{{ getLastWashEmptyStateText() }}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
<div v-if="getPlateDetailState(scan.plate).status === 'loading'" class="pos-scan-details__state">
|
<div v-if="getPlateDetailState(scan.plate).status === 'loading'" class="pos-scan-details__state">
|
||||||
<i class="fas fa-spinner fa-spin"></i>
|
<i class="fas fa-spinner fa-spin"></i>
|
||||||
<span>{{ $t('admin.pos.recent_scan_details_loading') }}</span>
|
<span>{{ $t('admin.pos.recent_scan_details_loading') }}</span>
|
||||||
|
|||||||
@@ -5448,6 +5448,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.samme'} @:{'words.generated.ydelse'}, @:{'words.generated.tilvalg'} @:{'words.generated.og'} @:{'words.generated.ekstra'} @:{'words.generated.varer'} @:{'words.generated.som'} @:{'words.generated.sidste'} @:{'words.generated.vask'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.samme'} @:{'words.generated.ydelse'}, @:{'words.generated.tilvalg'} @:{'words.generated.og'} @:{'words.generated.ekstra'} @:{'words.generated.varer'} @:{'words.generated.som'} @:{'words.generated.sidste'} @:{'words.generated.vask'}",
|
||||||
"manual_entry": "Manuell @:{'words.generated.registrering'}",
|
"manual_entry": "Manuell @:{'words.generated.registrering'}",
|
||||||
|
"never_washed": "Aldrig vasket",
|
||||||
"new_order": "@.capitalize:{'words.generated.ny'} order",
|
"new_order": "@.capitalize:{'words.generated.ny'} order",
|
||||||
"new_sale": "@.capitalize:{'words.generated.nyt'} @:{'words.generated.salg'}",
|
"new_sale": "@.capitalize:{'words.generated.nyt'} @:{'words.generated.salg'}",
|
||||||
"no_bookings": "@.capitalize:{'words.generated.ingen'} @:{'words.generated.bookinger'} @:{'words.generated.fundet'}",
|
"no_bookings": "@.capitalize:{'words.generated.ingen'} @:{'words.generated.bookinger'} @:{'words.generated.fundet'}",
|
||||||
|
|||||||
@@ -5558,6 +5558,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.gleiche'} @:{'words.generated.leistung'}, @:{'words.generated.zusatzoptionen'} @:{'words.generated.und'} @:{'words.generated.zusatzartikel'} @:{'words.generated.wie'} @:{'words.generated.bei'} @:{'words.generated.der'} @:{'words.generated.letzten'} @:{'words.generated.wasche'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.gleiche'} @:{'words.generated.leistung'}, @:{'words.generated.zusatzoptionen'} @:{'words.generated.und'} @:{'words.generated.zusatzartikel'} @:{'words.generated.wie'} @:{'words.generated.bei'} @:{'words.generated.der'} @:{'words.generated.letzten'} @:{'words.generated.wasche'}",
|
||||||
"manual_entry": "@.capitalize:{'words.generated.manuell'} registrering",
|
"manual_entry": "@.capitalize:{'words.generated.manuell'} registrering",
|
||||||
|
"never_washed": "Noch nie gewaschen",
|
||||||
"new_order": "@.capitalize:{'words.generated.neuer'} @:{'words.generated.auftrag'}",
|
"new_order": "@.capitalize:{'words.generated.neuer'} @:{'words.generated.auftrag'}",
|
||||||
"new_sale": "Nytt salg",
|
"new_sale": "Nytt salg",
|
||||||
"no_bookings": "@.capitalize:{'words.generated.keine'} @:{'words.generated.buchungen'} @:{'words.generated.gefunden'}",
|
"no_bookings": "@.capitalize:{'words.generated.keine'} @:{'words.generated.buchungen'} @:{'words.generated.gefunden'}",
|
||||||
|
|||||||
@@ -5279,6 +5279,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.same'} @:{'words.generated.service'}, @:{'words.generated.add'}-@:{'words.generated.ons'}, @:{'words.generated.and'} @:{'words.generated.extra'} @:{'words.generated.items'} @:{'words.generated.as'} @:{'words.replication.article.host_mention'} @:{'words.generated.previous'} @:{'words.generated.wash'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.same'} @:{'words.generated.service'}, @:{'words.generated.add'}-@:{'words.generated.ons'}, @:{'words.generated.and'} @:{'words.generated.extra'} @:{'words.generated.items'} @:{'words.generated.as'} @:{'words.replication.article.host_mention'} @:{'words.generated.previous'} @:{'words.generated.wash'}",
|
||||||
"manual_entry": "@:{'words.generated.manual'} @:{'words.generated.registration'}",
|
"manual_entry": "@:{'words.generated.manual'} @:{'words.generated.registration'}",
|
||||||
|
"never_washed": "Never washed",
|
||||||
"new_order": "@.capitalize:{'words.generated.new'} @:{'words.generated.order'}",
|
"new_order": "@.capitalize:{'words.generated.new'} @:{'words.generated.order'}",
|
||||||
"new_sale": "@.capitalize:{'words.generated.new'} sale",
|
"new_sale": "@.capitalize:{'words.generated.new'} sale",
|
||||||
"no_bookings": "@.capitalize:{'words.generated.no'} @:{'words.generated.orders'} @:{'words.generated.found'}",
|
"no_bookings": "@.capitalize:{'words.generated.no'} @:{'words.generated.orders'} @:{'words.generated.found'}",
|
||||||
|
|||||||
@@ -4852,6 +4852,8 @@
|
|||||||
"last_wash_matches_current_selection": "@:{'templates.generated.compat.pos.last_wash_matches_current_selection'}",
|
"last_wash_matches_current_selection": "@:{'templates.generated.compat.pos.last_wash_matches_current_selection'}",
|
||||||
"license_plate": "@:{'templates.generated.compat.tables.common.registration_number'}",
|
"license_plate": "@:{'templates.generated.compat.tables.common.registration_number'}",
|
||||||
"manual_entry": "@:{'templates.generated.compat.pos.manual_entry'}",
|
"manual_entry": "@:{'templates.generated.compat.pos.manual_entry'}",
|
||||||
|
"last_wash": "@:{'templates.generated.compat.global.last_wash'}",
|
||||||
|
"never_washed": "@:{'templates.generated.compat.pos.never_washed'}",
|
||||||
"new_order": "@:{'templates.generated.compat.pos.new_order'}",
|
"new_order": "@:{'templates.generated.compat.pos.new_order'}",
|
||||||
"new_sale": "@:{'templates.generated.compat.pos.new_sale'}",
|
"new_sale": "@:{'templates.generated.compat.pos.new_sale'}",
|
||||||
"no_bookings": "@:{'templates.generated.compat.pos.no_bookings'}",
|
"no_bookings": "@:{'templates.generated.compat.pos.no_bookings'}",
|
||||||
|
|||||||
@@ -5561,6 +5561,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.samme'} @:{'words.generated.tjeneste'}, @:{'words.generated.tillegg'} @:{'words.generated.og'} @:{'words.generated.ekstra'} @:{'words.generated.varer'} @:{'words.generated.som'} @:{'words.generated.forrige'} @:{'words.generated.vask'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.samme'} @:{'words.generated.tjeneste'}, @:{'words.generated.tillegg'} @:{'words.generated.og'} @:{'words.generated.ekstra'} @:{'words.generated.varer'} @:{'words.generated.som'} @:{'words.generated.forrige'} @:{'words.generated.vask'}",
|
||||||
"manual_entry": "Manuell @:{'words.generated.registrering'}",
|
"manual_entry": "Manuell @:{'words.generated.registrering'}",
|
||||||
|
"never_washed": "Aldri vasket",
|
||||||
"new_order": "@.capitalize:{'words.generated.bestillingen'}",
|
"new_order": "@.capitalize:{'words.generated.bestillingen'}",
|
||||||
"new_sale": "@.capitalize:{'words.generated.nytt'} @:{'words.generated.salg'}",
|
"new_sale": "@.capitalize:{'words.generated.nytt'} @:{'words.generated.salg'}",
|
||||||
"no_bookings": "@.capitalize:{'words.generated.ingen'} @:{'words.generated.bestillinger'} @:{'words.generated.funnet'}",
|
"no_bookings": "@.capitalize:{'words.generated.ingen'} @:{'words.generated.bestillinger'} @:{'words.generated.funnet'}",
|
||||||
|
|||||||
@@ -5611,6 +5611,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.samma'} @:{'words.generated.tjanst'}, @:{'words.generated.tillval'} @:{'words.generated.och'} @:{'words.generated.extra'} @:{'words.generated.artiklar'} @:{'words.generated.som'} @:{'words.generated.senaste'} @:{'words.generated.tvatten'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'words.generated.samma'} @:{'words.generated.tjanst'}, @:{'words.generated.tillval'} @:{'words.generated.och'} @:{'words.generated.extra'} @:{'words.generated.artiklar'} @:{'words.generated.som'} @:{'words.generated.senaste'} @:{'words.generated.tvatten'}",
|
||||||
"manual_entry": "Manuell @:{'words.generated.registrering'}",
|
"manual_entry": "Manuell @:{'words.generated.registrering'}",
|
||||||
|
"never_washed": "Aldrig tvättad",
|
||||||
"new_order": "@.capitalize:{'words.generated.ny'} @:{'words.generated.order'}",
|
"new_order": "@.capitalize:{'words.generated.ny'} @:{'words.generated.order'}",
|
||||||
"new_sale": "@.capitalize:{'words.generated.nytt'} salg",
|
"new_sale": "@.capitalize:{'words.generated.nytt'} salg",
|
||||||
"no_bookings": "@.capitalize:{'words.generated.ingen'} @:{'words.generated.bestillinger'} @:{'words.generated.funnet'}",
|
"no_bookings": "@.capitalize:{'words.generated.ingen'} @:{'words.generated.bestillinger'} @:{'words.generated.funnet'}",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.samme'} @:{'terms.glossary.ydelse'}, @:{'terms.glossary.tilvalg'} @:{'terms.glossary.og'} @:{'terms.glossary.ekstra'} @:{'terms.glossary.varer'} @:{'terms.glossary.som'} @:{'terms.glossary.sidste'} @:{'terms.glossary.vask'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.samme'} @:{'terms.glossary.ydelse'}, @:{'terms.glossary.tilvalg'} @:{'terms.glossary.og'} @:{'terms.glossary.ekstra'} @:{'terms.glossary.varer'} @:{'terms.glossary.som'} @:{'terms.glossary.sidste'} @:{'terms.glossary.vask'}",
|
||||||
"manual_entry": "Manuell @:{'terms.glossary.registrering'}",
|
"manual_entry": "Manuell @:{'terms.glossary.registrering'}",
|
||||||
|
"never_washed": "Aldrig vasket",
|
||||||
"new_order": "@.capitalize:{'terms.glossary.ny'} order",
|
"new_order": "@.capitalize:{'terms.glossary.ny'} order",
|
||||||
"new_sale": "@.capitalize:{'terms.glossary.nyt'} @:{'terms.glossary.salg'}",
|
"new_sale": "@.capitalize:{'terms.glossary.nyt'} @:{'terms.glossary.salg'}",
|
||||||
"no_bookings": "@.capitalize:{'terms.glossary.ingen'} @:{'terms.glossary.bookinger'} @:{'terms.glossary.fundet'}",
|
"no_bookings": "@.capitalize:{'terms.glossary.ingen'} @:{'terms.glossary.bookinger'} @:{'terms.glossary.fundet'}",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.gleiche'} @:{'terms.glossary.leistung'}, @:{'terms.glossary.zusatzoptionen'} @:{'terms.glossary.und'} @:{'terms.glossary.zusatzartikel'} @:{'terms.glossary.wie'} @:{'terms.glossary.bei'} @:{'terms.glossary.der'} @:{'terms.glossary.letzten'} @:{'terms.glossary.wasche'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.gleiche'} @:{'terms.glossary.leistung'}, @:{'terms.glossary.zusatzoptionen'} @:{'terms.glossary.und'} @:{'terms.glossary.zusatzartikel'} @:{'terms.glossary.wie'} @:{'terms.glossary.bei'} @:{'terms.glossary.der'} @:{'terms.glossary.letzten'} @:{'terms.glossary.wasche'}",
|
||||||
"manual_entry": "@.capitalize:{'terms.glossary.manuell'} registrering",
|
"manual_entry": "@.capitalize:{'terms.glossary.manuell'} registrering",
|
||||||
|
"never_washed": "Noch nie gewaschen",
|
||||||
"new_order": "@.capitalize:{'terms.glossary.neuer'} @:{'terms.glossary.auftrag'}",
|
"new_order": "@.capitalize:{'terms.glossary.neuer'} @:{'terms.glossary.auftrag'}",
|
||||||
"new_sale": "Nytt salg",
|
"new_sale": "Nytt salg",
|
||||||
"no_bookings": "@.capitalize:{'terms.glossary.keine'} @:{'terms.glossary.buchungen'} @:{'terms.glossary.gefunden'}",
|
"no_bookings": "@.capitalize:{'terms.glossary.keine'} @:{'terms.glossary.buchungen'} @:{'terms.glossary.gefunden'}",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.same'} @:{'terms.glossary.service'}, @:{'terms.glossary.add'}-@:{'terms.glossary.ons'}, @:{'terms.glossary.and'} @:{'terms.glossary.extra'} @:{'terms.glossary.items'} @:{'terms.glossary.as'} @:{'terms.replication.article.host_mention'} @:{'terms.glossary.previous'} @:{'terms.glossary.wash'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.same'} @:{'terms.glossary.service'}, @:{'terms.glossary.add'}-@:{'terms.glossary.ons'}, @:{'terms.glossary.and'} @:{'terms.glossary.extra'} @:{'terms.glossary.items'} @:{'terms.glossary.as'} @:{'terms.replication.article.host_mention'} @:{'terms.glossary.previous'} @:{'terms.glossary.wash'}",
|
||||||
"manual_entry": "@:{'terms.glossary.manual'} @:{'terms.glossary.registration'}",
|
"manual_entry": "@:{'terms.glossary.manual'} @:{'terms.glossary.registration'}",
|
||||||
|
"never_washed": "Never washed",
|
||||||
"new_order": "@.capitalize:{'terms.glossary.new'} @:{'terms.glossary.order'}",
|
"new_order": "@.capitalize:{'terms.glossary.new'} @:{'terms.glossary.order'}",
|
||||||
"new_sale": "@.capitalize:{'terms.glossary.new'} sale",
|
"new_sale": "@.capitalize:{'terms.glossary.new'} sale",
|
||||||
"no_bookings": "@.capitalize:{'terms.glossary.no'} @:{'terms.glossary.orders'} @:{'terms.glossary.found'}",
|
"no_bookings": "@.capitalize:{'terms.glossary.no'} @:{'terms.glossary.orders'} @:{'terms.glossary.found'}",
|
||||||
|
|||||||
@@ -76,6 +76,8 @@
|
|||||||
"last_wash_matches_current_selection": "@:{'phrases.compat.pos.last_wash_matches_current_selection'}",
|
"last_wash_matches_current_selection": "@:{'phrases.compat.pos.last_wash_matches_current_selection'}",
|
||||||
"license_plate": "@:{'phrases.compat.tables.common.registration_number'}",
|
"license_plate": "@:{'phrases.compat.tables.common.registration_number'}",
|
||||||
"manual_entry": "@:{'phrases.compat.pos.manual_entry'}",
|
"manual_entry": "@:{'phrases.compat.pos.manual_entry'}",
|
||||||
|
"last_wash": "@:{'phrases.compat.global.last_wash'}",
|
||||||
|
"never_washed": "@:{'phrases.compat.pos.never_washed'}",
|
||||||
"new_order": "@:{'phrases.compat.pos.new_order'}",
|
"new_order": "@:{'phrases.compat.pos.new_order'}",
|
||||||
"new_sale": "@:{'phrases.compat.pos.new_sale'}",
|
"new_sale": "@:{'phrases.compat.pos.new_sale'}",
|
||||||
"no_bookings": "@:{'phrases.compat.pos.no_bookings'}",
|
"no_bookings": "@:{'phrases.compat.pos.no_bookings'}",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.samme'} @:{'terms.glossary.tjeneste'}, @:{'terms.glossary.tillegg'} @:{'terms.glossary.og'} @:{'terms.glossary.ekstra'} @:{'terms.glossary.varer'} @:{'terms.glossary.som'} @:{'terms.glossary.forrige'} @:{'terms.glossary.vask'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.samme'} @:{'terms.glossary.tjeneste'}, @:{'terms.glossary.tillegg'} @:{'terms.glossary.og'} @:{'terms.glossary.ekstra'} @:{'terms.glossary.varer'} @:{'terms.glossary.som'} @:{'terms.glossary.forrige'} @:{'terms.glossary.vask'}",
|
||||||
"manual_entry": "Manuell @:{'terms.glossary.registrering'}",
|
"manual_entry": "Manuell @:{'terms.glossary.registrering'}",
|
||||||
|
"never_washed": "Aldri vasket",
|
||||||
"new_order": "@.capitalize:{'terms.glossary.bestillingen'}",
|
"new_order": "@.capitalize:{'terms.glossary.bestillingen'}",
|
||||||
"new_sale": "@.capitalize:{'terms.glossary.nytt'} @:{'terms.glossary.salg'}",
|
"new_sale": "@.capitalize:{'terms.glossary.nytt'} @:{'terms.glossary.salg'}",
|
||||||
"no_bookings": "@.capitalize:{'terms.glossary.ingen'} @:{'terms.glossary.bestillinger'} @:{'terms.glossary.funnet'}",
|
"no_bookings": "@.capitalize:{'terms.glossary.ingen'} @:{'terms.glossary.bestillinger'} @:{'terms.glossary.funnet'}",
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
},
|
},
|
||||||
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.samma'} @:{'terms.glossary.tjanst'}, @:{'terms.glossary.tillval'} @:{'terms.glossary.och'} @:{'terms.glossary.extra'} @:{'terms.glossary.artiklar'} @:{'terms.glossary.som'} @:{'terms.glossary.senaste'} @:{'terms.glossary.tvatten'}",
|
"last_wash_matches_current_selection": "@.capitalize:{'terms.glossary.samma'} @:{'terms.glossary.tjanst'}, @:{'terms.glossary.tillval'} @:{'terms.glossary.och'} @:{'terms.glossary.extra'} @:{'terms.glossary.artiklar'} @:{'terms.glossary.som'} @:{'terms.glossary.senaste'} @:{'terms.glossary.tvatten'}",
|
||||||
"manual_entry": "Manuell @:{'terms.glossary.registrering'}",
|
"manual_entry": "Manuell @:{'terms.glossary.registrering'}",
|
||||||
|
"never_washed": "Aldrig tvättad",
|
||||||
"new_order": "@.capitalize:{'terms.glossary.ny'} @:{'terms.glossary.order'}",
|
"new_order": "@.capitalize:{'terms.glossary.ny'} @:{'terms.glossary.order'}",
|
||||||
"new_sale": "@.capitalize:{'terms.glossary.nytt'} salg",
|
"new_sale": "@.capitalize:{'terms.glossary.nytt'} salg",
|
||||||
"no_bookings": "@.capitalize:{'terms.glossary.ingen'} @:{'terms.glossary.bestillinger'} @:{'terms.glossary.funnet'}",
|
"no_bookings": "@.capitalize:{'terms.glossary.ingen'} @:{'terms.glossary.bestillinger'} @:{'terms.glossary.funnet'}",
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ vi.mock("@/components/session/token/SessionUser.vue", () => ({
|
|||||||
},
|
},
|
||||||
global: {
|
global: {
|
||||||
language: {
|
language: {
|
||||||
|
last_wash: "Last wash",
|
||||||
nothing_left_to_show: "Nothing left to show",
|
nothing_left_to_show: "Nothing left to show",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -133,6 +134,7 @@ const messages = {
|
|||||||
make: "Make",
|
make: "Make",
|
||||||
model: "Model",
|
model: "Model",
|
||||||
no_plates_found: "No license plates found",
|
no_plates_found: "No license plates found",
|
||||||
|
never_washed: "Never washed",
|
||||||
recent_scans: "Recent scans",
|
recent_scans: "Recent scans",
|
||||||
recent_scans_helper: "Select a license plate to view vehicle details.",
|
recent_scans_helper: "Select a license plate to view vehicle details.",
|
||||||
recent_scan_details_empty: "No vehicle details are available for this scan.",
|
recent_scan_details_empty: "No vehicle details are available for this scan.",
|
||||||
@@ -164,6 +166,9 @@ const scans = [
|
|||||||
customer_name: "Pleno Logistics",
|
customer_name: "Pleno Logistics",
|
||||||
seen_before: true,
|
seen_before: true,
|
||||||
barred: false,
|
barred: false,
|
||||||
|
// TRU-78: enriched by the API so the landing page can show when
|
||||||
|
// the plate was last washed (DHL pick-up use case).
|
||||||
|
last_wash: "2026-04-07 17:12:33",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 802,
|
id: 802,
|
||||||
@@ -174,6 +179,22 @@ const scans = [
|
|||||||
customer_name: "",
|
customer_name: "",
|
||||||
seen_before: false,
|
seen_before: false,
|
||||||
barred: false,
|
barred: false,
|
||||||
|
// TRU-78: explicit null means the API confirmed the plate has
|
||||||
|
// never been washed.
|
||||||
|
last_wash: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 803,
|
||||||
|
plate: "EF11111",
|
||||||
|
plate_scanner_id: 3,
|
||||||
|
created_at: "2026-04-08 08:30:00",
|
||||||
|
customer_number: null,
|
||||||
|
customer_name: "",
|
||||||
|
seen_before: false,
|
||||||
|
barred: false,
|
||||||
|
// TRU-78: missing field should be treated as "never washed" too,
|
||||||
|
// so older backends don't break the new UI.
|
||||||
|
// (no `last_wash` key on purpose)
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -341,4 +362,59 @@ describe("PosLastScannedLicensePlatesV2", () => {
|
|||||||
"Vehicle details could not be loaded"
|
"Vehicle details could not be loaded"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TRU-78 / DRIFT 17: license plate scan should show "last washed" on the
|
||||||
|
// landing page so the operator can see at a glance when a trailer was
|
||||||
|
// last washed (DHL pick-up use case).
|
||||||
|
it("renders the last washed timestamp when the scan has a last_wash value", async () => {
|
||||||
|
const wrapper = mountWithApp(PosLastScannedLicensePlatesV2, { messages });
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(1000);
|
||||||
|
paginationState.list.value = scans;
|
||||||
|
await flushUi();
|
||||||
|
|
||||||
|
await wrapper.get('[data-testid="pos-recent-scan-row-801"]').trigger("click");
|
||||||
|
await flushUi();
|
||||||
|
|
||||||
|
const lastWashField = wrapper.get('[data-testid="pos-recent-scan-detail-801-last-wash"]');
|
||||||
|
expect(lastWashField.exists()).toBe(true);
|
||||||
|
expect(lastWashField.text()).toContain("Last wash");
|
||||||
|
// The MySQL DATETIME "2026-04-07 17:12:33" is rendered in the user's
|
||||||
|
// locale. We accept both the raw DATETIME string (jsdom without full
|
||||||
|
// Intl support) and the locale-formatted output (e.g. 04/07/2026 or
|
||||||
|
// 2026-04-07 in browsers with Intl.DateTimeFormat).
|
||||||
|
expect(lastWashField.text()).toMatch(/2026/);
|
||||||
|
expect(lastWashField.text()).toMatch(/04[\/.\- ]07|07[\/.\- ]04|7[\/.\- ]4|2026-04-07/);
|
||||||
|
expect(lastWashField.text()).toMatch(/17:12/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows the 'never washed' message when the API confirms the plate has no last_wash", async () => {
|
||||||
|
const wrapper = mountWithApp(PosLastScannedLicensePlatesV2, { messages });
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(1000);
|
||||||
|
paginationState.list.value = scans;
|
||||||
|
await flushUi();
|
||||||
|
|
||||||
|
await wrapper.get('[data-testid="pos-recent-scan-row-802"]').trigger("click");
|
||||||
|
await flushUi();
|
||||||
|
|
||||||
|
const neverWashed = wrapper.get('[data-testid="pos-recent-scan-never-washed-802"]');
|
||||||
|
expect(neverWashed.exists()).toBe(true);
|
||||||
|
expect(neverWashed.text()).toContain("Never washed");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to 'never washed' when the scan has no last_wash key at all", async () => {
|
||||||
|
const wrapper = mountWithApp(PosLastScannedLicensePlatesV2, { messages });
|
||||||
|
|
||||||
|
await vi.advanceTimersByTimeAsync(1000);
|
||||||
|
paginationState.list.value = scans;
|
||||||
|
await flushUi();
|
||||||
|
|
||||||
|
await wrapper.get('[data-testid="pos-recent-scan-row-803"]').trigger("click");
|
||||||
|
await flushUi();
|
||||||
|
|
||||||
|
const neverWashed = wrapper.get('[data-testid="pos-recent-scan-never-washed-803"]');
|
||||||
|
expect(neverWashed.exists()).toBe(true);
|
||||||
|
expect(neverWashed.text()).toContain("Never washed");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user