diff --git a/frontend/modules/transport/pages/carriers/[id]/edit.vue b/frontend/modules/transport/pages/carriers/[id]/edit.vue
index 00f61e3..0ab84ac 100644
--- a/frontend/modules/transport/pages/carriers/[id]/edit.vue
+++ b/frontend/modules/transport/pages/carriers/[id]/edit.vue
@@ -25,14 +25,19 @@
:required="true"
:error="mainErrors.errors.name"
/>
-
+
+
+ main.liotPlates = sanitizeLiotPlates(v)"
+ :label="t('transport.carriers.form.main.liotPlates')"
+ :hint="t('transport.carriers.form.main.liotPlatesHint')"
+ :required="true"
+ :error="mainErrors.errors.liotPlates"
+ />
+
-
-
+
+
+ main.liotPlates = sanitizeLiotPlates(v)"
+ :label="t('transport.carriers.form.main.liotPlates')"
+ :hint="t('transport.carriers.form.main.liotPlatesHint')"
+ :required="true"
+ :disabled="mainLocked"
+ :error="mainErrors.errors.liotPlates"
+ />
+
@@ -308,7 +313,7 @@ import CarrierPriceBlock from '~/modules/transport/components/CarrierPriceBlock.
import CarrierQualimatTab from '~/modules/transport/components/CarrierQualimatTab.vue'
import { useCarrierForm } from '~/modules/transport/composables/useCarrierForm'
import type { QualimatCarrierRow } from '~/modules/transport/composables/useQualimatSearch'
-import { clampPercent, sanitizeDecimal } from '~/modules/transport/utils/forms/numberInput'
+import { clampPercent, sanitizeDecimal, sanitizeLiotPlates } from '~/modules/transport/utils/forms/numberInput'
import { sanitizeFreeText } from '~/shared/utils/textSanitize'
interface SelectOption {
diff --git a/frontend/modules/transport/utils/forms/__tests__/numberInput.test.ts b/frontend/modules/transport/utils/forms/__tests__/numberInput.test.ts
index fff0a56..eeba136 100644
--- a/frontend/modules/transport/utils/forms/__tests__/numberInput.test.ts
+++ b/frontend/modules/transport/utils/forms/__tests__/numberInput.test.ts
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
-import { clampPercent, sanitizeDecimal } from '../numberInput'
+import { clampPercent, sanitizeDecimal, sanitizeLiotPlates } from '../numberInput'
describe('numberInput — saisie volume / indexation (ERP-170)', () => {
it('sanitizeDecimal : ne garde que chiffres + un seul point', () => {
@@ -19,4 +19,12 @@ describe('numberInput — saisie volume / indexation (ERP-170)', () => {
expect(clampPercent('12,5')).toBe('12,5') // ≤ 100 → inchangé
expect(clampPercent('')).toBe('')
})
+
+ it('sanitizeLiotPlates : garde lettres/chiffres/tiret/point-virgule, retire espaces et reste', () => {
+ expect(sanitizeLiotPlates('AB-123-CD;EF-456-GH')).toBe('AB-123-CD;EF-456-GH')
+ expect(sanitizeLiotPlates('ab-123-cd ; ef-456-gh')).toBe('ab-123-cd;ef-456-gh') // espaces retirés
+ expect(sanitizeLiotPlates('AB 123 CD')).toBe('AB123CD') // espaces retirés
+ expect(sanitizeLiotPlates('AB.123/CD#42')).toBe('AB123CD42') // . / # retirés
+ expect(sanitizeLiotPlates('')).toBe('')
+ })
})
diff --git a/frontend/modules/transport/utils/forms/numberInput.ts b/frontend/modules/transport/utils/forms/numberInput.ts
index 29f9f8e..79b8d98 100644
--- a/frontend/modules/transport/utils/forms/numberInput.ts
+++ b/frontend/modules/transport/utils/forms/numberInput.ts
@@ -26,3 +26,13 @@ export function clampPercent(value: string): string {
const n = Number(String(value ?? '').replace(',', '.').replace(/\s/g, ''))
return (!Number.isNaN(n) && n > 100) ? '100' : value
}
+
+/**
+ * Restreint la saisie des immatriculations LIOT : ne garde que lettres, chiffres,
+ * tiret et point-virgule (séparateur de plaques). Les espaces et tout autre
+ * caractère sont supprimés à la frappe / au collage. La normalisation finale
+ * (majuscules + « ; » espacé) reste au back (RG-4.13).
+ */
+export function sanitizeLiotPlates(value: string): string {
+ return (value ?? '').replace(/[^A-Za-z0-9;-]/g, '')
+}