feat : M5 — Tickets de pesée (ERP-188 → ERP-193) #144
@@ -5,23 +5,9 @@
|
||||
* mettre en forme la valeur déjà normalisée renvoyée par l'API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Date courte française `JJ-MM-AAAA` (spec M5). Chaîne vide si la valeur est
|
||||
* absente ou invalide. Lit les composantes locales (cohérent avec l'affichage
|
||||
* des autres répertoires M1→M4).
|
||||
*/
|
||||
export function formatDateFr(value: string | null | undefined): string {
|
||||
if (!value) {
|
||||
return ''
|
||||
}
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return ''
|
||||
}
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
return `${day}-${month}-${date.getFullYear()}`
|
||||
}
|
||||
// Date courte française `JJ-MM-AAAA` (spec M5) : helper partagé inter-modules
|
||||
// (mutualisé avec les répertoires M1→M4). Re-exporté ici pour les écrans M5.
|
||||
export { formatDateFr } from '~/shared/utils/date'
|
||||
|
||||
/**
|
||||
* Poids en kg avec séparateur de milliers (espace) + suffixe « Kg »
|
||||
|
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { debounce } from '~/shared/utils/debounce'
|
||||
import { formatDateFr } from '~/shared/utils/date'
|
||||
import { useQualimatSearch, type QualimatCarrierRow } from '~/modules/transport/composables/useQualimatSearch'
|
||||
|
||||
/**
|
||||
@@ -92,19 +93,6 @@ function isExpired(value: string): boolean {
|
||||
return date.getTime() < today.getTime()
|
||||
}
|
||||
|
||||
/** Format court français JJ-MM-AAAA (chaîne vide si date absente / invalide). */
|
||||
function formatDateFr(value: string | null | undefined): string {
|
||||
if (!value) {
|
||||
return ''
|
||||
}
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return ''
|
||||
}
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
return `${day}-${month}-${date.getFullYear()}`
|
||||
}
|
||||
|
||||
// ── Confirmation d'intégration ───────────────────────────────────────────────
|
||||
const confirmOpen = ref(false)
|
||||
|
||||
@@ -141,6 +141,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { formatDateFr } from '~/shared/utils/date'
|
||||
|
||||
interface FilterOption {
|
||||
value: string
|
||||
@@ -235,20 +236,6 @@ function isValidityExpired(item: Record<string, unknown>): boolean {
|
||||
return date.getTime() < today.getTime()
|
||||
}
|
||||
|
||||
/** Format court francais JJ-MM-AAAA (spec M4). Chaine vide si date absente / invalide. */
|
||||
function formatDateFr(value: string | null | undefined): string {
|
||||
if (!value) {
|
||||
return ''
|
||||
}
|
||||
const date = new Date(value)
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return ''
|
||||
}
|
||||
const day = String(date.getDate()).padStart(2, '0')
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||
return `${day}-${month}-${date.getFullYear()}`
|
||||
}
|
||||
|
||||
/** Clic sur une ligne → ecran Consultation (route a plat /carriers/{id}). */
|
||||
function onRowClick(item: Record<string, unknown>): void {
|
||||
router.push(`/carriers/${item.id}`)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { todayIso } from '../date'
|
||||
import { formatDateFr, todayIso } from '../date'
|
||||
|
||||
describe('todayIso', () => {
|
||||
it('formate la date locale en YYYY-MM-DD (zero-pad mois/jour)', () => {
|
||||
@@ -17,3 +17,28 @@ describe('todayIso', () => {
|
||||
expect(todayIso(new Date(2026, 11, 31, 12, 0))).toBe('2026-12-31')
|
||||
})
|
||||
})
|
||||
|
||||
describe('formatDateFr', () => {
|
||||
it('formate un datetime ISO avec offset en JJ-MM-AAAA', () => {
|
||||
expect(formatDateFr('2026-06-17T09:12:00+02:00')).toBe('17-06-2026')
|
||||
})
|
||||
|
||||
it('lit la date dans la CHAINE, sans decalage de fuseau (deterministe)', () => {
|
||||
// Minuit UTC : une lecture via new Date().getDate() basculerait au 4 dans un
|
||||
// fuseau negatif (ex. America). On lit la chaine -> reste le 05 partout.
|
||||
expect(formatDateFr('2026-01-05T00:00:00Z')).toBe('05-01-2026')
|
||||
// Idem juste avant minuit avec offset +02:00 : la date affichee est celle
|
||||
// portee par la chaine (17), pas le 16 d'un runtime UTC.
|
||||
expect(formatDateFr('2026-06-17T00:30:00+02:00')).toBe('17-06-2026')
|
||||
})
|
||||
|
||||
it('accepte une date nue YYYY-MM-DD', () => {
|
||||
expect(formatDateFr('2026-03-07')).toBe('07-03-2026')
|
||||
})
|
||||
|
||||
it('renvoie une chaine vide pour une valeur absente ou non ISO', () => {
|
||||
expect(formatDateFr(null)).toBe('')
|
||||
expect(formatDateFr(undefined)).toBe('')
|
||||
expect(formatDateFr('pas-une-date')).toBe('')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -30,3 +30,22 @@ export function nowIsoDateTime(now: Date = new Date()): string {
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0')
|
||||
return `${todayIso(now)}T${hours}:${minutes}:${seconds}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Date courte française `JJ-MM-AAAA` à partir d'une valeur ISO (`YYYY-MM-DD` ou
|
||||
* datetime `YYYY-MM-DDTHH:mm:ss±HH:mm`). Chaîne vide si absente ou non ISO.
|
||||
*
|
||||
* On lit les composantes DIRECTEMENT dans la chaîne (10 premiers caractères) au
|
||||
* lieu de `new Date(value).getDate()` : un datetime porteur d'un offset (ex.
|
||||
* `…T00:30:00+02:00`, ou `…Z`) basculerait d'un jour selon le fuseau du
|
||||
* navigateur / du runner CI. Rendu ainsi déterministe et cohérent avec l'écran
|
||||
* d'édition (slice de la chaîne brute) et l'export serveur (`format('d/m/Y')`).
|
||||
*/
|
||||
export function formatDateFr(value: string | null | undefined): string {
|
||||
const match = value ? /^(\d{4})-(\d{2})-(\d{2})/.exec(value) : null
|
||||
if (!match) {
|
||||
return ''
|
||||
}
|
||||
const [, year, month, day] = match
|
||||
return `${day}-${month}-${year}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user
🟢 Mineur —
formatDateFrdupliqué + lecture en fuseau localFonction identique à celle de
transport/pages/carriers/index.vue(3ᵉ variante de rendu date FR dans le repo). De plus elle litgetDate()/getMonth()en fuseau navigateur : sur une date proche de minuit avec offset+02:00, un runtime UTC (CI/Vitest, poste hors Europe/Paris) décale d'un jour, alors que l'écran d'édition (slice de la chaîne brute) et l'export XLSX (format('d/m/Y H:i')serveur) gardent le bon jour → divergence liste vs édition vs export. À hoister dansshared/utils/date.tsà côté denowIsoDateTime/todayIso.