From 289b41d38daa49f719e32a9871aef68c84310f09 Mon Sep 17 00:00:00 2001 From: sunhwaaRj Date: Sun, 11 Jan 2026 18:05:38 +0900 Subject: [PATCH 1/7] =?UTF-8?q?#141=20[CHORE]=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/icons/teamficial-keyword.svg | 16 +++++++++ .../(main)/teampsylog/_components/LogNote.tsx | 33 ++++--------------- 2 files changed, 23 insertions(+), 26 deletions(-) create mode 100644 public/icons/teamficial-keyword.svg diff --git a/public/icons/teamficial-keyword.svg b/public/icons/teamficial-keyword.svg new file mode 100644 index 00000000..bc45f2ba --- /dev/null +++ b/public/icons/teamficial-keyword.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/app/(main)/teampsylog/_components/LogNote.tsx b/src/app/(main)/teampsylog/_components/LogNote.tsx index 53453995..0c35d712 100644 --- a/src/app/(main)/teampsylog/_components/LogNote.tsx +++ b/src/app/(main)/teampsylog/_components/LogNote.tsx @@ -146,32 +146,13 @@ const LogNote = ({ > 다음 페이지 - {data?.totalElements === 0 ? null : isEditMode ? ( - <> - teamficial_symbol -

- {selectedSlot !== null - ? `변경할 키워드를 선택하세요` - : '변경할 대표키워드를\n먼저 선택하세요'} -

