fix: align frontend types and forms with api_yal backend (name→first_name+last_name, token→access_token)
This commit is contained in:
@@ -31,8 +31,7 @@
|
||||
<span v-if="notifCount" class="badge">{{ notifCount }}</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/profile" class="header__profile">
|
||||
<img v-if="user?.avatar" :src="user.avatar" alt="" class="avatar avatar--sm" />
|
||||
<span v-else class="avatar avatar--sm header__avatar-placeholder">{{ userInitials }}</span>
|
||||
<span class="avatar avatar--sm header__avatar-placeholder">{{ userInitials }}</span>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -62,8 +61,8 @@ const menuOpen = ref(false)
|
||||
const notifCount = ref(0)
|
||||
|
||||
const userInitials = computed(() => {
|
||||
if (!user.value?.name) return '?'
|
||||
return user.value.name.charAt(0).toUpperCase()
|
||||
if (!user.value?.full_name) return '?'
|
||||
return user.value.full_name.charAt(0).toUpperCase()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -12,11 +12,10 @@ export const useAuth = () => {
|
||||
}
|
||||
|
||||
const register = async (data: {
|
||||
name: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
email: string
|
||||
password: string
|
||||
password_confirm: string
|
||||
phone?: string
|
||||
}) => {
|
||||
await authStore.register(data)
|
||||
}
|
||||
|
||||
@@ -7,14 +7,27 @@
|
||||
<div class="form-group">
|
||||
<label class="form-label">Имя</label>
|
||||
<input
|
||||
v-model="name"
|
||||
v-model="firstName"
|
||||
type="text"
|
||||
class="form-input"
|
||||
:class="{ 'form-input--error': errors.name }"
|
||||
:class="{ 'form-input--error': errors.firstName }"
|
||||
placeholder="Ваше имя"
|
||||
required
|
||||
/>
|
||||
<span v-if="errors.name" class="form-error">{{ errors.name }}</span>
|
||||
<span v-if="errors.firstName" class="form-error">{{ errors.firstName }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Фамилия</label>
|
||||
<input
|
||||
v-model="lastName"
|
||||
type="text"
|
||||
class="form-input"
|
||||
:class="{ 'form-input--error': errors.lastName }"
|
||||
placeholder="Ваша фамилия"
|
||||
required
|
||||
/>
|
||||
<span v-if="errors.lastName" class="form-error">{{ errors.lastName }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@@ -30,16 +43,6 @@
|
||||
<span v-if="errors.email" class="form-error">{{ errors.email }}</span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Телефон</label>
|
||||
<input
|
||||
v-model="phone"
|
||||
type="tel"
|
||||
class="form-input"
|
||||
placeholder="+7 (XXX) XXX-XX-XX"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Пароль</label>
|
||||
<input
|
||||
@@ -91,13 +94,14 @@ definePageMeta({
|
||||
middleware: 'guest',
|
||||
})
|
||||
|
||||
const name = ref('')
|
||||
const firstName = ref('')
|
||||
const lastName = ref('')
|
||||
const email = ref('')
|
||||
const phone = ref('')
|
||||
const password = ref('')
|
||||
const passwordConfirm = ref('')
|
||||
const errors = reactive({
|
||||
name: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
email: '',
|
||||
password: '',
|
||||
passwordConfirm: '',
|
||||
@@ -108,13 +112,15 @@ const loading = ref(false)
|
||||
const { register } = useAuth()
|
||||
|
||||
async function handleRegister() {
|
||||
errors.name = ''
|
||||
errors.firstName = ''
|
||||
errors.lastName = ''
|
||||
errors.email = ''
|
||||
errors.password = ''
|
||||
errors.passwordConfirm = ''
|
||||
apiError.value = ''
|
||||
|
||||
if (!name.value) { errors.name = 'Введите имя'; return }
|
||||
if (!firstName.value) { errors.firstName = 'Введите имя'; return }
|
||||
if (!lastName.value) { errors.lastName = 'Введите фамилию'; return }
|
||||
if (!email.value) { errors.email = 'Введите email'; return }
|
||||
if (!password.value || password.value.length < 6) {
|
||||
errors.password = 'Пароль минимум 6 символов'
|
||||
@@ -128,11 +134,10 @@ async function handleRegister() {
|
||||
loading.value = true
|
||||
try {
|
||||
await register({
|
||||
name: name.value,
|
||||
first_name: firstName.value,
|
||||
last_name: lastName.value,
|
||||
email: email.value,
|
||||
password: password.value,
|
||||
password_confirm: passwordConfirm.value,
|
||||
phone: phone.value || undefined,
|
||||
})
|
||||
navigateTo('/')
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -18,13 +18,12 @@
|
||||
<template v-else-if="user">
|
||||
<div class="profile__header">
|
||||
<div class="profile__avatar">
|
||||
<img v-if="user.avatar" :src="user.avatar" alt="" class="avatar avatar--lg" />
|
||||
<span v-else class="avatar avatar--lg profile__avatar-placeholder">
|
||||
<span class="avatar avatar--lg profile__avatar-placeholder">
|
||||
{{ userInitials }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="profile__info">
|
||||
<h2>{{ user.name }}</h2>
|
||||
<h2>{{ user.full_name }}</h2>
|
||||
<p class="body-text--gray">{{ user.email }}</p>
|
||||
<span class="tag" style="margin-top: 8px">
|
||||
{{ user.role === 'admin' ? 'Администратор' : user.role === 'moderator' ? 'Модератор' : 'Пользователь' }}
|
||||
@@ -82,8 +81,8 @@ const reviewsCount = ref(0)
|
||||
const favoritesCount = ref(0)
|
||||
|
||||
const userInitials = computed(() => {
|
||||
if (!user.value?.name) return '?'
|
||||
return user.value.name.charAt(0).toUpperCase()
|
||||
if (!user.value?.full_name) return '?'
|
||||
return user.value.full_name.charAt(0).toUpperCase()
|
||||
})
|
||||
|
||||
function handleLogout() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { User, LoginRequest, RegisterRequest } from '~/types'
|
||||
import type { User, LoginRequest, RegisterRequest, AuthResponse } from '~/types'
|
||||
|
||||
interface AuthState {
|
||||
user: User | null
|
||||
@@ -23,8 +23,8 @@ export const useAuthStore = defineStore('auth', {
|
||||
this.loading = true
|
||||
try {
|
||||
const api = useApi()
|
||||
const response = await api.post<{ access_token: string; user: User }>('/auth/login', { email, password })
|
||||
this.token = response.access_token
|
||||
const response = await api.post<AuthResponse>('/auth/login', { email, password })
|
||||
this.token = response.token
|
||||
this.user = response.user
|
||||
await this.fetchUser()
|
||||
} finally {
|
||||
@@ -36,8 +36,8 @@ export const useAuthStore = defineStore('auth', {
|
||||
this.loading = true
|
||||
try {
|
||||
const api = useApi()
|
||||
const response = await api.post<{ access_token: string; user: User }>('/auth/register', data)
|
||||
this.token = response.access_token
|
||||
const response = await api.post<AuthResponse>('/auth/register', data)
|
||||
this.token = response.token
|
||||
this.user = response.user
|
||||
} finally {
|
||||
this.loading = false
|
||||
@@ -48,7 +48,8 @@ export const useAuthStore = defineStore('auth', {
|
||||
if (!this.token) return
|
||||
try {
|
||||
const api = useApi()
|
||||
this.user = await api.get<User>('/me')
|
||||
const profile = await api.get<Partial<User>>('/me')
|
||||
this.user = this.user ? { ...this.user, ...profile } : (profile as User)
|
||||
} catch {
|
||||
this.token = null
|
||||
this.user = null
|
||||
@@ -58,8 +59,8 @@ export const useAuthStore = defineStore('auth', {
|
||||
async refreshToken(): Promise<boolean> {
|
||||
try {
|
||||
const api = useApi()
|
||||
const response = await api.post<{ access_token: string }>('/auth/refresh')
|
||||
this.token = response.access_token
|
||||
const response = await api.post<{ token: string }>('/auth/refresh')
|
||||
this.token = response.token
|
||||
return true
|
||||
} catch {
|
||||
this.token = null
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
export interface User {
|
||||
id: number
|
||||
name: string
|
||||
email: string
|
||||
phone?: string
|
||||
avatar?: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
full_name: string
|
||||
role: 'user' | 'admin' | 'moderator'
|
||||
phone?: string
|
||||
city?: string
|
||||
created_at?: string
|
||||
updated_at?: string
|
||||
}
|
||||
|
||||
export interface AuthTokens {
|
||||
access_token: string
|
||||
refresh_token?: string
|
||||
token: string
|
||||
expires_at: string
|
||||
}
|
||||
|
||||
export interface LoginRequest {
|
||||
@@ -19,11 +22,10 @@ export interface LoginRequest {
|
||||
}
|
||||
|
||||
export interface RegisterRequest {
|
||||
name: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
email: string
|
||||
password: string
|
||||
password_confirm: string
|
||||
phone?: string
|
||||
}
|
||||
|
||||
export interface ResetPasswordRequest {
|
||||
@@ -98,6 +100,12 @@ export interface Review {
|
||||
comments_count?: number
|
||||
}
|
||||
|
||||
export interface AuthResponse {
|
||||
token: string
|
||||
expires_at: string
|
||||
user: User
|
||||
}
|
||||
|
||||
export interface ApiError {
|
||||
message: string
|
||||
errors?: Record<string, string[]>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"agent": {
|
||||
"build": {
|
||||
"temperature": 0.4
|
||||
|
||||
Reference in New Issue
Block a user