diff --git a/src/components/pages/pending/pending-members/index.tsx b/src/components/pages/pending/pending-members/index.tsx index 24547724..d514b6b5 100644 --- a/src/components/pages/pending/pending-members/index.tsx +++ b/src/components/pages/pending/pending-members/index.tsx @@ -8,6 +8,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { API } from '@/api'; import { EmptyState } from '@/components/layout/empty-state'; +import { groupKeys } from '@/lib/query-key/query-key-group'; import { GetJoinRequestsResponse } from '@/types/service/group'; import { PendingMemberCard } from './pending-member-card'; @@ -21,7 +22,7 @@ export const GroupPendingMembers = ({ groupId }: Props) => { const queryClient = useQueryClient(); const { data, isLoading, error } = useQuery({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), queryFn: () => API.groupService.getJoinRequests({ groupId }, 'PENDING'), }); @@ -41,11 +42,11 @@ export const GroupPendingMembers = ({ groupId }: Props) => { // 가입 신청 목록 캐시 무효화 및 자동 refetch // GroupPendingSummary의 count도 자동으로 업데이트됨 await queryClient.invalidateQueries({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), refetchType: 'active', // 활성화된 모든 쿼리 자동 refetch }); // 모임 상세 정보도 갱신 - await queryClient.invalidateQueries({ queryKey: ['groupDetails', groupId] }); + await queryClient.invalidateQueries({ queryKey: groupKeys.detail(groupId) }); }, }); @@ -56,7 +57,7 @@ export const GroupPendingMembers = ({ groupId }: Props) => { // 가입 신청 목록 캐시 무효화 및 모든 활성 쿼리 refetch // GroupPendingSummary의 count도 자동으로 업데이트됨 await queryClient.invalidateQueries({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), refetchType: 'active', // 활성화된 모든 쿼리 자동 refetch }); }, diff --git a/src/components/pages/pending/pending-summary/index.tsx b/src/components/pages/pending/pending-summary/index.tsx index e9d05754..bac3db0f 100644 --- a/src/components/pages/pending/pending-summary/index.tsx +++ b/src/components/pages/pending/pending-summary/index.tsx @@ -7,6 +7,7 @@ import { DEFAULT_GROUP_IMAGE } from 'constants/default-images'; import { API } from '@/api'; import { ImageWithFallback } from '@/components/ui'; +import { groupKeys } from '@/lib/query-key/query-key-group'; import { GetJoinRequestsResponse } from '@/types/service/group'; interface Props { @@ -16,7 +17,7 @@ interface Props { export const GroupPendingSummary = ({ groupId, initialData }: Props) => { const { data } = useQuery({ - queryKey: ['joinRequests', groupId, 'PENDING'], + queryKey: groupKeys.joinRequests(groupId, 'PENDING'), queryFn: () => API.groupService.getJoinRequests({ groupId }, 'PENDING'), initialData, }); diff --git a/src/lib/metadata/home.ts b/src/lib/metadata/home.ts index 100e2e0b..b78f6c95 100644 --- a/src/lib/metadata/home.ts +++ b/src/lib/metadata/home.ts @@ -1,18 +1,39 @@ import { Metadata } from 'next'; import { headers } from 'next/headers'; +import { API } from '@/api'; +import { GROUP_LIST_PAGE_SIZE } from '@/lib/constants/group-list'; + export const generateHomeMetadata = async (keyword?: string): Promise => { - const headersList = headers(); - const host = (await headersList).get('host') || process.env.DOMAIN; + const headersList = await headers(); + const host = headersList.get('host') || process.env.DOMAIN || 'wego.monster'; + const protocol = + headersList.get('x-forwarded-proto') || (host.includes('localhost') ? 'http' : 'https'); const currentUrl = keyword - ? `https://${host}/?keyword=${encodeURIComponent(keyword)}` - : `https://${host}/`; + ? `${protocol}://${host}/?keyword=${encodeURIComponent(keyword)}` + : `${protocol}://${host}/`; + const logoImageUrl = `${protocol}://${host}/icons/resizable/icon-wego-logo.svg`; try { if (keyword) { const metaTitle = `${keyword} 검색결과 | WeGo`; const metaDescription = `"${keyword}"에 대한 모임 검색 결과를 확인해보세요.`; + let searchImageUrl = logoImageUrl; + try { + const searchResponse = await API.groupService.getGroups({ + size: GROUP_LIST_PAGE_SIZE, + keyword, + }); + const firstGroupImage = searchResponse.items[0]?.images?.[0]; + if (firstGroupImage) { + searchImageUrl = firstGroupImage; + } + } catch (error) { + // 실패 시 기본 로고 이미지 사용 + console.error('이미지를 가져오는데 실패했습니다:', error); + } + return { title: metaTitle, description: metaDescription, @@ -24,11 +45,20 @@ export const generateHomeMetadata = async (keyword?: string): Promise locale: 'ko_KR', type: 'website', url: currentUrl, + images: [ + { + url: searchImageUrl, + width: 400, + height: 400, + alt: `${keyword} 검색 결과 모임 이미지`, + }, + ], }, twitter: { card: 'summary', title: metaTitle, description: metaDescription, + images: [searchImageUrl], }, robots: { index: true, @@ -54,11 +84,20 @@ export const generateHomeMetadata = async (keyword?: string): Promise locale: 'ko_KR', type: 'website', url: currentUrl, + images: [ + { + url: logoImageUrl, + width: 400, + height: 400, + alt: 'WeGo 로고', + }, + ], }, twitter: { card: 'summary', title: metaTitle, description: metaDescription, + images: [logoImageUrl], }, robots: { index: true, @@ -78,9 +117,18 @@ export const generateHomeMetadata = async (keyword?: string): Promise description: 'WeGo에서 함께할 다양한 모임을 탐색하고 참여하세요.', url: currentUrl, type: 'website', + images: [ + { + url: logoImageUrl, + width: 400, + height: 400, + alt: 'WeGo 로고', + }, + ], }, twitter: { card: 'summary', + images: [logoImageUrl], }, }; } diff --git a/src/lib/query-key/query-key-group/index.ts b/src/lib/query-key/query-key-group/index.ts index d89ca44d..bc2f3313 100644 --- a/src/lib/query-key/query-key-group/index.ts +++ b/src/lib/query-key/query-key-group/index.ts @@ -7,4 +7,6 @@ export const groupKeys = { myList: (filters: { type: 'current' | 'myPost' | 'past'; cursor?: number; size: number }) => [...groupKeys.myLists(), filters] as const, detail: (groupId: string) => [...groupKeys.all, groupId] as const, + joinRequests: (groupId: string, status: string = 'PENDING') => + ['joinRequests', groupId, status] as const, };