feat(src/components/feed/FeedCard.vue): добавляет обработку события клика для кнопок лайка и дизлайка

 feat(src/views/matches/MatchesView.vue): обновляет отображение аватара и возраста партнера в карточке совпадений
This commit is contained in:
Oscar
2026-06-08 21:33:44 +03:00
parent ffde85242a
commit 6f7ef5e670
2 changed files with 30 additions and 24 deletions

View File

@@ -65,12 +65,12 @@
<!-- Action buttons (visible on non-drag mode) --> <!-- Action buttons (visible on non-drag mode) -->
<div v-if="isTop" class="feed-card__actions" @click.stop> <div v-if="isTop" class="feed-card__actions" @click.stop>
<button class="feed-card__btn feed-card__btn--dislike" aria-label="Пропустить" @click="handleDislike"> <button class="feed-card__btn feed-card__btn--dislike" aria-label="Пропустить" @click.stop="handleDislike">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="24" height="24"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="24" height="24">
<path d="M18 6L6 18M6 6l12 12" /> <path d="M18 6L6 18M6 6l12 12" />
</svg> </svg>
</button> </button>
<button class="feed-card__btn feed-card__btn--like" aria-label="Лайк" @click="handleLike"> <button class="feed-card__btn feed-card__btn--like" aria-label="Лайк" @click.stop="handleLike">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="24" height="24"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="24" height="24">
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" /> <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
</svg> </svg>

View File

@@ -26,8 +26,8 @@
> >
<RouterLink :to="`/profile/${match.partnerProfile.id}`" class="match-card__avatar-wrap"> <RouterLink :to="`/profile/${match.partnerProfile.id}`" class="match-card__avatar-wrap">
<img <img
v-if="match.partnerProfile.avatarUrl" v-if="match.partnerProfile.media[0]?.path"
:src="match.partnerProfile.avatarUrl" :src="match.partnerProfile.media[0].path"
:alt="match.partnerProfile.name" :alt="match.partnerProfile.name"
class="match-card__avatar" class="match-card__avatar"
> >
@@ -41,10 +41,10 @@
<div class="match-card__info"> <div class="match-card__info">
<RouterLink :to="`/profile/${match.partnerProfile.id}`" class="match-card__name"> <RouterLink :to="`/profile/${match.partnerProfile.id}`" class="match-card__name">
{{ match.partnerProfile.name }} {{ match.partnerProfile.name }}
<span v-if="match.partnerProfile.age" class="match-card__age">, {{ match.partnerProfile.age }}</span> <span v-if="match.partnerProfile.birthDate" class="match-card__age">, {{ calcAge(match.partnerProfile.birthDate) }}</span>
</RouterLink> </RouterLink>
<span v-if="match.partnerProfile.cityName" class="meta match-card__city"> <span v-if="match.partnerProfile.city?.name" class="meta match-card__city">
{{ match.partnerProfile.cityName }} {{ match.partnerProfile.city.name }}
</span> </span>
</div> </div>
@@ -63,6 +63,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue' import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import type { MatchDto, ProfileResponseDto } from '@/api/api'
import { apiClient } from '@/api/client' import { apiClient } from '@/api/client'
import AppButton from '@/components/common/AppButton.vue' import AppButton from '@/components/common/AppButton.vue'
import EmptyState from '@/components/common/EmptyState.vue' import EmptyState from '@/components/common/EmptyState.vue'
@@ -71,36 +72,41 @@ import { useAuth } from '@/composables/useAuth'
import { useChat } from '@/composables/useChat' import { useChat } from '@/composables/useChat'
import { useUi } from '@/composables/useUi' import { useUi } from '@/composables/useUi'
interface Match { type EnrichedMatch = MatchDto & { partnerProfile: ProfileResponseDto }
id: string
profileId: string
partnerProfile: {
id: string
name: string
avatarUrl?: string
cityName?: string
age?: number
}
createdAt: string
hasChat: boolean
}
const authStore = useAuth() const authStore = useAuth()
const chatStore = useChat() const chatStore = useChat()
const uiStore = useUi() const uiStore = useUi()
const router = useRouter() const router = useRouter()
const matches = ref<Match[]>([]) const matches = ref<EnrichedMatch[]>([])
const loading = ref(false) const loading = ref(false)
function calcAge(birthDate: string): number | undefined {
const birth = new Date(birthDate)
if (Number.isNaN(birth.getTime()))
return undefined
const today = new Date()
let age = today.getFullYear() - birth.getFullYear()
if (today.getMonth() < birth.getMonth() || (today.getMonth() === birth.getMonth() && today.getDate() < birth.getDate()))
age--
return age
}
onMounted(async () => { onMounted(async () => {
const profileId = authStore.activeProfile?.id const profileId = authStore.activeProfile?.id
if (!profileId) if (!profileId)
return return
loading.value = true loading.value = true
try { try {
const res = await apiClient.api.likesControllerGetMyMatches({ profileId }) as unknown as Match[] const matchDtos = await apiClient.api.likesControllerGetMyMatches({ profileId })
matches.value = res matches.value = await Promise.all(
matchDtos.map(async (m) => {
const partnerProfileId = m.profile1Id === profileId ? m.profile2Id : m.profile1Id
const partnerProfile = await apiClient.api.profilesControllerFindOne(partnerProfileId)
return { ...m, partnerProfile }
}),
)
} }
catch { catch {
uiStore.addToast('Не удалось загрузить совпадения', 'error') uiStore.addToast('Не удалось загрузить совпадения', 'error')
@@ -110,7 +116,7 @@ onMounted(async () => {
} }
}) })
async function openChat(match: Match) { async function openChat(match: EnrichedMatch) {
const profileId = authStore.activeProfile?.id const profileId = authStore.activeProfile?.id
if (!profileId) if (!profileId)
return return