diff --git a/src/api/matches.ts b/src/api/matches.ts index f98c797..93d4dc3 100644 --- a/src/api/matches.ts +++ b/src/api/matches.ts @@ -20,6 +20,15 @@ export interface ReceivedMatch { expiresAt: string | null } +/** 진행중(수락된) 매칭 — 채팅 재진입 목록용. */ +export interface OngoingMatch { + matchId: number + otherDogId: number + otherDogName: string + otherDogBreed: string | null + respondedAt: string | null +} + /** STOMP /topic/users/{userId} 로 오는 매칭 알림. */ export interface MatchNotification { type: 'NEW_REQUEST' | 'ACCEPTED' | 'REJECTED' | 'EXPIRED' | 'FEEDBACK_REQUEST' @@ -35,4 +44,5 @@ export const matchesApi = { reject: (id: number) => http.post(`/api/matches/${id}/reject`), received: (dogId: number) => http.get(`/api/matches/received/${dogId}`), sent: (dogId: number) => http.get(`/api/matches/sent/${dogId}`), + ongoing: (dogId: number) => http.get(`/api/matches/ongoing/${dogId}`), } diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index 6b0c4ae..94dfd0f 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -39,6 +39,37 @@ + + + + {{ matching.ongoing.length }} + + + + 진행중 채팅 + + 진행중인 매칭이 없어요. + + + + + + + {{ o.otherDogName }} + {{ o.otherDogBreed || '견종 미상' }} · 대화 열기 + + + + + + + @@ -128,6 +159,12 @@ function openFeedback(id: number) { feedbackOpen.value = true } +/** 진행중 채팅 목록에서 특정 매칭 채팅 다시 열기. */ +function openMatchChat(matchId: number) { + matchChatId.value = matchId + matchChatOpen.value = true +} + onMounted(async () => { await dogs.loadMyDogs() if (auth.member && dogs.currentDogId != null) { diff --git a/src/stores/matching.ts b/src/stores/matching.ts index 6d39202..56cef89 100644 --- a/src/stores/matching.ts +++ b/src/stores/matching.ts @@ -1,7 +1,12 @@ import { defineStore } from 'pinia' import { ref } from 'vue' import { Notify } from 'quasar' -import { matchesApi, type MatchNotification, type ReceivedMatch } from '@/api/matches' +import { + matchesApi, + type MatchNotification, + type OngoingMatch, + type ReceivedMatch, +} from '@/api/matches' import { createUserNotifications } from '@/lib/chatSocket' /** @@ -13,6 +18,7 @@ import { createUserNotifications } from '@/lib/chatSocket' */ export const useMatchingStore = defineStore('matching', () => { const received = ref([]) + const ongoing = ref([]) const sentPendingTargetIds = ref>(new Set()) const openChatMatchId = ref(null) /** 산책 후 피드백(찰떡지수) 팝업을 띄울 매칭 id — 알림 수신 시 세팅. */ @@ -24,8 +30,13 @@ export const useMatchingStore = defineStore('matching', () => { async function refresh(dogId: number): Promise { myDogId = dogId try { - const [rec, snt] = await Promise.all([matchesApi.received(dogId), matchesApi.sent(dogId)]) + const [rec, snt, ong] = await Promise.all([ + matchesApi.received(dogId), + matchesApi.sent(dogId), + matchesApi.ongoing(dogId).catch(() => [] as OngoingMatch[]), + ]) received.value = rec + ongoing.value = ong sentPendingTargetIds.value = new Set(snt.map((m) => m.targetDogId)) } catch { // 무시 (미로그인/네트워크) @@ -44,6 +55,7 @@ export const useMatchingStore = defineStore('matching', () => { socket?.deactivate() socket = null received.value = [] + ongoing.value = [] sentPendingTargetIds.value = new Set() } @@ -69,6 +81,7 @@ export const useMatchingStore = defineStore('matching', () => { await matchesApi.accept(id) received.value = received.value.filter((m) => m.id !== id) openChatMatchId.value = id // 수락자도 바로 채팅 열기 + if (myDogId != null) void refresh(myDogId) // 진행중 목록에 반영 } async function reject(id: number): Promise { @@ -89,6 +102,7 @@ export const useMatchingStore = defineStore('matching', () => { return { received, + ongoing, sentPendingTargetIds, openChatMatchId, feedbackMatchId,