diff --git a/.github/workflows/closed-issue.yml b/.github/workflows/closed-issue.yml deleted file mode 100644 index 375418c..0000000 --- a/.github/workflows/closed-issue.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Close Mentioned Issues if Checklist Complete - -on: - pull_request: - types: [closed] - -permissions: - issues: write - pull-requests: read - contents: read - -jobs: - close-mentioned-issues: - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - name: Check if checklist is fully complete - id: checklist - run: | - BODY="${{ github.event.pull_request.body }}" - UNCHECKED=$(echo "$BODY" | grep -c '\[ \]') - if [ "$UNCHECKED" -eq 0 ]; then - echo "checklist-complete=true" >> $GITHUB_OUTPUT - else - echo "checklist-complete=false" >> $GITHUB_OUTPUT - fi - - - name: Extract issue numbers - id: issues - run: | - BODY="${{ github.event.pull_request.body }}" - echo "ISSUES=$(echo "$BODY" | grep -oE '#[0-9]+' | tr -d '#' | tr '\n' ' ')" >> $GITHUB_OUTPUT - - - name: Close mentioned issues - if: steps.checklist.outputs.checklist-complete == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - for issue in ${{ steps.issues.outputs.ISSUES }}; do - gh issue close "$issue" --repo "${{ github.repository }}" - done diff --git a/src/App.tsx b/src/App.tsx index a45430c..f976809 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,6 +12,7 @@ import styled from "styled-components"; import WritingPage from "./pages/writing/WritingPage"; import Testpage from "./pages/Testpage"; import EditPage from "./pages/writing/EditPage"; +import HashtagDetail from "./pages/collection/HashtagDetail"; function App() { return ( @@ -29,6 +30,7 @@ function App() { } /> } /> + } /> } /> diff --git a/src/components/diary/Header.tsx b/src/components/diary/Header.tsx index 9d8ccf6..38dbf35 100644 --- a/src/components/diary/Header.tsx +++ b/src/components/diary/Header.tsx @@ -1,3 +1,84 @@ -const Header = () => {}; +import styled from "styled-components"; +import { + IoChevronBack, + IoChevronForward, + IoHomeOutline, +} from "react-icons/io5"; +import { useNavigate } from "react-router-dom"; + +interface HeaderProps { + characterList: string[]; + currentIndex: number; + setCurrentIndex: React.Dispatch>; +} + +const Header = ({ + characterList, + currentIndex, + setCurrentIndex, +}: HeaderProps) => { + const navigate = useNavigate(); + + const goPrev = () => { + setCurrentIndex( + (prev) => (prev - 1 + characterList.length) % characterList.length, + ); + }; + + const goNext = () => { + setCurrentIndex((prev) => (prev + 1) % characterList.length); + }; + + return ( + + navigate("/")} /> + + + + + + {characterList[currentIndex]} + + + + + + + + ); +}; export default Header; + +const HeaderWrapper = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 20px; +`; + +const CenterContainer = styled.div` + position: absolute; + left: 50%; + transform: translateX(-50%); + width: 160px; + display: flex; + align-items: center; + justify-content: space-between; + color: #2d3552; + font-weight: 500; + font-size: 1.2rem; +`; + +const Name = styled.span` + flex: 1; + text-align: center; +`; + +const Placeholder = styled.div` + width: 28px; +`; + +const ClickableIcon = styled.div` + cursor: pointer; +`; diff --git a/src/components/home/DiaryList.tsx b/src/components/home/DiaryList.tsx index 1735393..1902116 100644 --- a/src/components/home/DiaryList.tsx +++ b/src/components/home/DiaryList.tsx @@ -93,13 +93,19 @@ export const DiaryTitle = styled.div` export const TagWrapper = styled.div` display: flex; - gap: 8px; - font-size: 14px; - color: #3b82f6; + flex-wrap: nowrap; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; margin-bottom: 8px; `; -export const Tag = styled.span``; +export const Tag = styled.span` + font-size: 14px; + color: #3b82f6; + margin-right: 8px; + flex-shrink: 0; +`; export const Content = styled.div` font-size: 14px; diff --git a/src/pages/DiaryDetail.tsx b/src/pages/DiaryDetail.tsx index d0fe4ed..27f914f 100644 --- a/src/pages/DiaryDetail.tsx +++ b/src/pages/DiaryDetail.tsx @@ -1,6 +1,6 @@ import styled from "styled-components"; import { IoHomeOutline, IoTrashBinOutline } from "react-icons/io5"; -import { BsPencil } from "react-icons/bs"; +import { BsPencil, BsStar, BsStarFill } from "react-icons/bs"; import { useNavigate, useParams } from "react-router-dom"; import { useEffect, useState } from "react"; import { getDiary } from "../services/apis/diary/diary"; @@ -48,6 +48,8 @@ const DiaryDetail = () => { } }, [diary]); + const [starred, setStarred] = useState(false); + const formatDate = (rawDate: string) => { const date = new Date(rawDate); return `${date.getFullYear()}.${String(date.getMonth() + 1).padStart(2, "0")}.${String(date.getDate()).padStart(2, "0")}.`; @@ -87,6 +89,11 @@ const DiaryDetail = () => { alt={diary.character} /> {diary.character} + {starred ? ( + setStarred(false)} /> + ) : ( + setStarred(true)} /> + )} {aiComment || "AI 코멘트를 생성 중입니다..."} @@ -148,7 +155,7 @@ const EditIcon = styled(BsPencil)` color: #1e2a52; `; -const Body = styled.div` +export const Body = styled.div` padding: 24px; display: flex; flex-direction: column; @@ -162,13 +169,13 @@ const Title = styled.h2` border-radius: 8px; `; -const TagBox = styled.div` +export const TagBox = styled.div` display: flex; gap: 8px; flex-wrap: wrap; `; -const Tag = styled.span` +export const Tag = styled.span` background: #ffffff; color: #2563eb; padding: 6px 12px; @@ -191,34 +198,47 @@ const CommentTitle = styled.h3` color: #1e2a52; `; -const CommentCard = styled.div` +export const CommentCard = styled.div` background: #fff; border-radius: 16px; padding: 16px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); `; -const CharacterRow = styled.div` +export const CharacterRow = styled.div` display: flex; align-items: center; gap: 12px; margin-bottom: 8px; `; -const CharacterImg = styled.img` +export const CharacterImg = styled.img` width: 40px; height: 40px; border-radius: 50%; `; -const CharacterName = styled.div` +export const CharacterName = styled.div` font-size: 16px; font-weight: 600; color: #1e2a52; `; -const CommentText = styled.p` +export const CommentText = styled.p` font-size: 14px; color: #374151; line-height: 1.6; `; + +export const StarIcon = styled(BsStar)` + margin-left: auto; + font-size: 20px; + cursor: pointer; +`; + +export const StarIconFill = styled(BsStarFill)` + margin-left: auto; + font-size: 20px; + color: #ffd600; + cursor: pointer; +`; diff --git a/src/pages/collection/Comments.tsx b/src/pages/collection/Comments.tsx index 1de4d7f..3883190 100644 --- a/src/pages/collection/Comments.tsx +++ b/src/pages/collection/Comments.tsx @@ -1,9 +1,67 @@ +import { useState } from "react"; +import { + Body, + CharacterImg, + CharacterName, + CharacterRow, + CommentCard, + CommentText, + StarIcon, + StarIconFill, +} from "../DiaryDetail"; +import Header from "../../components/diary/Header"; + +const dummyComments = [ + "오랜만에 영화관에서 좋은 시간 보냈다니 내가 다 기쁘다! 너의 여유로운 하루가 참 따뜻하게 느껴져 :)", + "오늘 하루도 수고 많았어! 너의 일상이 더 행복해지길 바랄게.", + "새로운 도전을 했다는 말에 나도 힘이 나! 계속 응원할게 :)", +]; + +const characterList = ["웅이", "앙글이", "티바노"]; + const Comments = () => { + const [starred, setStarred] = useState( + new Array(dummyComments.length).fill(false), + ); + const [currentIndex, setCurrentIndex] = useState(0); + return ( - <> - <>Comments -

