From 210ab43a0b5bc6dec65afde16acb6b142a69b42f Mon Sep 17 00:00:00 2001 From: igor Date: Fri, 13 Feb 2026 22:01:40 +0100 Subject: [PATCH] fixed response data for login, fixed tabs --- AGENTS.md | 13 +- frontend/src/views/AuthView.vue | 296 +++++++++++++++----------------- 2 files changed, 152 insertions(+), 157 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 742a4b8..367c9fe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,6 +25,8 @@ It describes what the project is, what is already implemented, and what still ne - `frontend/src/router/index.ts` maps `/` to `frontend/src/views/AuthView.vue`. - `AuthView` serves as login + registration entry (single form, email + password). - Successful login stores `token` and `user_email` in `localStorage`. + - `frontend/src/views/AuthView.vue` formatting now uses tab-based indentation. + - Login response parsing in `AuthView` now reads user fields from `response.data.user`. - Frontend i18n is wired: - setup in `frontend/src/i18n/index.ts` - locale files in `frontend/src/locales/{sk,cs,en,es,de}.ts` @@ -34,8 +36,7 @@ It describes what the project is, what is already implemented, and what still ne - design tokens in `frontend/src/assets/css/style.css` (`:root` variables). - App logo is served from `frontend/public/Nutrio.png` (copied from `doc/Nutrio.png`). - Font Awesome is installed and registered globally in `frontend/src/main.ts`. -- `frontend/src/BackendAPI.js` is generated via `backend/scripts/buildTypeScript.php` and should not be edited manually. -- `frontend/src/BackendAPI.d.ts` provides TS declarations for generated `BackendAPI.js`. +- `frontend/src/BackendAPI.ts` is generated via `backend/scripts/buildTypeScript.php` and should not be edited manually. - `backend/data.json` contains sample meal data (not currently wired into DB/API flow). ## Backend Architecture @@ -139,8 +140,11 @@ All actions are invoked through `backend/public/API.php` with `?action= { - return SUPPORTED_LOCALES.includes(value as AppLocale) + return SUPPORTED_LOCALES.includes(value as AppLocale) } const setLocale = (value: string) => { - if (!isSupportedLocale(value)) { - return - } - i18n.global.locale.value = value - document.documentElement.setAttribute('lang', value) - localStorage.setItem('locale', value) + if (!isSupportedLocale(value)) { + return + } + i18n.global.locale.value = value + document.documentElement.setAttribute('lang', value) + localStorage.setItem('locale', value) } const localeValue = computed({ - get: () => i18n.global.locale.value as AppLocale, - set: (value: string) => setLocale(value), + get: () => i18n.global.locale.value as AppLocale, + set: (value: string) => setLocale(value), }) watch( - () => i18n.global.locale.value, - (nextLocale) => { - document.documentElement.setAttribute('lang', nextLocale) - }, - { immediate: true }, + () => i18n.global.locale.value, + (nextLocale) => { + document.documentElement.setAttribute('lang', nextLocale) + }, + { immediate: true }, ) const getInitialTheme = (): ThemeMode => { - const storedTheme = localStorage.getItem('theme') - return storedTheme === 'dark' ? 'dark' : 'light' + const storedTheme = localStorage.getItem('theme') + return storedTheme === 'dark' ? 'dark' : 'light' } const theme = ref(getInitialTheme()) const applyTheme = (nextTheme: ThemeMode) => { - theme.value = nextTheme - document.documentElement.setAttribute('data-theme', nextTheme) - localStorage.setItem('theme', nextTheme) + theme.value = nextTheme + document.documentElement.setAttribute('data-theme', nextTheme) + localStorage.setItem('theme', nextTheme) } applyTheme(theme.value) const toggleTheme = () => { - applyTheme(theme.value === 'dark' ? 'light' : 'dark') + applyTheme(theme.value === 'dark' ? 'light' : 'dark') } const isDarkMode = computed(() => theme.value === 'dark') const themeLabel = computed(() => { - return isDarkMode.value ? t('theme.dark') : t('theme.light') + return isDarkMode.value ? t('theme.dark') : t('theme.light') }) const submitLabel = computed(() => { - return isLoading.value ? t('auth.submitting') : t('auth.submit') + return isLoading.value ? t('auth.submitting') : t('auth.submit') }) const mapApiError = (error: unknown): string => { - if (typeof error !== 'string') { - return t('auth.errors.loginFailed') - } - if (error === 'Invalid email or password') { - return t('auth.errors.invalidCredentials') - } - if (error === 'Invalid email format') { - return t('auth.errors.invalidEmail') - } - return t('auth.errors.loginFailed') + if (typeof error !== 'string') { + return t('auth.errors.loginFailed') + } + if (error === 'Invalid email or password') { + return t('auth.errors.invalidCredentials') + } + if (error === 'Invalid email format') { + return t('auth.errors.invalidEmail') + } + return t('auth.errors.loginFailed') } const submitForm = async () => { - errorMessage.value = '' - successMessage.value = '' + errorMessage.value = '' + successMessage.value = '' - const normalizedEmail = email.value.trim().toLowerCase() - const normalizedPassword = password.value + const normalizedEmail = email.value.trim().toLowerCase() + const normalizedPassword = password.value - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ - if (!emailRegex.test(normalizedEmail)) { - errorMessage.value = t('auth.errors.invalidEmail') - return - } + if (!emailRegex.test(normalizedEmail)) { + errorMessage.value = t('auth.errors.invalidEmail') + return + } - if (normalizedPassword.length <= 0) { - errorMessage.value = t('auth.errors.passwordRequired') - return - } + if (normalizedPassword.length <= 0) { + errorMessage.value = t('auth.errors.passwordRequired') + return + } - isLoading.value = true - try { - const response = (await BackendAPI.userLogin(normalizedEmail, normalizedPassword)) as LoginResponse - const token = response.user?.token ?? null - const userEmail = response.user?.email ?? normalizedEmail + isLoading.value = true + try { + const response = (await BackendAPI.userLogin( + normalizedEmail, + normalizedPassword, + )) as LoginResponse + const token = response.data?.user?.token ?? null + const userEmail = response.data?.user?.email ?? normalizedEmail + console.log(response) + if (token) { + localStorage.setItem('token', token) + } else { + localStorage.removeItem('token') + } + localStorage.setItem('user_email', userEmail) - if (token) { - localStorage.setItem('token', token) - } else { - localStorage.removeItem('token') - } - localStorage.setItem('user_email', userEmail) + successMessage.value = response.auto_registered + ? t('auth.successAutoRegistered') + : t('auth.successLoggedIn') - successMessage.value = response.auto_registered - ? t('auth.successAutoRegistered') - : t('auth.successLoggedIn') - - email.value = normalizedEmail - password.value = '' - showPassword.value = false - } catch (error) { - errorMessage.value = mapApiError(error) - } finally { - isLoading.value = false - } + email.value = normalizedEmail + password.value = '' + showPassword.value = false + } catch (error) { + errorMessage.value = mapApiError(error) + } finally { + isLoading.value = false + } } + + + + + \ No newline at end of file