added i18n for backend errors
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "frangipane-client",
|
"name": "frangipane-client",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"backendVersion": "1.0.4",
|
"backendVersion": "1.0.5",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { UpdateUserResponse } from '../types';
|
import { UpdateUserResponse } from '../types';
|
||||||
import { apiFetch } from './client'
|
import { apiFetch, ApiError } from './client'
|
||||||
// import { upload } from '@tauri-apps/plugin-upload';
|
|
||||||
import { getAuthData } from '../store';
|
import { getAuthData } from '../store';
|
||||||
import { API } from '../main.ts';
|
import { API } from '../main.ts';
|
||||||
|
|
||||||
@@ -25,7 +24,6 @@ export async function uploadAvatar(
|
|||||||
xhr.setRequestHeader('Authorization', `Bearer ${auth.token}`);
|
xhr.setRequestHeader('Authorization', `Bearer ${auth.token}`);
|
||||||
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
|
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
|
||||||
|
|
||||||
// Handle Progress
|
|
||||||
if (xhr.upload && onProgress) {
|
if (xhr.upload && onProgress) {
|
||||||
xhr.upload.onprogress = (event) => {
|
xhr.upload.onprogress = (event) => {
|
||||||
if (event.lengthComputable) {
|
if (event.lengthComputable) {
|
||||||
@@ -39,11 +37,32 @@ export async function uploadAvatar(
|
|||||||
if (xhr.status >= 200 && xhr.status < 300) {
|
if (xhr.status >= 200 && xhr.status < 300) {
|
||||||
resolve(xhr.response);
|
resolve(xhr.response);
|
||||||
} else {
|
} else {
|
||||||
|
if (xhr.status === 413) {
|
||||||
|
reject(new ApiError('FILE_TOO_LARGE', 'File too large'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = JSON.parse(xhr.responseText);
|
||||||
|
if (res && res.code && res.message) {
|
||||||
|
reject(new ApiError(res.code, res.message));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
reject(new Error(`Upload failed with status ${xhr.status}: ${xhr.responseText}`));
|
reject(new Error(`Upload failed with status ${xhr.status}: ${xhr.responseText}`));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr.onerror = () => reject(new Error('Network error during upload'));
|
xhr.onerror = () => {
|
||||||
|
if (xhr.status === 413) {
|
||||||
|
reject(new ApiError('FILE_TOO_LARGE', 'File too large'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reject(new ApiError("UPLOAD_FAILED", "Failed uploading file."));
|
||||||
|
};
|
||||||
|
|
||||||
xhr.send(fileData);
|
xhr.send(fileData);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,17 @@ import { getAuthData, clearAuthData } from '../store'
|
|||||||
import { API } from '../main.ts'
|
import { API } from '../main.ts'
|
||||||
import router from '../router'
|
import router from '../router'
|
||||||
|
|
||||||
|
// Custom Error class to hold the backend code
|
||||||
|
export class ApiError extends Error {
|
||||||
|
code: string;
|
||||||
|
|
||||||
|
constructor(code: string, message: string) {
|
||||||
|
super(message);
|
||||||
|
this.name = 'ApiError';
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function apiFetch<T>(
|
export async function apiFetch<T>(
|
||||||
path: string,
|
path: string,
|
||||||
options: RequestInit = {}
|
options: RequestInit = {}
|
||||||
@@ -15,26 +26,36 @@ export async function apiFetch<T>(
|
|||||||
...options,
|
...options,
|
||||||
method: options.method || 'GET',
|
method: options.method || 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
// Only add json header if it's not formdata
|
|
||||||
...(!isFormData ? { 'Content-Type': 'application/json' } : {}),
|
...(!isFormData ? { 'Content-Type': 'application/json' } : {}),
|
||||||
...(auth.token ? { Authorization: `Bearer ${auth.token}` } : {}),
|
...(auth.token ? { Authorization: `Bearer ${auth.token}` } : {}),
|
||||||
...options.headers,
|
...options.headers,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (res.status === 401 && auth.token) {
|
// Invalid token?
|
||||||
|
if (res.status === 401) {
|
||||||
|
if (auth.token) {
|
||||||
await clearAuthData()
|
await clearAuthData()
|
||||||
router.push('/login')
|
router.push('/login')
|
||||||
throw new Error("Session expired")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle error responses
|
// Handle error responses
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const text = await res.text()
|
const text = await res.text()
|
||||||
|
|
||||||
|
try {
|
||||||
|
const json = JSON.parse(text);
|
||||||
|
if (json && json.code && json.message) {
|
||||||
|
throw new ApiError(json.code, json.message);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof ApiError) throw e;
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error(text || res.statusText)
|
throw new Error(text || res.statusText)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the response as text first
|
|
||||||
const responseText = await res.text()
|
const responseText = await res.text()
|
||||||
|
|
||||||
if (!responseText) {
|
if (!responseText) {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
<form class="modal" @submit.prevent="submit">
|
<form class="modal" @submit.prevent="submit">
|
||||||
<h2>{{ $t('chat-create-title') }}</h2>
|
<h2>{{ $t('chat-create-title') }}</h2>
|
||||||
|
|
||||||
|
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label>{{ $t('chat-create-name') }}</label>
|
<label>{{ $t('chat-create-name') }}</label>
|
||||||
<input v-model="name" :placeholder="$t('chat-create-name-placeholder')" autofocus />
|
<input v-model="name" :placeholder="$t('chat-create-name-placeholder')" autofocus />
|
||||||
@@ -32,7 +34,11 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { createRoom } from '../api/rooms'
|
import { createRoom } from '../api/rooms'
|
||||||
import type { Room } from '../types'
|
import type { Room } from '../types'
|
||||||
|
import { useErrorTranslator } from '../errors';
|
||||||
|
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
|
const errorMessage = ref('')
|
||||||
const name = ref('')
|
const name = ref('')
|
||||||
const global = ref(false)
|
const global = ref(false)
|
||||||
|
|
||||||
@@ -42,11 +48,16 @@ const emit = defineEmits<{
|
|||||||
}>()
|
}>()
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
|
try {
|
||||||
const room = await createRoom(name.value, global.value)
|
const room = await createRoom(name.value, global.value)
|
||||||
emit('created', room)
|
emit('created', room)
|
||||||
emit('close')
|
emit('close')
|
||||||
name.value = ''
|
name.value = ''
|
||||||
global.value = false
|
global.value = false
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
errorMessage.value = translateError(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ import { ref } from 'vue'
|
|||||||
import { sendRoomInvite } from '../api/rooms'
|
import { sendRoomInvite } from '../api/rooms'
|
||||||
import { sendFriendRequest } from '../api/friends';
|
import { sendFriendRequest } from '../api/friends';
|
||||||
import { useFluent } from 'fluent-vue';
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { useErrorTranslator } from '../errors';
|
||||||
|
|
||||||
const { $t } = useFluent();
|
const { $t } = useFluent();
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
const props = defineProps<{ room_uuid: string }>();
|
const props = defineProps<{ room_uuid: string }>();
|
||||||
|
|
||||||
@@ -50,10 +52,7 @@ async function submit() {
|
|||||||
errorMessage.value = ''
|
errorMessage.value = ''
|
||||||
const username = receiverUsername.value.trim()
|
const username = receiverUsername.value.trim()
|
||||||
|
|
||||||
if (!username) {
|
if (!username) return
|
||||||
// errorMessage.value = 'Username is required.'
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendRoomInvite(username, props.room_uuid)
|
await sendRoomInvite(username, props.room_uuid)
|
||||||
@@ -67,7 +66,7 @@ async function submit() {
|
|||||||
emit('close')
|
emit('close')
|
||||||
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
errorMessage.value = err?.message || err || $t('shared-error');
|
errorMessage.value = translateError(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -41,8 +41,10 @@ import { updateSettings } from '../api/account'
|
|||||||
import { updateLocalUser } from '../store'
|
import { updateLocalUser } from '../store'
|
||||||
import type { User } from '../types'
|
import type { User } from '../types'
|
||||||
import { useFluent } from 'fluent-vue';
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { useErrorTranslator } from '../errors';
|
||||||
|
|
||||||
const { $t } = useFluent();
|
const { $t } = useFluent();
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
const props = defineProps<{ user: User | null }>()
|
const props = defineProps<{ user: User | null }>()
|
||||||
const emit = defineEmits(['close', 'updated'])
|
const emit = defineEmits(['close', 'updated'])
|
||||||
@@ -84,7 +86,7 @@ async function submit() {
|
|||||||
emit('updated')
|
emit('updated')
|
||||||
emit('close')
|
emit('close')
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
errorMessage.value = err?.message || $t('settings-error-failed')
|
errorMessage.value = translateError(err);
|
||||||
} finally {
|
} finally {
|
||||||
isSubmitting.value = false
|
isSubmitting.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,10 @@ import { refreshLocalUser } from '../store.ts';
|
|||||||
import { getAuthData } from '../store.ts';
|
import { getAuthData } from '../store.ts';
|
||||||
import { refreshAvatar } from '../store.ts';
|
import { refreshAvatar } from '../store.ts';
|
||||||
import { useFluent } from 'fluent-vue';
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { useErrorTranslator } from '../errors.ts';
|
||||||
|
|
||||||
const { $t } = useFluent();
|
const { $t } = useFluent();
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
const emit = defineEmits(['close', 'updated']);
|
const emit = defineEmits(['close', 'updated']);
|
||||||
|
|
||||||
@@ -166,7 +168,8 @@ async function handleUpload() {
|
|||||||
emit('close');
|
emit('close');
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("Upload failed:", err);
|
console.error("Upload failed:", err);
|
||||||
errorMessage.value = $t('settings-error-upload-avatar-failed-upload');
|
const msg = translateError(err);
|
||||||
|
errorMessage.value = msg !== 'An error occurred' ? msg : $t('settings-error-upload-avatar-failed-upload');
|
||||||
isSubmitting.value = false;
|
isSubmitting.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/errors.ts
Normal file
30
src/errors.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { ApiError } from './api/client';
|
||||||
|
|
||||||
|
export function useErrorTranslator() {
|
||||||
|
const { $t } = useFluent();
|
||||||
|
|
||||||
|
function translateError(err: unknown): string {
|
||||||
|
if (err instanceof ApiError) {
|
||||||
|
// Convert "AUTH_INVALID_CREDENTIALS" -> "error-auth-invalid-credentials"
|
||||||
|
const key = `error-${err.code.toLowerCase().replace(/_/g, '-')}`;
|
||||||
|
|
||||||
|
const translated = $t(key);
|
||||||
|
|
||||||
|
// Fallback to the message provided by backend.
|
||||||
|
if (translated === key) {
|
||||||
|
return err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err instanceof Error) {
|
||||||
|
return err.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $t('shared-error');
|
||||||
|
}
|
||||||
|
|
||||||
|
return { translateError };
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ auth-login-btn = Login
|
|||||||
auth-register-btn = Create Account
|
auth-register-btn = Create Account
|
||||||
auth-no-account = Don't have an account?
|
auth-no-account = Don't have an account?
|
||||||
auth-has-account = Already have an account?
|
auth-has-account = Already have an account?
|
||||||
auth-error-unknown = An unknown error occurred
|
|
||||||
auth-error-password-match = Passwords do not match
|
auth-error-password-match = Passwords do not match
|
||||||
auth-error-password-length = Password must be at least 8 characters long
|
auth-error-password-length = Password must be at least 8 characters long
|
||||||
auth-error-email-invalid = Please enter a valid email address
|
auth-error-email-invalid = Please enter a valid email address
|
||||||
@@ -130,3 +129,34 @@ shared-confirm = Confirm
|
|||||||
|
|
||||||
## Notifications
|
## Notifications
|
||||||
notifications-message-title = New {$messageType} message from {$senderUsername}
|
notifications-message-title = New {$messageType} message from {$senderUsername}
|
||||||
|
|
||||||
|
## Errors (backend)
|
||||||
|
error-auth-invalid-credentials = Invalid email or password.
|
||||||
|
error-auth-missing-token = Authentication missing.
|
||||||
|
error-auth-invalid-token = Session expired or invalid.
|
||||||
|
error-user-not-found = User not found.
|
||||||
|
error-user-email-taken = Email is already in use.
|
||||||
|
error-user-username-taken = Username is already taken.
|
||||||
|
error-user-username-length = Username must be 1-35 characters long.
|
||||||
|
error-user-invalid-email = Invalid email format.
|
||||||
|
error-user-password-too-short = Password must be at least 8 characters.
|
||||||
|
error-user-empty-fields = Required fields are empty.
|
||||||
|
error-avatar-not-found = Avatar not found.
|
||||||
|
error-room-not-found = Room not found.
|
||||||
|
error-room-name-length = Room name must be 1-35 characters long.
|
||||||
|
error-room-not-member = You are not a member of this room.
|
||||||
|
error-room-already-member = This person is already a member.
|
||||||
|
error-room-owner-cannot-leave = Owner cannot leave the room without transferring ownership.
|
||||||
|
error-room-global-no-members = Cannot list members for global rooms.
|
||||||
|
error-invite-self = You cannot invite yourself.
|
||||||
|
error-invite-already-sent = Invite already sent.
|
||||||
|
error-invite-not-found = Invite not found.
|
||||||
|
error-friend-request-self = You cannot friend request yourself.
|
||||||
|
error-friend-already-exists = You are already friends.
|
||||||
|
error-friend-request-already-sent = Friend request already pending.
|
||||||
|
error-friend-request-not-found = Friend request not found.
|
||||||
|
error-friend-not-found = User is not in your friends list.
|
||||||
|
error-internal-server-error = An error occured.
|
||||||
|
error-internal-db-error = An error occured.
|
||||||
|
error-file-too-large = The file is too large (max 2MB).
|
||||||
|
error-upload-failed = Failed to upload the file.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ auth-login-btn = Se connecter
|
|||||||
auth-register-btn = Créer un compte
|
auth-register-btn = Créer un compte
|
||||||
auth-no-account = Pas encore de compte ?
|
auth-no-account = Pas encore de compte ?
|
||||||
auth-has-account = Déjà un compte ?
|
auth-has-account = Déjà un compte ?
|
||||||
auth-error-unknown = Une erreur inconnue est survenue
|
|
||||||
auth-error-password-match = Les mots de passe ne correspondent pas
|
auth-error-password-match = Les mots de passe ne correspondent pas
|
||||||
auth-error-password-length = Le mot de passe doit faire au moins 8 caractères
|
auth-error-password-length = Le mot de passe doit faire au moins 8 caractères
|
||||||
auth-error-email-invalid = Veuillez entrer une adresse email valide
|
auth-error-email-invalid = Veuillez entrer une adresse email valide
|
||||||
@@ -128,3 +127,34 @@ shared-confirm = Confirmer
|
|||||||
|
|
||||||
## Notifications
|
## Notifications
|
||||||
notifications-message-title = Nouveau message {$messageType} de {$senderUsername}
|
notifications-message-title = Nouveau message {$messageType} de {$senderUsername}
|
||||||
|
|
||||||
|
## Errors (backend)
|
||||||
|
error-auth-invalid-credentials = Email ou mot de passe incorrect.
|
||||||
|
error-auth-missing-token = Authentification manquante.
|
||||||
|
error-auth-invalid-token = Session expirée ou invalide.
|
||||||
|
error-user-not-found = Utilisateur introuvable.
|
||||||
|
error-user-email-taken = L'adresse email est déjà utilisée.
|
||||||
|
error-user-username-taken = Ce nom d'utilisateur est déjà pris.
|
||||||
|
error-user-username-length = Le nom d'utilisateur doit faire 1-35 caractères.
|
||||||
|
error-user-invalid-email = Format d'email invalide.
|
||||||
|
error-user-password-too-short = Le mot de passe doit faire au moins 8 caractères.
|
||||||
|
error-user-empty-fields = Des champs requis sont vides.
|
||||||
|
error-avatar-not-found = Avatar introuvable.
|
||||||
|
error-room-not-found = Salon introuvable.
|
||||||
|
error-room-name-length = Le nom de la salle doit faire 1-35 caractères.
|
||||||
|
error-room-not-member = Vous n'êtes pas membre de ce salon.
|
||||||
|
error-room-already-member = Cette personne est déjà membre.
|
||||||
|
error-room-owner-cannot-leave = Le propriétaire ne peut pas quitter le salon sans transférer la propriété.
|
||||||
|
error-room-global-no-members = Impossible de lister les membres d'un salon global.
|
||||||
|
error-invite-self = Vous ne pouvez pas vous inviter vous-même.
|
||||||
|
error-invite-already-sent = Invitation déjà envoyée.
|
||||||
|
error-invite-not-found = Invitation introuvable.
|
||||||
|
error-friend-request-self = Vous ne pouvez pas vous ajouter en ami.
|
||||||
|
error-friend-already-exists = Vous êtes déjà amis.
|
||||||
|
error-friend-request-already-sent = Demande d'ami déjà en attente.
|
||||||
|
error-friend-request-not-found = Demande d'ami introuvable.
|
||||||
|
error-friend-not-found = L'utilisateur n'est pas dans votre liste d'amis.
|
||||||
|
error-internal-server-error = Une erreur est survenue.
|
||||||
|
error-internal-db-error = Une erreur est survenue.
|
||||||
|
error-file-too-large = Le fichier est trop volumineux (max 2Mo).
|
||||||
|
error-upload-failed = Erreur lors de l'envoi du fichier.
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ async function init() {
|
|||||||
|
|
||||||
init()
|
init()
|
||||||
|
|
||||||
// export const API = 'http://127.0.0.1:8080'
|
export const API = 'http://127.0.0.1:8080'
|
||||||
// export const API = 'http://192.168.1.183:8080'
|
// export const API = 'http://192.168.1.183:8080'
|
||||||
export const API = 'https://alatreon.org/frangipane'
|
// export const API = 'https://alatreon.org/frangipane'
|
||||||
// export const API_WS = 'ws://127.0.0.1:8080/ws'
|
export const API_WS = 'ws://127.0.0.1:8080/ws'
|
||||||
// export const API_WS = 'ws://192.168.1.183:8080/ws'
|
// export const API_WS = 'ws://192.168.1.183:8080/ws'
|
||||||
export const API_WS = 'wss://alatreon.org/frangipane/ws'
|
// export const API_WS = 'wss://alatreon.org/frangipane/ws'
|
||||||
|
|||||||
@@ -50,12 +50,15 @@ import type { Friend } from '../types'
|
|||||||
import { getAvatarUrl } from '../store'
|
import { getAvatarUrl } from '../store'
|
||||||
import defaultAvatar from '../assets/default-avatar.png'
|
import defaultAvatar from '../assets/default-avatar.png'
|
||||||
import UserProfileModal from '../components/UserProfileModal.vue'
|
import UserProfileModal from '../components/UserProfileModal.vue'
|
||||||
|
import { useErrorTranslator } from '../errors'
|
||||||
|
|
||||||
const friends = ref<Friend[]>([])
|
const friends = ref<Friend[]>([])
|
||||||
const username = ref('')
|
const username = ref('')
|
||||||
const errorMessage = ref('')
|
const errorMessage = ref('')
|
||||||
const isLoading = ref(true)
|
const isLoading = ref(true)
|
||||||
|
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
const selectedFriend = ref<Friend | null>(null)
|
const selectedFriend = ref<Friend | null>(null)
|
||||||
|
|
||||||
async function loadFriends() {
|
async function loadFriends() {
|
||||||
@@ -91,7 +94,7 @@ async function send() {
|
|||||||
errorMessage.value = ''
|
errorMessage.value = ''
|
||||||
await loadFriends()
|
await loadFriends()
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
errorMessage.value = err
|
errorMessage.value = translateError(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -143,7 +146,6 @@ async function send() {
|
|||||||
.friends-list {
|
.friends-list {
|
||||||
position: relative;
|
position: relative;
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
min-height: 200px;
|
|
||||||
background: var(--panel);
|
background: var(--panel);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { ref } from "vue";
|
|||||||
import { login } from '../store.ts'
|
import { login } from '../store.ts'
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useFluent } from 'fluent-vue';
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { useErrorTranslator } from "../errors.ts";
|
||||||
|
|
||||||
const email = ref("");
|
const email = ref("");
|
||||||
const password = ref("");
|
const password = ref("");
|
||||||
@@ -32,6 +33,7 @@ const errorMessage = ref("");
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { $t } = useFluent();
|
const { $t } = useFluent();
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
errorMessage.value = "";
|
errorMessage.value = "";
|
||||||
@@ -39,7 +41,8 @@ async function submit() {
|
|||||||
await login(email.value, "", password.value);
|
await login(email.value, "", password.value);
|
||||||
router.push("/");
|
router.push("/");
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
errorMessage.value = err?.message || $t('auth-error-unknown');
|
errorMessage.value = translateError(err);
|
||||||
|
// errorMessage.value = err?.message || $t('auth-error-unknown');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -47,8 +47,10 @@ import { fetchFriendRequests, acceptFriendRequest, declineFriendRequest } from '
|
|||||||
import { fetchRoomInvites, acceptRoomInvite, declineRoomInvite } from '../api/rooms.ts'
|
import { fetchRoomInvites, acceptRoomInvite, declineRoomInvite } from '../api/rooms.ts'
|
||||||
import { useNotifications } from '../store'
|
import { useNotifications } from '../store'
|
||||||
import { useFluent } from 'fluent-vue';
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { useErrorTranslator } from '../errors.ts';
|
||||||
|
|
||||||
const { $t } = useFluent();
|
const { $t } = useFluent();
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
const errorMessage = ref('')
|
const errorMessage = ref('')
|
||||||
const { requests, invites, refreshNotifications } = useNotifications()
|
const { requests, invites, refreshNotifications } = useNotifications()
|
||||||
@@ -65,7 +67,8 @@ async function acceptFriend(senderUuid: string) {
|
|||||||
requests.value = requests.value.filter(r => r.sender_uuid !== senderUuid)
|
requests.value = requests.value.filter(r => r.sender_uuid !== senderUuid)
|
||||||
// fetchFriends().then(f => (friends.value = f))
|
// fetchFriends().then(f => (friends.value = f))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorMessage.value = $t('notifications-error-friend-accept')
|
const msg = translateError(err);
|
||||||
|
errorMessage.value = msg !== $t('shared-error') ? msg : $t('notifications-error-friend-accept')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +78,8 @@ async function declineFriend(senderUuid: string) {
|
|||||||
requests.value = requests.value.filter(r => r.sender_uuid !== senderUuid)
|
requests.value = requests.value.filter(r => r.sender_uuid !== senderUuid)
|
||||||
// fetchFriends().then(f => (friends.value = f))
|
// fetchFriends().then(f => (friends.value = f))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorMessage.value = $t('notifications-error-friend-decline')
|
const msg = translateError(err);
|
||||||
|
errorMessage.value = msg !== $t('shared-error') ? msg : $t('notifications-error-friend-decline')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +88,8 @@ async function acceptRoom(senderUuid: string, roomUuid: string) {
|
|||||||
await acceptRoomInvite(senderUuid, roomUuid)
|
await acceptRoomInvite(senderUuid, roomUuid)
|
||||||
invites.value = invites.value.filter(r => r.room_uuid !== roomUuid)
|
invites.value = invites.value.filter(r => r.room_uuid !== roomUuid)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorMessage.value = $t('notifications-error-room-accept')
|
const msg = translateError(err);
|
||||||
throw err
|
errorMessage.value = msg !== $t('shared-error') ? msg : $t('notifications-error-room-accept')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,8 +98,8 @@ async function declineRoom(senderUuid: string, roomUuid: string) {
|
|||||||
await declineRoomInvite(senderUuid, roomUuid)
|
await declineRoomInvite(senderUuid, roomUuid)
|
||||||
invites.value = invites.value.filter(r => r.room_uuid !== roomUuid)
|
invites.value = invites.value.filter(r => r.room_uuid !== roomUuid)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
errorMessage.value = $t('notifications-error-room-decline')
|
const msg = translateError(err);
|
||||||
throw err
|
errorMessage.value = msg !== $t('shared-error') ? msg : $t('notifications-error-room-decline')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<button type="submit">{{ $t('auth-register-btn') }}</button>
|
<button type="submit">{{ $t('auth-register-btn') }}</button>
|
||||||
|
|
||||||
<p class="login-link">
|
<p class="login-link">
|
||||||
{{ $t('auth-has-settings') }} <router-link to="/login">{{ $t('auth-login-title') }}</router-link>
|
{{ $t('auth-has-account') }} <router-link to="/login">{{ $t('auth-login-title') }}</router-link>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
<p v-if="errorMessage" class="error-message">{{ errorMessage }}</p>
|
||||||
@@ -35,8 +35,10 @@ import { ref } from "vue";
|
|||||||
import { register } from '../store.ts'
|
import { register } from '../store.ts'
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useFluent } from 'fluent-vue';
|
import { useFluent } from 'fluent-vue';
|
||||||
|
import { useErrorTranslator } from '../errors';
|
||||||
|
|
||||||
const { $t } = useFluent();
|
const { $t } = useFluent();
|
||||||
|
const { translateError } = useErrorTranslator();
|
||||||
|
|
||||||
const email = ref("");
|
const email = ref("");
|
||||||
const username = ref("");
|
const username = ref("");
|
||||||
@@ -51,17 +53,15 @@ async function submit(event: Event) {
|
|||||||
|
|
||||||
const form = event.target as HTMLFormElement;
|
const form = event.target as HTMLFormElement;
|
||||||
|
|
||||||
// Check password length and email
|
// if (!form.checkValidity()) {
|
||||||
if (!form.checkValidity()) {
|
// if (password.value.length < 8) {
|
||||||
if (password.value.length < 8) {
|
// errorMessage.value = $t('auth-error-password-length');
|
||||||
errorMessage.value = $t('auth-error-password-length');
|
// } else {
|
||||||
} else {
|
// errorMessage.value = $t('auth-error-email-invalid');
|
||||||
errorMessage.value = $t('auth-error-email-invalid');
|
// }
|
||||||
}
|
// return;
|
||||||
return;
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
// Check password match
|
|
||||||
if (password.value !== confirmPassword.value) {
|
if (password.value !== confirmPassword.value) {
|
||||||
errorMessage.value = $t('auth-error-password-match');
|
errorMessage.value = $t('auth-error-password-match');
|
||||||
return;
|
return;
|
||||||
@@ -71,7 +71,7 @@ async function submit(event: Event) {
|
|||||||
await register(email.value, username.value, password.value);
|
await register(email.value, username.value, password.value);
|
||||||
router.push("/");
|
router.push("/");
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
errorMessage.value = err?.message || "An unknown error occurred";
|
errorMessage.value = translateError(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user