From 5d21bb5b0afb6e3efb9589cf9b111de3f83162c4 Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Fri, 19 Sep 2025 15:02:01 +0200 Subject: [PATCH] Fix jwt-token --- client/src/components/MovementAlertsPanel.jsx | 26 ++++---- client/src/pages/MapView.jsx | 2 +- client/src/pages/Register.jsx | 20 ++++--- client/src/utils/tempTranslations.js | 60 ++++++++++++++++++- 4 files changed, 84 insertions(+), 24 deletions(-) diff --git a/client/src/components/MovementAlertsPanel.jsx b/client/src/components/MovementAlertsPanel.jsx index 19d40fe..7246338 100644 --- a/client/src/components/MovementAlertsPanel.jsx +++ b/client/src/components/MovementAlertsPanel.jsx @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import { format } from 'date-fns'; import { useSocket } from '../contexts/SocketContext'; +import { useTranslation } from '../utils/tempTranslations'; import { ExclamationTriangleIcon, InformationCircleIcon, @@ -13,6 +14,7 @@ import { } from '@heroicons/react/24/outline'; const MovementAlertsPanel = () => { + const { t } = useTranslation(); const { movementAlerts, clearMovementAlerts } = useSocket(); const [expandedAlert, setExpandedAlert] = useState(null); const [filter, setFilter] = useState('all'); // all, critical, high, medium @@ -55,12 +57,12 @@ const MovementAlertsPanel = () => { }); const droneTypes = { - 1: "DJI Mavic", - 2: "Racing Drone", - 3: "DJI Phantom", - 4: "Fixed Wing", - 5: "Surveillance", - 0: "Unknown" + 1: t('movementAlerts.droneTypes.djiMavic'), + 2: t('movementAlerts.droneTypes.racingDrone'), + 3: t('movementAlerts.droneTypes.djiPhantom'), + 4: t('movementAlerts.droneTypes.fixedWing'), + 5: t('movementAlerts.droneTypes.surveillance'), + 0: t('movementAlerts.droneTypes.unknown') }; return ( @@ -68,7 +70,7 @@ const MovementAlertsPanel = () => {
-

Movement Alerts

+

{t('movementAlerts.title')}

{movementAlerts.length > 0 && ( {movementAlerts.length} @@ -82,10 +84,10 @@ const MovementAlertsPanel = () => { onChange={(e) => setFilter(e.target.value)} className="text-sm border border-gray-300 rounded px-2 py-1" > - - - - + + + + {movementAlerts.length > 0 && ( @@ -93,7 +95,7 @@ const MovementAlertsPanel = () => { onClick={clearMovementAlerts} className="text-sm text-gray-600 hover:text-gray-800" > - Clear All + {t('movementAlerts.clearAll')} )}
diff --git a/client/src/pages/MapView.jsx b/client/src/pages/MapView.jsx index 0833a4c..6f73c78 100644 --- a/client/src/pages/MapView.jsx +++ b/client/src/pages/MapView.jsx @@ -340,7 +340,7 @@ const MapView = () => { onChange={(e) => setShowDroneDetections(e.target.checked)} className="rounded border-gray-300 text-primary-600 focus:ring-primary-500" /> - Show Drone Detections + {t('map.showDroneDetections')} {droneDetectionHistory.length > 0 && ( diff --git a/client/src/pages/Register.jsx b/client/src/pages/Register.jsx index 917ac81..040cadf 100644 --- a/client/src/pages/Register.jsx +++ b/client/src/pages/Register.jsx @@ -1,11 +1,13 @@ import React, { useState, useEffect } from 'react'; import { Navigate, Link } from 'react-router-dom'; import { useAuth } from '../contexts/AuthContext'; +import { useTranslation } from '../utils/tempTranslations'; import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'; import toast from 'react-hot-toast'; import api from '../services/api'; const Register = () => { + const { t } = useTranslation(); const [formData, setFormData] = useState({ username: '', email: '', @@ -31,11 +33,11 @@ const Register = () => { // Security check: If registration is not enabled, show error if (!response.data.data?.features?.registration) { - toast.error('Registration is not enabled for this tenant'); + toast.error(t('register.registrationDisabled')); } } catch (error) { console.error('Failed to fetch tenant config:', error); - toast.error('Failed to load authentication configuration'); + toast.error(t('register.configLoadFailed')); } finally { setConfigLoading(false); } @@ -124,38 +126,38 @@ const Register = () => { // Validation if (!formData.username || !formData.email || !formData.password) { - toast.error('Please fill in all required fields'); + toast.error(t('register.fillAllFields')); return; } if (formData.password !== formData.confirmPassword) { - toast.error('Passwords do not match'); + toast.error(t('register.passwordsMismatch')); return; } if (formData.password.length < 8) { - toast.error('Password must be at least 8 characters long'); + toast.error(t('register.passwordTooShort')); return; } // Strong password validation const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/; if (!passwordRegex.test(formData.password)) { - toast.error('Password must contain at least one lowercase letter, one uppercase letter, and one number'); + toast.error(t('register.passwordRequirements')); return; } // Username validation const usernameRegex = /^[a-zA-Z0-9._-]+$/; if (!usernameRegex.test(formData.username)) { - toast.error('Username can only contain letters, numbers, dots, underscores, and hyphens'); + toast.error(t('register.usernameInvalid')); return; } // Email validation const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(formData.email)) { - toast.error('Please enter a valid email address'); + toast.error(t('register.emailInvalid')); return; } @@ -163,7 +165,7 @@ const Register = () => { if (formData.phone_number) { const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/; if (!phoneRegex.test(formData.phone_number.replace(/[\s\-\(\)]/g, ''))) { - toast.error('Please enter a valid phone number'); + toast.error(t('register.phoneInvalid')); return; } } diff --git a/client/src/utils/tempTranslations.js b/client/src/utils/tempTranslations.js index 327e034..91a401b 100644 --- a/client/src/utils/tempTranslations.js +++ b/client/src/utils/tempTranslations.js @@ -313,7 +313,35 @@ const translations = { differentPatterns: 'Different dash patterns', droneLabels: 'Drone ID labels shown', positionOffsets: 'Slight position offsets for visibility', - ringSize: 'Ring size = estimated distance from detector' + ringSize: 'Ring size = estimated distance from detector', + showDroneDetections: 'Show Drone Detections' + }, + movementAlerts: { + title: 'Movement Alerts', + allAlerts: 'All Alerts', + critical: 'Critical', + highPriority: 'High Priority', + mediumPriority: 'Medium Priority', + clearAll: 'Clear All', + droneTypes: { + djiMavic: 'DJI Mavic', + racingDrone: 'Racing Drone', + djiPhantom: 'DJI Phantom', + fixedWing: 'Fixed Wing', + surveillance: 'Surveillance', + unknown: 'Unknown' + } + }, + register: { + registrationDisabled: 'Registration is not enabled for this tenant', + configLoadFailed: 'Failed to load authentication configuration', + fillAllFields: 'Please fill in all required fields', + passwordsMismatch: 'Passwords do not match', + passwordTooShort: 'Password must be at least 8 characters long', + passwordRequirements: 'Password must contain at least one lowercase letter, one uppercase letter, and one number', + usernameInvalid: 'Username can only contain letters, numbers, dots, underscores, and hyphens', + emailInvalid: 'Please enter a valid email address', + phoneInvalid: 'Please enter a valid phone number' }, app: { title: 'UAM-ILS Drone Detection System', @@ -684,7 +712,35 @@ const translations = { differentPatterns: 'Olika streckmönster', droneLabels: 'Drönar-ID-etiketter visas', positionOffsets: 'Lätta positionsförskjutningar för synlighet', - ringSize: 'Ringstorlek = uppskattad distans från detektor' + ringSize: 'Ringstorlek = uppskattad distans från detektor', + showDroneDetections: 'Visa drönardetekteringar' + }, + movementAlerts: { + title: 'Rörelselarm', + allAlerts: 'Alla larm', + critical: 'Kritisk', + highPriority: 'Hög prioritet', + mediumPriority: 'Medel prioritet', + clearAll: 'Rensa alla', + droneTypes: { + djiMavic: 'DJI Mavic', + racingDrone: 'Racingdrönare', + djiPhantom: 'DJI Phantom', + fixedWing: 'Fast vinge', + surveillance: 'Övervakning', + unknown: 'Okänd' + } + }, + register: { + registrationDisabled: 'Registrering är inte aktiverad för denna klient', + configLoadFailed: 'Misslyckades med att ladda autentiseringskonfiguration', + fillAllFields: 'Vänligen fyll i alla obligatoriska fält', + passwordsMismatch: 'Lösenorden stämmer inte överens', + passwordTooShort: 'Lösenordet måste vara minst 8 tecken långt', + passwordRequirements: 'Lösenordet måste innehålla minst en liten bokstav, en stor bokstav och en siffra', + usernameInvalid: 'Användarnamn kan bara innehålla bokstäver, siffror, punkter, understreck och bindestreck', + emailInvalid: 'Vänligen ange en giltig e-postadress', + phoneInvalid: 'Vänligen ange ett giltigt telefonnummer' }, app: { title: 'UAM-ILS Drönardetekteringssystem',