diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 00000000..7b1a146b Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 00000000..97a88aeb Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/file.svg b/public/file.svg deleted file mode 100644 index 004145cd..00000000 --- a/public/file.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg deleted file mode 100644 index 567f17b0..00000000 --- a/public/globe.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/next.svg b/public/next.svg deleted file mode 100644 index 5174b28c..00000000 --- a/public/next.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg deleted file mode 100644 index 77053960..00000000 --- a/public/vercel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/window.svg b/public/window.svg deleted file mode 100644 index b2b2a44f..00000000 --- a/public/window.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/app/(main)/project/[id]/page.tsx b/src/app/(main)/project/[id]/page.tsx index c2e16416..34902c93 100644 --- a/src/app/(main)/project/[id]/page.tsx +++ b/src/app/(main)/project/[id]/page.tsx @@ -1,5 +1,24 @@ import React from 'react'; import ProjectInfo from './_components/ProjectInfo'; +import { Metadata } from 'next'; + +export async function generateMetadata(): Promise { + return { + title: `TEAMFICIAL`, + description: `소프트스킬 팀빌딩 서비스, 팀피셜`, + openGraph: { + title: `TEAMFICIAL`, + description: `소프트스킬 팀빌딩 서비스, 팀피셜`, + images: [ + { + url: 'https://www.teamficial.com/og/Teamficial_metatag_Image.jpg', + width: 1200, + height: 630, + }, + ], + }, + }; +} type Props = { params: Promise<{ id: string }>; diff --git a/src/app/(main)/teampsylog/[uuid]/page.tsx b/src/app/(main)/teampsylog/[uuid]/page.tsx index bc9408c3..b3572c8c 100644 --- a/src/app/(main)/teampsylog/[uuid]/page.tsx +++ b/src/app/(main)/teampsylog/[uuid]/page.tsx @@ -1,6 +1,48 @@ import React from 'react'; import KeywordListPage from './_components/KeywordListPage'; import MobileHeader from '@/components/common/MobileHeader'; +import { Metadata } from 'next'; +import axios from 'axios'; + +type Props = { + params: Promise<{ uuid: string }>; +}; + +export async function generateMetadata({ params }: Props): Promise { + const { uuid } = await params; + let userName = '사용자'; + + try { + const res = await axios.get( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/teamficial-log/requester`, + { + params: { + requesterUuid: uuid, + }, + }, + ); + + userName = res.data?.result?.requesterName ?? '사용자'; + } catch (error) { + console.error('Failed to fetch requester data:', error); + } + + return { + title: `${userName}님의 팀피셜록`, + description: `소프트스킬 팀빌딩 서비스, 팀피셜`, + openGraph: { + title: `${userName}님의 팀피셜록`, + description: `소프트스킬 팀빌딩 서비스, 팀피셜`, + images: [ + { + url: 'https://www.teamficial.com/og/Teamficial_metatag_Image.jpg', + width: 1200, + height: 630, + }, + ], + }, + }; +} const page = () => { return ( diff --git a/src/app/(main)/teampsylog/_components/CommentPage.tsx b/src/app/(main)/teampsylog/_components/CommentPage.tsx index 976a5a5c..f7e08705 100644 --- a/src/app/(main)/teampsylog/_components/CommentPage.tsx +++ b/src/app/(main)/teampsylog/_components/CommentPage.tsx @@ -37,7 +37,7 @@ const CommentPage = ({ return (
diff --git a/src/app/(main)/teampsylog/_components/KeywordBar.tsx b/src/app/(main)/teampsylog/_components/KeywordBar.tsx index b89bf95f..9dd1f99d 100644 --- a/src/app/(main)/teampsylog/_components/KeywordBar.tsx +++ b/src/app/(main)/teampsylog/_components/KeywordBar.tsx @@ -1,5 +1,5 @@ import { useGetKeyword } from '@/hooks/queries/useKeyword'; -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import KeywordItem from './KeywordItem'; import Image from 'next/image'; import ProfileDropdown from './ProfileDropdown'; @@ -63,6 +63,9 @@ const KeywordBar = ({ addToast({ message: '링크가 복사되었어요' }); }; + const [dismissedByUser, setDismissedByUser] = useState(false); + const showShareGuide = !dismissedByUser && !isEditMode; + useEffect(() => { // 편집 모드이고 아직 슬롯이 선택되지 않았을 때만 가이드 표시 if (isEditMode && selectedSlot === null) { @@ -114,6 +117,15 @@ const KeywordBar = ({ + {showShareGuide && ( + setDismissedByUser(true)} + text="팀피셜록 링크를 공유해보세요!" + share={true} + balloonClassName="right-4" + /> + )}
)}
@@ -148,6 +160,15 @@ const KeywordBar = ({ {isEditMode && showGuide && ( setShowGuide(false)} /> )} + {showShareGuide && ( + setDismissedByUser(true)} + text={`팀피셜록 링크를\n공유해보세요!`} + share={true} + balloonClassName="right-0 -translate-y-10" + /> + )}
{mobileDisplayKeywords.map((keyword, index) => ( void; text?: string; + balloonClassName?: string; // 말풍선 위치 오버라이드 } const KeywordGuideBalloon: React.FC = ({ position, + share = false, onClose, text = '변경할 대표 키워드를\n먼저 선택하세요', + balloonClassName, }) => { return (
@@ -28,7 +34,9 @@ const KeywordGuideBalloon: React.FC = ({
{/* 꼬리 */}