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