- - ) : !selectedKeywordId ? ( - <> - teamficial_symbol -

- 키워드를 선택해 자세한 내용을 확인하세요 -

- + {!selectedKeywordId ? ( + teamficial_symbol ) : ( id === selectedKeywordId)] ?? ''} From 9c7c85a526af5ea632d4238055704a930d5714fb Mon Sep 17 00:00:00 2001 From: sunhwaaRj Date: Sun, 11 Jan 2026 18:06:13 +0900 Subject: [PATCH 2/7] =?UTF-8?q?#141=20[FEAT]=20=EB=8C=80=ED=91=9C=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=88=98=EC=A0=95=20=EC=95=88=EB=82=B4=20?= =?UTF-8?q?=ED=86=A0=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teampsylog/_components/KeywordBar.tsx | 116 +++++++++++------- .../_components/KeywordGuideBalloon.tsx | 36 ++++++ .../teampsylog/_components/KeywordItem.tsx | 22 ++-- 3 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx diff --git a/src/app/(main)/teampsylog/_components/KeywordBar.tsx b/src/app/(main)/teampsylog/_components/KeywordBar.tsx index b42ceda9..b89bf95f 100644 --- a/src/app/(main)/teampsylog/_components/KeywordBar.tsx +++ b/src/app/(main)/teampsylog/_components/KeywordBar.tsx @@ -1,10 +1,11 @@ import { useGetKeyword } from '@/hooks/queries/useKeyword'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import KeywordItem from './KeywordItem'; import Image from 'next/image'; import ProfileDropdown from './ProfileDropdown'; import { ResponseProfile } from '@/types/profile'; import { useToast } from '@/contexts/ToastContext'; +import KeywordGuideBalloon from './KeywordGuideBalloon'; const KeywordBar = ({ profileId, @@ -29,6 +30,7 @@ const KeywordBar = ({ }) => { const { data } = useGetKeyword({ profileId }); const { addToast } = useToast(); + const [showGuide, setShowGuide] = useState(false); const headKeywords = data?.headKeywords || []; const desktopDisplayKeywords = [ @@ -61,45 +63,63 @@ const KeywordBar = ({ addToast({ message: '링크가 복사되었어요' }); }; + useEffect(() => { + // 편집 모드이고 아직 슬롯이 선택되지 않았을 때만 가이드 표시 + if (isEditMode && selectedSlot === null) { + setShowGuide(true); + } else { + setShowGuide(false); + } + }, [isEditMode, selectedSlot]); + if (!isShareMode) return null; + return ( <> {/* desktop */} -
- {/* 대표키워드 및 프로필 드롭다운 */} -
- - {desktopDisplayKeywords.map((keyword, index) => ( - = headKeywords.length} - onClick={() => isEditMode && onSelectSlot(index)} - /> - ))} -
- {isShareMode && ( -
- - + {desktopDisplayKeywords.map((keyword, index) => ( + = headKeywords.length} + onClick={() => isEditMode && onSelectSlot(index)} + /> + ))} +
+ {isShareMode && ( +
+ + +
+ )}
- )} + + {/* mobile */}
{/* 수정 버튼 및 프로필 드롭다운 */} @@ -123,18 +143,24 @@ const KeywordBar = ({
-
- {mobileDisplayKeywords.map((keyword, index) => ( - = headKeywords.length} - onClick={() => isEditMode && onSelectSlot(index)} - isMobileDevice={true} - /> - ))} + +
+ {isEditMode && showGuide && ( + setShowGuide(false)} /> + )} +
+ {mobileDisplayKeywords.map((keyword, index) => ( + = headKeywords.length} + onClick={() => isEditMode && onSelectSlot(index)} + isMobileDevice={true} + /> + ))} +
diff --git a/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx b/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx new file mode 100644 index 00000000..9deaa6b4 --- /dev/null +++ b/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx @@ -0,0 +1,36 @@ +import React from 'react'; + +interface KeywordGuideBalloonProps { + position: 'top' | 'bottom'; + onClose: () => void; +} + +const KeywordGuideBalloon: React.FC = ({ position, onClose }) => { + return ( +
+
+ 변경할 대표 키워드를 먼저 선택하세요 + +
+ {/* 꼬리 */} +
+
+ ); +}; + +export default KeywordGuideBalloon; diff --git a/src/app/(main)/teampsylog/_components/KeywordItem.tsx b/src/app/(main)/teampsylog/_components/KeywordItem.tsx index 86b7b1e4..48f0476a 100644 --- a/src/app/(main)/teampsylog/_components/KeywordItem.tsx +++ b/src/app/(main)/teampsylog/_components/KeywordItem.tsx @@ -44,15 +44,19 @@ const KeywordItem = ({
Date: Sun, 11 Jan 2026 19:10:16 +0900 Subject: [PATCH 3/7] =?UTF-8?q?#141=20[FEAT]=20=EB=8C=80=ED=91=9C=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=84=A0=ED=83=9D=20=EC=95=88=EB=82=B4=20?= =?UTF-8?q?=ED=86=A0=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/KeywordGuideBalloon.tsx | 15 +++++++++----- .../(main)/teampsylog/_components/LogNote.tsx | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx b/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx index 9deaa6b4..5d97cf5f 100644 --- a/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx +++ b/src/app/(main)/teampsylog/_components/KeywordGuideBalloon.tsx @@ -3,20 +3,25 @@ import React from 'react'; interface KeywordGuideBalloonProps { position: 'top' | 'bottom'; onClose: () => void; + text?: string; } -const KeywordGuideBalloon: React.FC = ({ position, onClose }) => { +const KeywordGuideBalloon: React.FC = ({ + position, + onClose, + text = '변경할 대표 키워드를\n먼저 선택하세요', +}) => { return (
-
- 변경할 대표 키워드를 먼저 선택하세요 +
+ {text} diff --git a/src/app/(main)/teampsylog/_components/LogNote.tsx b/src/app/(main)/teampsylog/_components/LogNote.tsx index 0c35d712..40cff70c 100644 --- a/src/app/(main)/teampsylog/_components/LogNote.tsx +++ b/src/app/(main)/teampsylog/_components/LogNote.tsx @@ -8,6 +8,7 @@ import AllKeyword from './AllKeyword'; import Loading from '@/components/common/Loading'; import ErrorDisplay from '@/components/common/Error'; import BottomComment from './BottomComment'; +import KeywordGuideBalloon from './KeywordGuideBalloon'; const LogNote = ({ userId, @@ -24,6 +25,7 @@ const LogNote = ({ }) => { const [page, setPage] = useState(0); const [isMobileSheetOpen, setIsMobileSheetOpen] = useState(false); + const [showGuide, setShowGuide] = useState(false); const { data, isLoading, isError } = useGetKeywordList({ userId: userId ?? 0, @@ -42,6 +44,14 @@ const LogNote = ({ setSelectedKeywordId(null); }, [page]); + useEffect(() => { + if (isEditMode && selectedSlot !== null) { + setShowGuide(true); + } else { + setShowGuide(false); + } + }, [isEditMode, selectedSlot]); + const handleKeywordClick = (keywordId: number) => { if (isEditMode && selectedSlot !== null) { // 편집 모드: 선택된 슬롯에 키워드 할당 @@ -67,6 +77,16 @@ const LogNote = ({
{/* 왼쪽 페이지 */}
+ {showGuide && ( +
+ setShowGuide(false)} + text={`변경할 키워드를\n선택하세요`} + /> +
+ )} +
{/* mobile */} -
+
Date: Sun, 11 Jan 2026 19:22:43 +0900 Subject: [PATCH 6/7] =?UTF-8?q?#141=20[CHORE]=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=8B=B1=20=ED=98=95=EC=8B=9D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/project/formatDate.ts | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/utils/project/formatDate.ts b/src/utils/project/formatDate.ts index 99620710..3b72837a 100644 --- a/src/utils/project/formatDate.ts +++ b/src/utils/project/formatDate.ts @@ -1,5 +1,22 @@ +export const parseDate = (dateString: string): Date | null => { + if (!dateString) return null; + + const isoString = dateString.replace(/\./g, '-').replace(' ', 'T'); + + const date = new Date(isoString); + + if (isNaN(date.getTime())) { + console.error('Failed to parse date:', dateString); + return null; + } + + return date; +}; + export const formatDate = (dateString: string) => { - const date = new Date(dateString); + const date = parseDate(dateString); + if (!date) return ''; + const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); @@ -8,7 +25,9 @@ export const formatDate = (dateString: string) => { }; export const formatDateDot = (dateString: string): string => { - const date = new Date(dateString); + const date = parseDate(dateString); + if (!date) return ''; + const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); @@ -17,13 +36,17 @@ export const formatDateDot = (dateString: string): string => { }; export const formatDday = (dday: number | null | undefined): string => { - // NaN 체크 - if (dday == null || isNaN(Number(dday))) { + if (dday == null) { return '마감'; } const numDday = Number(dday); + if (isNaN(numDday)) { + console.error('Invalid dday value:', dday); + return '마감'; + } + if (numDday > 0) return `D-${numDday}`; if (numDday === 0) return 'D-DAY'; return '마감'; From 3ffced3707327b1760daf651769e73949eda5337 Mon Sep 17 00:00:00 2001 From: sunhwaaRj Date: Sun, 11 Jan 2026 19:33:51 +0900 Subject: [PATCH 7/7] =?UTF-8?q?#141=20[CHORE]=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=8B=B1=20=ED=98=95=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/project/formatDate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/project/formatDate.ts b/src/utils/project/formatDate.ts index 3b72837a..260cf1ed 100644 --- a/src/utils/project/formatDate.ts +++ b/src/utils/project/formatDate.ts @@ -1,7 +1,7 @@ export const parseDate = (dateString: string): Date | null => { if (!dateString) return null; - const isoString = dateString.replace(/\./g, '-').replace(' ', 'T'); + const isoString = dateString.replace(/\./g, '-').replace(/ /g, 'T'); const date = new Date(isoString);