일단 없는 걸로

- + +
+ +
즐겨찾기 한 코멘트 목록
+ {dummyComments.map((comment, index) => ( + + + + 웅이 + {starred[index] ? ( + { + const newStars = [...starred]; + newStars[index] = false; + setStarred(newStars); + }} + /> + ) : ( + { + const newStars = [...starred]; + newStars[index] = true; + setStarred(newStars); + }} + /> + )} + + {comment} + + ))} + ); }; + export default Comments; diff --git a/src/pages/collection/HashtagDetail.tsx b/src/pages/collection/HashtagDetail.tsx new file mode 100644 index 0000000..73f1fd3 --- /dev/null +++ b/src/pages/collection/HashtagDetail.tsx @@ -0,0 +1,31 @@ +import { useState } from "react"; +import Header from "../../components/diary/Header"; +import { Body } from "../DiaryDetail"; +import DiaryList from "../../components/home/DiaryList"; + +const characterList = [ + "슬픔", + "행복", + "기쁨", + "사랑", + "우정", + "추억", + "여행", + "일상", + "꿈", +]; + +const HashtagDetail = () => { + const [currentIndex, setCurrentIndex] = useState(0); + return ( + +
+ + + ); +}; +export default HashtagDetail; diff --git a/src/pages/collection/Hashtags.tsx b/src/pages/collection/Hashtags.tsx index e8e96d1..12afc32 100644 --- a/src/pages/collection/Hashtags.tsx +++ b/src/pages/collection/Hashtags.tsx @@ -1,9 +1,23 @@ +import { IoHomeOutline } from "react-icons/io5"; +import { Body, Tag, TagBox } from "../DiaryDetail"; +import { useNavigate } from "react-router-dom"; + +const dummyHashtags = Array.from({ length: 50 }, (_, i) => `더미태그${i + 1}`); + const Hashtags = () => { + const navigate = useNavigate(); return ( - <> - <>Hashtags -

일단 없는 걸로

- + + navigate("/")} /> +
해시태그 목록
+ + {dummyHashtags.map((tag, idx) => ( + navigate(`/hashtag/${(idx + 1).toString()}`)}> + #{tag} + + ))} + + ); }; export default Hashtags;