refactor(device_setup): type API errors with status-code-based enum

Introduce LegacyDeviceSetupErrorEvent and two mappers for the
generate-activation-key and create-device endpoints. 403 on
activation-key maps to invalidIdentificator; 404 to deviceNotFound;
401 (already activated or B2B) unifies as deviceNotAvailable. On
create-device, 403 → invalidField and 404 → invalidActivationKey.
The view state now splits validation vs API errors with a
displayErrorKey extension, replacing the previous e.toString() leak
that could surface stack traces to users.
This commit is contained in:
2026-04-17 11:12:37 +02:00
parent fad2c8792c
commit bf1032245a
12 changed files with 245 additions and 50 deletions

View File

@@ -89,6 +89,11 @@
"recoverPasswordErrorInvalidField": "Eines der Felder ist ungültig. Bitte überprüfen Sie es und versuchen Sie es erneut.",
"recoverPasswordErrorTokenExpired": "Der Wiederherstellungslink ist abgelaufen. Bitte fordern Sie einen neuen an.",
"recoverPasswordErrorTokenNotFound": "Der Wiederherstellungslink ist ungültig. Bitte fordern Sie einen neuen an.",
"deviceSetupErrorInvalidIdentificator": "Die Geräte-ID ist ungültig.",
"deviceSetupErrorDeviceNotFound": "Das Gerät konnte nicht gefunden werden. Bitte überprüfen Sie den Code und versuchen Sie es erneut.",
"deviceSetupErrorDeviceNotAvailable": "Dieses Gerät ist nicht für die Aktivierung verfügbar.",
"deviceSetupErrorInvalidField": "Eines der Gerätedetails ist ungültig. Bitte überprüfen und erneut versuchen.",
"deviceSetupErrorInvalidActivationKey": "Der Aktivierungsschlüssel ist ungültig. Bitte scannen Sie das Gerät erneut.",
"stepUserContactSupertitle": "Benutzer und Kontakt",
"stepUserContactTitle": "Erstelle dein Konto",
"stepUserContactSubtitle": "Mit deiner E-Mail und deiner Telefonnummer können wir dich jederzeit informieren",

View File

@@ -89,6 +89,11 @@
"recoverPasswordErrorInvalidField": "One of the fields is invalid. Please check and try again.",
"recoverPasswordErrorTokenExpired": "The recovery link has expired. Please request a new one.",
"recoverPasswordErrorTokenNotFound": "The recovery link is not valid. Please request a new one.",
"deviceSetupErrorInvalidIdentificator": "The device identifier is not valid.",
"deviceSetupErrorDeviceNotFound": "We couldn't find the device. Please check the code and try again.",
"deviceSetupErrorDeviceNotAvailable": "This device is not available for activation.",
"deviceSetupErrorInvalidField": "One of the device details is invalid. Please check and try again.",
"deviceSetupErrorInvalidActivationKey": "The activation key is not valid. Please scan the device again.",
"stepUserContactSupertitle": "User & contact",
"stepUserContactTitle": "Create your account",
"stepUserContactSubtitle": "With your email and phone number we can keep you informed at all times",

View File

@@ -89,6 +89,11 @@
"recoverPasswordErrorInvalidField": "Alguno de los campos no es válido. Revísalos e inténtalo de nuevo.",
"recoverPasswordErrorTokenExpired": "El enlace de recuperación ha caducado. Solicita uno nuevo.",
"recoverPasswordErrorTokenNotFound": "El enlace de recuperación no es válido. Solicita uno nuevo.",
"deviceSetupErrorInvalidIdentificator": "El identificador del dispositivo no es válido.",
"deviceSetupErrorDeviceNotFound": "No encontramos el dispositivo. Verifica el código e inténtalo de nuevo.",
"deviceSetupErrorDeviceNotAvailable": "Este dispositivo no está disponible para activarse.",
"deviceSetupErrorInvalidField": "Alguno de los datos del dispositivo no es válido. Revísalo e inténtalo de nuevo.",
"deviceSetupErrorInvalidActivationKey": "La clave de activación no es válida. Vuelve a escanear el dispositivo.",
"stepUserContactSupertitle": "Usuario y contacto",
"stepUserContactTitle": "Crea tu usuario",
"stepUserContactSubtitle": "Con tu email y tu número podremos mantenerte siempre informado",

View File

