🔧 refactor(api): исправляет интерфейсы и убирает ненужные приведения типов в API запросах
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { City, Greeting, Tag } from '@/composables/useUi'
|
||||
import { onMounted } from 'vue'
|
||||
import { apiClient } from '@/api/client'
|
||||
import AppToast from '@/components/common/AppToast.vue'
|
||||
@@ -29,9 +28,9 @@ async function loadReferences() {
|
||||
return
|
||||
try {
|
||||
const [tags, cities, greetings] = await Promise.all([
|
||||
apiClient.api.tagsControllerFindAll() as unknown as Tag[],
|
||||
apiClient.api.citiesControllerFindAll() as unknown as City[],
|
||||
apiClient.api.greetingsControllerFindAll() as unknown as Greeting[],
|
||||
apiClient.api.tagsControllerFindAll(),
|
||||
apiClient.api.citiesControllerFindAll(),
|
||||
apiClient.api.greetingsControllerFindAll(),
|
||||
])
|
||||
uiStore.setTags(tags)
|
||||
uiStore.setCities(cities)
|
||||
|
||||
@@ -232,7 +232,7 @@ export interface DateStatusDto {
|
||||
|
||||
export interface DateWithStatusDto {
|
||||
date: DateDto;
|
||||
date_status?: DateStatusDto | null;
|
||||
dateStatus?: DateStatusDto | null;
|
||||
}
|
||||
|
||||
export interface UpdateDateStatusDto {
|
||||
@@ -833,7 +833,16 @@ export class Api<SecurityDataType extends unknown> {
|
||||
* @secure
|
||||
*/
|
||||
feedControllerGetFeed: (query: FeedControllerGetFeedParams, params: RequestParams = {}) =>
|
||||
this.http.request<ProfileResponseDto[], any>({
|
||||
this.http.request<
|
||||
{
|
||||
items: ProfileResponseDto[];
|
||||
/** @example 1 */
|
||||
page: number;
|
||||
/** @example 20 */
|
||||
limit: number;
|
||||
},
|
||||
any
|
||||
>({
|
||||
path: `/api/v1/feed`,
|
||||
method: "GET",
|
||||
query: query,
|
||||
|
||||
@@ -46,7 +46,7 @@ axiosInstance.interceptors.response.use(
|
||||
async (error) => {
|
||||
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean }
|
||||
|
||||
if (error.response?.status === 401 && !originalRequest._retry) {
|
||||
if (error.response?.status === 401 && !originalRequest._retry && !originalRequest.url?.includes('/auth/refresh')) {
|
||||
if (_isRefreshing) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_failedQueue.push({ resolve, reject })
|
||||
@@ -68,11 +68,11 @@ axiosInstance.interceptors.response.use(
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await axios.post<{ data: { accessToken: string, refreshToken: string } }>(
|
||||
const res = await axiosInstance.post<{ accessToken: string, refreshToken: string }>(
|
||||
`${BASE_URL}/api/v1/auth/refresh`,
|
||||
{ refreshToken },
|
||||
)
|
||||
const { accessToken, refreshToken: newRefresh } = res.data.data
|
||||
const { accessToken, refreshToken: newRefresh } = res.data
|
||||
_setAccessToken(accessToken)
|
||||
localStorage.setItem('refreshToken', newRefresh)
|
||||
_processQueue(null, accessToken)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="card-stack">
|
||||
{{ feedStore.cards }}
|
||||
<!-- {{ feedStore }} -->
|
||||
<div v-if="feedStore.loading && feedStore.cards.length === 0" class="card-stack__loading">
|
||||
<LoadingSpinner size="lg" />
|
||||
</div>
|
||||
|
||||
@@ -106,7 +106,7 @@ watch(() => filters.cityId, async (cityId) => {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await apiClient.api.citiesControllerFindDistricts(cityId) as unknown as District[]
|
||||
const res = await apiClient.api.citiesControllerFindDistricts(cityId)
|
||||
uiStore.setDistricts(cityId, res)
|
||||
districts.value = res
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ watch(() => form.cityId, async (cityId) => {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await apiClient.api.citiesControllerFindDistricts(cityId) as unknown as District[]
|
||||
const res = await apiClient.api.citiesControllerFindDistricts(cityId)
|
||||
uiStore.setDistricts(cityId, res)
|
||||
districts.value = res
|
||||
}
|
||||
|
||||
@@ -1,32 +1,9 @@
|
||||
import type { LoginDto, MediaItemDto, RegisterDto, TagDto } from '@/api/api'
|
||||
import type { LoginDto, MeResponseDto, ProfileResponseDto, RegisterDto } from '@/api/api'
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { _clearAuth, _setAccessToken, apiClient } from '@/api/client'
|
||||
|
||||
export interface UserProfile {
|
||||
id: string
|
||||
userId: string
|
||||
name: string
|
||||
birthDate: string
|
||||
gender: 'male' | 'female'
|
||||
cityId?: string | null
|
||||
districtId?: string | null
|
||||
description?: string | null
|
||||
nation?: string | null
|
||||
height?: number | null
|
||||
weight?: number | null
|
||||
activeChatId?: string | null
|
||||
tags: TagDto[]
|
||||
media: MediaItemDto[]
|
||||
}
|
||||
|
||||
export interface AuthUser {
|
||||
id: string
|
||||
phone: string
|
||||
status: 'active' | 'banned' | 'pending'
|
||||
roleId?: string | null
|
||||
role?: { id: string, name: string } | null
|
||||
profiles: UserProfile[]
|
||||
}
|
||||
export type UserProfile = ProfileResponseDto
|
||||
export type AuthUser = Omit<MeResponseDto, 'profiles'> & { profiles: UserProfile[] }
|
||||
|
||||
const user = ref<AuthUser | null>(null)
|
||||
const activeProfileId = ref<string | null>(null)
|
||||
@@ -40,20 +17,14 @@ const activeProfile = computed(() =>
|
||||
const hasProfiles = computed(() => profiles.value.length > 0)
|
||||
|
||||
async function login(dto: LoginDto) {
|
||||
const res = await apiClient.api.authControllerLogin(dto) as unknown as {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
}
|
||||
const res = await apiClient.api.authControllerLogin(dto)
|
||||
_setAccessToken(res.accessToken)
|
||||
localStorage.setItem('refreshToken', res.refreshToken)
|
||||
await fetchMe()
|
||||
}
|
||||
|
||||
async function register(dto: RegisterDto) {
|
||||
const res = await apiClient.api.authControllerRegister(dto) as unknown as {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
}
|
||||
const res = await apiClient.api.authControllerRegister(dto)
|
||||
_setAccessToken(res.accessToken)
|
||||
localStorage.setItem('refreshToken', res.refreshToken)
|
||||
await fetchMe()
|
||||
@@ -76,10 +47,9 @@ async function fetchMe() {
|
||||
apiClient.api.usersControllerGetMe(),
|
||||
apiClient.api.profilesControllerGetMyProfiles(),
|
||||
])
|
||||
const fullProfiles = profilesRes as unknown as UserProfile[]
|
||||
user.value = { ...meRes, profiles: fullProfiles } as unknown as AuthUser
|
||||
if (fullProfiles.length > 0 && !activeProfileId.value) {
|
||||
activeProfileId.value = fullProfiles[0].id
|
||||
user.value = { ...meRes, profiles: profilesRes }
|
||||
if (profilesRes.length > 0 && !activeProfileId.value) {
|
||||
activeProfileId.value = profilesRes[0].id
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { SendMessageDto } from '@/api/api'
|
||||
import type { ChatDto, MessageDto, SendMessageDto } from '@/api/api'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { apiClient } from '@/api/client'
|
||||
|
||||
@@ -8,26 +8,14 @@ export interface ChatProfile {
|
||||
avatarUrl?: string
|
||||
}
|
||||
|
||||
export interface Chat {
|
||||
id: string
|
||||
profile1Id: string
|
||||
profile2Id: string
|
||||
status: 'active' | 'closed'
|
||||
export type Chat = ChatDto & {
|
||||
partner?: ChatProfile
|
||||
lastMessage?: ChatMessage
|
||||
lastMessage?: MessageDto
|
||||
unreadCount?: number
|
||||
createdAt?: string
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string
|
||||
chatId: string
|
||||
profileId: string
|
||||
text?: string
|
||||
mediaUrl?: string
|
||||
mediaType?: 'photo' | 'voice' | 'video'
|
||||
createdAt: string
|
||||
}
|
||||
export type ChatMessage = MessageDto
|
||||
|
||||
// Polling interval — replace with WebSocket when backend supports it
|
||||
const POLL_INTERVAL = 2000
|
||||
@@ -39,14 +27,14 @@ const pollingTimer = ref<ReturnType<typeof setInterval> | null>(null)
|
||||
const loading = ref(false)
|
||||
|
||||
async function fetchChats(profileId: string) {
|
||||
const res = await apiClient.api.chatControllerGetChats({ profileId }) as unknown as Chat[]
|
||||
const res = await apiClient.api.chatControllerGetChats({ profileId })
|
||||
chats.value = res
|
||||
}
|
||||
|
||||
async function fetchMessages(chatId: string, profileId: string) {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await apiClient.api.chatControllerGetMessages({ chatId, profileId }) as unknown as ChatMessage[]
|
||||
const res = await apiClient.api.chatControllerGetMessages({ chatId, profileId })
|
||||
messages.value = res
|
||||
}
|
||||
finally {
|
||||
@@ -55,13 +43,13 @@ async function fetchMessages(chatId: string, profileId: string) {
|
||||
}
|
||||
|
||||
async function sendMessage(chatId: string, profileId: string, dto: SendMessageDto) {
|
||||
const res = await apiClient.api.chatControllerSendMessage({ chatId, profileId }, dto) as unknown as ChatMessage
|
||||
const res = await apiClient.api.chatControllerSendMessage({ chatId, profileId }, dto)
|
||||
messages.value.push(res)
|
||||
return res
|
||||
}
|
||||
|
||||
async function openChat(profileId: string, matchId: string) {
|
||||
const res = await apiClient.api.chatControllerCreateChat({ profileId, matchId }) as unknown as Chat
|
||||
const res = await apiClient.api.chatControllerCreateChat({ profileId, matchId })
|
||||
const existing = chats.value.findIndex(c => c.id === res.id)
|
||||
if (existing === -1)
|
||||
chats.value.unshift(res)
|
||||
@@ -81,7 +69,7 @@ function startPolling(chatId: string, profileId: string) {
|
||||
// TODO: replace with WebSocket subscription
|
||||
pollingTimer.value = setInterval(async () => {
|
||||
try {
|
||||
const res = await apiClient.api.chatControllerGetMessages({ chatId, profileId }) as unknown as ChatMessage[]
|
||||
const res = await apiClient.api.chatControllerGetMessages({ chatId, profileId })
|
||||
if (res.length > messages.value.length) {
|
||||
messages.value = res
|
||||
}
|
||||
|
||||
@@ -1,22 +1,8 @@
|
||||
import type { FeedControllerGetFeedParams, MediaItemDto, TagDto } from '@/api/api'
|
||||
import type { FeedControllerGetFeedParams, ProfileResponseDto } from '@/api/api'
|
||||
import { reactive, ref } from 'vue'
|
||||
import { apiClient } from '@/api/client'
|
||||
|
||||
export interface FeedProfile {
|
||||
id: string
|
||||
name: string
|
||||
birthDate: string
|
||||
gender: 'male' | 'female'
|
||||
cityId?: string | null
|
||||
cityName?: string
|
||||
districtId?: string | null
|
||||
description?: string | null
|
||||
nation?: string | null
|
||||
height?: number | null
|
||||
weight?: number | null
|
||||
tags?: TagDto[]
|
||||
media?: MediaItemDto[]
|
||||
}
|
||||
export type FeedProfile = ProfileResponseDto & { age?: number | null, cityName?: string }
|
||||
|
||||
const cards = ref<FeedProfile[]>([])
|
||||
const filters = reactive<Partial<FeedControllerGetFeedParams>>({})
|
||||
@@ -37,13 +23,13 @@ async function fetchNextPage(profileId: string) {
|
||||
...filters,
|
||||
})
|
||||
|
||||
console.log(res.data)
|
||||
console.log(res.items)
|
||||
|
||||
if (page.value === 1)
|
||||
cards.value = res.data
|
||||
else cards.value.push(...res.data)
|
||||
cards.value = res.items
|
||||
else cards.value.push(...res.items)
|
||||
|
||||
hasMore.value = res.length >= 20
|
||||
hasMore.value = res.items.length >= res.limit
|
||||
page.value++
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -9,7 +9,7 @@ const loading = ref(false)
|
||||
async function fetchProfile(profileId: string) {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await apiClient.api.profilesControllerFindOne(profileId) as unknown as UserProfile
|
||||
const res = await apiClient.api.profilesControllerFindOne(profileId)
|
||||
currentProfile.value = res
|
||||
return res
|
||||
}
|
||||
@@ -19,13 +19,13 @@ async function fetchProfile(profileId: string) {
|
||||
}
|
||||
|
||||
async function createProfile(dto: CreateProfileDto) {
|
||||
const res = await apiClient.api.profilesControllerCreate(dto) as unknown as UserProfile
|
||||
const res = await apiClient.api.profilesControllerCreate(dto)
|
||||
currentProfile.value = res
|
||||
return res
|
||||
}
|
||||
|
||||
async function updateProfile(profileId: string, dto: UpdateProfileDto) {
|
||||
const res = await apiClient.api.profilesControllerUpdate(profileId, dto) as unknown as UserProfile
|
||||
const res = await apiClient.api.profilesControllerUpdate(profileId, dto)
|
||||
currentProfile.value = res
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { CityResponseDto, DistrictResponseDto, GreetingDto, TagResponseDto } from '@/api/api'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
export type ToastType = 'success' | 'error' | 'info' | 'warning'
|
||||
@@ -9,26 +10,10 @@ export interface Toast {
|
||||
duration?: number
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
id: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface City {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface District {
|
||||
id: string
|
||||
name: string
|
||||
cityId: string
|
||||
}
|
||||
|
||||
export interface Greeting {
|
||||
id: string
|
||||
text: string
|
||||
}
|
||||
export type Tag = TagResponseDto
|
||||
export type City = CityResponseDto
|
||||
export type District = DistrictResponseDto
|
||||
export type Greeting = GreetingDto
|
||||
|
||||
const toasts = ref<Toast[]>([])
|
||||
const sidebarExpanded = ref(false)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import axios from 'axios'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { _getAccessToken, _setAccessToken, BASE_URL } from '@/api/client'
|
||||
import { _getAccessToken, _setAccessToken, axiosInstance, BASE_URL } from '@/api/client'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
|
||||
export const router = createRouter({
|
||||
@@ -51,12 +50,12 @@ router.beforeEach(async (to, _from, next) => {
|
||||
const storedRefresh = localStorage.getItem('refreshToken')
|
||||
if (storedRefresh && !_getAccessToken()) {
|
||||
try {
|
||||
const res = await axios.post<{ data: { accessToken: string, refreshToken: string } }>(
|
||||
const res = await axiosInstance.post<{ accessToken: string, refreshToken: string }>(
|
||||
`${BASE_URL}/api/v1/auth/refresh`,
|
||||
{ refreshToken: storedRefresh },
|
||||
)
|
||||
_setAccessToken(res.data.data.accessToken)
|
||||
localStorage.setItem('refreshToken', res.data.data.refreshToken)
|
||||
_setAccessToken(res.data.accessToken)
|
||||
localStorage.setItem('refreshToken', res.data.refreshToken)
|
||||
await authStore.fetchMe()
|
||||
}
|
||||
catch {
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { CreateProfileDto } from '@/api/api'
|
||||
import type { UserProfile } from '@/composables/useAuth'
|
||||
import type { District } from '@/composables/useUi'
|
||||
import { useVuelidate } from '@vuelidate/core'
|
||||
import { helpers, required } from '@vuelidate/validators'
|
||||
@@ -224,7 +223,7 @@ watch(() => form.cityId, async (cityId) => {
|
||||
}
|
||||
loadingDistricts.value = true
|
||||
try {
|
||||
const res = await apiClient.api.citiesControllerFindDistricts(cityId) as unknown as District[]
|
||||
const res = await apiClient.api.citiesControllerFindDistricts(cityId)
|
||||
uiStore.setDistricts(cityId, res)
|
||||
districts.value = res
|
||||
}
|
||||
@@ -270,7 +269,7 @@ async function finish() {
|
||||
loading.value = true
|
||||
try {
|
||||
form.tagIds = selectedTags.value
|
||||
const profile = await apiClient.api.profilesControllerCreate(form as unknown as CreateProfileDto) as unknown as UserProfile
|
||||
const profile = await apiClient.api.profilesControllerCreate(form as unknown as CreateProfileDto)
|
||||
authStore.addProfile(profile)
|
||||
uiStore.addToast('Профиль создан', 'success')
|
||||
router.replace('/feed')
|
||||
|
||||
@@ -140,7 +140,7 @@ const dateOpen = ref(false)
|
||||
onMounted(async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await apiClient.api.profilesControllerFindOne(profileId) as unknown as UserProfile
|
||||
const res = await apiClient.api.profilesControllerFindOne(profileId)
|
||||
profile.value = res
|
||||
}
|
||||
catch {
|
||||
|
||||
Reference in New Issue
Block a user