@@ -89,6 +89,11 @@
"recoverPasswordErrorInvalidField": "L'un des champs n'est pas valide. Vérifiez et réessayez.",
"recoverPasswordErrorTokenExpired": "Le lien de récupération a expiré. Demandez-en un nouveau.",
"recoverPasswordErrorTokenNotFound": "Le lien de récupération n'est pas valide. Demandez-en un nouveau.",
"deviceSetupErrorInvalidIdentificator": "L'identifiant de l'appareil n'est pas valide.",
"deviceSetupErrorDeviceNotFound": "Nous n'avons pas trouvé l'appareil. Vérifiez le code et réessayez.",
"deviceSetupErrorDeviceNotAvailable": "Cet appareil n'est pas disponible pour l'activation.",
"deviceSetupErrorInvalidField": "L'un des détails de l'appareil n'est pas valide. Vérifiez et réessayez.",
"deviceSetupErrorInvalidActivationKey": "La clé d'activation n'est pas valide. Veuillez scanner à nouveau l'appareil.",
"stepUserContactSupertitle": "Utilisateur et contact",
"stepUserContactTitle": "Crée ton compte",
"stepUserContactSubtitle": "Avec ton e-mail et ton numéro, nous pourrons te tenir informé à tout moment",

View File

@@ -89,6 +89,11 @@
"recoverPasswordErrorInvalidField": "Uno dei campi non è valido. Controlla e riprova.",
"recoverPasswordErrorTokenExpired": "Il link di recupero è scaduto. Richiedine uno nuovo.",
"recoverPasswordErrorTokenNotFound": "Il link di recupero non è valido. Richiedine uno nuovo.",
"deviceSetupErrorInvalidIdentificator": "L'identificatore del dispositivo non è valido.",
"deviceSetupErrorDeviceNotFound": "Non abbiamo trovato il dispositivo. Controlla il codice e riprova.",
"deviceSetupErrorDeviceNotAvailable": "Questo dispositivo non è disponibile per l'attivazione.",
"deviceSetupErrorInvalidField": "Uno dei dettagli del dispositivo non è valido. Controlla e riprova.",
"deviceSetupErrorInvalidActivationKey": "La chiave di attivazione non è valida. Scansiona nuovamente il dispositivo.",
"stepUserContactSupertitle": "Utente e contatti",
"stepUserContactTitle": "Crea il tuo account",
"stepUserContactSubtitle": "Con la tua email e il tuo numero potremo tenerti sempre informato",

View File

@@ -89,6 +89,11 @@
"recoverPasswordErrorInvalidField": "Um dos campos não é válido. Verifica e tenta novamente.",
"recoverPasswordErrorTokenExpired": "O link de recuperação expirou. Solicita um novo.",
"recoverPasswordErrorTokenNotFound": "O link de recuperação não é válido. Solicita um novo.",
"deviceSetupErrorInvalidIdentificator": "O identificador do dispositivo não é válido.",
"deviceSetupErrorDeviceNotFound": "Não encontramos o dispositivo. Verifica o código e tenta novamente.",
"deviceSetupErrorDeviceNotAvailable": "Este dispositivo não está disponível para ativação.",
"deviceSetupErrorInvalidField": "Um dos dados do dispositivo não é válido. Verifica e tenta novamente.",
"deviceSetupErrorInvalidActivationKey": "A chave de ativação não é válida. Volta a digitalizar o dispositivo.",
"stepUserContactSupertitle": "Utilizador e contacto",
"stepUserContactTitle": "Cria a tua conta",
"stepUserContactSubtitle": "Com o teu email e o teu número poderemos manter-te sempre informado",

View File

@@ -434,6 +434,16 @@ class I18n {
'recoverPasswordErrorTokenExpired';
static const String recoverPasswordErrorTokenNotFound =
'recoverPasswordErrorTokenNotFound';
static const String deviceSetupErrorInvalidIdentificator =
'deviceSetupErrorInvalidIdentificator';
static const String deviceSetupErrorDeviceNotFound =
'deviceSetupErrorDeviceNotFound';
static const String deviceSetupErrorDeviceNotAvailable =
'deviceSetupErrorDeviceNotAvailable';
static const String deviceSetupErrorInvalidField =
'deviceSetupErrorInvalidField';
static const String deviceSetupErrorInvalidActivationKey =
'deviceSetupErrorInvalidActivationKey';
static const String errorGeofenceCreate = 'errorGeofenceCreate';
static const String errorGeofenceDelete = 'errorGeofenceDelete';
static const String errorGeofenceUpdate = 'errorGeofenceUpdate';