diff --git a/src/common/router/root.tsx b/src/common/router/root.tsx index 467853e..498baa8 100644 --- a/src/common/router/root.tsx +++ b/src/common/router/root.tsx @@ -15,7 +15,7 @@ const root = createBrowserRouter([ element: }, { - path: '/setting', + path: '/setting/:section', element: }, { diff --git a/src/common/util/html.tsx b/src/common/util/html.tsx index da4df5d..061891a 100644 --- a/src/common/util/html.tsx +++ b/src/common/util/html.tsx @@ -11,6 +11,6 @@ export const getImgUrls = (content: string) => { } export const removeHtmlTags = (content: string) => { - const regex = /(<([^>]+)>)/gi; + const regex = /(<([^>]+)>| )/gi; return content.replace(regex, ""); } \ No newline at end of file diff --git a/src/common/util/string.tsx b/src/common/util/string.tsx new file mode 100644 index 0000000..6592c79 --- /dev/null +++ b/src/common/util/string.tsx @@ -0,0 +1,9 @@ +export const getFolderTitle = (title: string, depth: number) => { + let prefix = ""; + if (depth === 1) { + prefix = "↳"; + } else if (depth === 2) { + prefix = "-"; + } + return `${prefix} ${title}`; +} \ No newline at end of file diff --git a/src/components/blog/BlogSearchBar.tsx b/src/components/blog/BlogSearchBar.tsx new file mode 100644 index 0000000..ffadb33 --- /dev/null +++ b/src/components/blog/BlogSearchBar.tsx @@ -0,0 +1,17 @@ +function BlogSearchBar({value, setValue}: { + value: string, + setValue: (value: string) => void, +}) { + return ( + { + setValue(e.target.value) + }}> + + ); +} + +export default BlogSearchBar; \ No newline at end of file diff --git a/src/components/blog/BlogSideBar.tsx b/src/components/blog/BlogSideBar.tsx new file mode 100644 index 0000000..e0f4fe2 --- /dev/null +++ b/src/components/blog/BlogSideBar.tsx @@ -0,0 +1,88 @@ +import {FolderType} from "../../common/types/blog.tsx"; +import {useSelector} from "react-redux"; +import {RootState} from "../../store.tsx"; +import {faker} from "@faker-js/faker/locale/ko"; +import {OutlineLink} from "../common/OutlineButton.tsx"; +import BlogTagCard from "./BlogTagCard.tsx"; +import {getFolderTitle} from "../../common/util/string.tsx"; + +function BlogSideBar({folders, username, addTag, setSelectedFolder, bgColor, side}: { + folders: FolderType[], + username: string | undefined, + addTag: (tagName: string) => void, + setSelectedFolder: (folder: FolderType) => void, + bgColor?: string, + side?: boolean, +}) { + + const loginState = useSelector((state: RootState) => state.loginSlice); + + return ( +
+
+ username +
+ {username} +
+ {username === loginState.username && ( +
+ + +
+ )} +
+
+
폴더
+ +
+
+
태그
+
+ {[Array.from({length: 24}).map(() => ( + + ))]} +
+
+
+ ); +} + +function BlogFolderList({depth = 0, folders, setSelectedFolder}: { + depth?: number, + folders: FolderType[], + setSelectedFolder: (folder: FolderType) => void, +}) { + + return ( +
+ {folders.map(folder => +
+ {depth === 0 &&
} + + {depth === 0 &&
} + +
)} +
+ ); +} + +export default BlogSideBar; \ No newline at end of file diff --git a/src/components/blog/BlogTagCard.tsx b/src/components/blog/BlogTagCard.tsx new file mode 100644 index 0000000..ac9c8e1 --- /dev/null +++ b/src/components/blog/BlogTagCard.tsx @@ -0,0 +1,16 @@ +import {TagResponse} from "../../common/types/post.tsx"; +import {TextButton} from "../common/TextButton.tsx"; + +function BlogTagCard({tag, addTag}: { + tag: TagResponse, + addTag: (tagName: string) => void, +}) { + return ( + addTag(tag.name)} + addStyle={"!px-1 !py-0 hover:text-lime-700"}/> + ); +} + +export default BlogTagCard; \ No newline at end of file diff --git a/src/components/common/FillButton.tsx b/src/components/common/FillButton.tsx index bbeb89e..603ee07 100644 --- a/src/components/common/FillButton.tsx +++ b/src/components/common/FillButton.tsx @@ -1,10 +1,18 @@ import {Link} from "react-router-dom"; -const className = " bg-lime-500 hover:bg-lime-400 text-white font-bold py-2 px-4 rounded hover:cursor-pointer"; +const className = " bg-lime-500 hover:brightness-105 text-white text-sm font-semibold py-2 px-4 rounded hover:cursor-pointer"; -export function FillButton({text, onClick, addStyle}: { text: string, onClick: () => void, addStyle?: string }) { +export function FillButton({text, onClick, addStyle, disabled}: { + text: string, + onClick: () => void, + addStyle?: string, + disabled?: boolean +}) { return ( - ); @@ -12,14 +20,22 @@ export function FillButton({text, onClick, addStyle}: { text: string, onClick: ( export function FillLink({text, to, addStyle}: { text: string, to: string, addStyle?: string }) { return ( - + {text} ); } -export function LoadMoreButton({onClick, addStyle}: { onClick: () => void, addStyle?: string }) { +export function LoadMoreButton({onClick, addStyle, disabled}: { + onClick: () => void, + addStyle?: string, + disabled?: boolean +}) { return ( - + ); } \ No newline at end of file diff --git a/src/components/common/Header.tsx b/src/components/common/Header.tsx index 0c9f3f4..fe8d40e 100644 --- a/src/components/common/Header.tsx +++ b/src/components/common/Header.tsx @@ -98,9 +98,9 @@ function Header() { className="w-full block px-4 py-2 text-gray-700 hover:bg-gray-100"> 내 블로그 - - 설정 + 프로필 설정
diff --git a/src/components/common/IconButton.tsx b/src/components/common/IconButton.tsx index 4c9b0f6..0995c47 100644 --- a/src/components/common/IconButton.tsx +++ b/src/components/common/IconButton.tsx @@ -1,8 +1,8 @@ import {ReactNode} from 'react'; -function IconButton({icon, onClick}: { icon: ReactNode; onClick: () => void }) { +function IconButton({icon, onClick, addStyle}: { icon: ReactNode; onClick: () => void, addStyle?: string }) { return ( - ); diff --git a/src/components/common/OutlineButton.tsx b/src/components/common/OutlineButton.tsx index 3b59dd3..8e62863 100644 --- a/src/components/common/OutlineButton.tsx +++ b/src/components/common/OutlineButton.tsx @@ -4,7 +4,7 @@ const className = " bg-transparent hover:bg-lime-300 text-lime-700 font-semibold export function OutlineButton({text, onClick, addStyle}: { text: string, onClick?: () => void, addStyle?: string }) { return ( - ); @@ -12,7 +12,7 @@ export function OutlineButton({text, onClick, addStyle}: { text: string, onClick export function OutlineLink({text, to, addStyle}: { text: string, to: string, addStyle?: string }) { return ( - + {text} ); diff --git a/src/components/common/PaginationButton.tsx b/src/components/common/PaginationButton.tsx index c8f8082..992ae3a 100644 --- a/src/components/common/PaginationButton.tsx +++ b/src/components/common/PaginationButton.tsx @@ -1,5 +1,8 @@ import {PageResponse} from "../../common/types/common.tsx"; -import {MdArrowLeft, MdArrowRight} from "react-icons/md"; +import { + MdKeyboardDoubleArrowLeft, + MdKeyboardDoubleArrowRight +} from "react-icons/md"; import {useEffect, useState} from "react"; function PaginationButton({pageInfo, setPage}: { @@ -22,40 +25,82 @@ function PaginationButton({pageInfo, setPage}: { } else { setPageList(getArray(startPage, paginationSize)); } - }, [startPage]); + }, [startPage, pageInfo]); return ( -
- - {pageList.map((page) => ( - )} +
+ - ))} - -
+ + //
+ // + // {pageList.map((page) => ( + // + // ))} + // + //
); + + } export default PaginationButton; \ No newline at end of file diff --git a/src/components/common/TextButton.tsx b/src/components/common/TextButton.tsx index 64f7e80..fd80149 100644 --- a/src/components/common/TextButton.tsx +++ b/src/components/common/TextButton.tsx @@ -4,7 +4,7 @@ const className = " flex justify-center items-center bg-transparent py-2 px-4 ho export function TextButton({text, onClick, addStyle}: { text: string, onClick?: () => void, addStyle?: string }) { return ( - ); @@ -13,7 +13,7 @@ export function TextButton({text, onClick, addStyle}: { text: string, onClick?: export function TextLink({text, to, addStyle}: { text: string, to: string, addStyle?: string }) { return ( - + {text} ); diff --git a/src/components/setting/FolderCardList.tsx b/src/components/folder/FolderCardList.tsx similarity index 94% rename from src/components/setting/FolderCardList.tsx rename to src/components/folder/FolderCardList.tsx index 610bdba..16845a8 100644 --- a/src/components/setting/FolderCardList.tsx +++ b/src/components/folder/FolderCardList.tsx @@ -5,10 +5,11 @@ import {CSS} from "@dnd-kit/utilities"; import {FillButton} from "../common/FillButton.tsx"; import {MdOutlineMenu} from "react-icons/md"; import {TextButton} from "../common/TextButton.tsx"; +import {restrictToVerticalAxis} from "@dnd-kit/modifiers"; function FolderCardList({ folders, - depth, + depth = 0, editFolderId, editFolderTitle, setEditFolderId, @@ -21,7 +22,7 @@ function FolderCardList({ setOpenMoveModal }: { folders: FolderType[], - depth: number, + depth?: number, editFolderId: string, editFolderTitle: string, setEditFolderId: (editFolderId: string) => void, @@ -33,8 +34,9 @@ function FolderCardList({ setOpenMoveModal: (openMoveModal: boolean) => void, setSelectedFolder: (selectedFolder: FolderType) => void, }) { + return ( - + {folders.map((folder: FolderType) => ( setEditFolderId("")} addStyle={"!bg-gray-400 hover:brightness-110"}/> handleEdit({...folder, title: editFolderTitle})}/> + onClick={() => handleEdit({...folder, title: editFolderTitle})} + addStyle={`${folder.title === editFolderTitle && "opacity-50 hover:!cursor-auto"}`} + disabled={folder.title === editFolderTitle}/> :
diff --git a/src/components/setting/FolderMoveModal.tsx b/src/components/folder/FolderMoveModal.tsx similarity index 100% rename from src/components/setting/FolderMoveModal.tsx rename to src/components/folder/FolderMoveModal.tsx diff --git a/src/components/blog/CategorySelectBox.tsx b/src/components/folder/FolderSelectBox.tsx similarity index 74% rename from src/components/blog/CategorySelectBox.tsx rename to src/components/folder/FolderSelectBox.tsx index 10916ff..6eafbc6 100644 --- a/src/components/blog/CategorySelectBox.tsx +++ b/src/components/folder/FolderSelectBox.tsx @@ -1,11 +1,12 @@ import {FolderType} from "../../common/types/blog.tsx"; import {MdOutlineArrowDropDown} from "react-icons/md"; import {useEffect, useRef, useState} from "react"; +import {getFolderTitle} from "../../common/util/string.tsx"; -function CategorySelectBox({folders, depth, selectedFolder, targetFolder, setTargetFolder, center}: { +function FolderSelectBox({folders, depth = 0, selectedFolder, targetFolder, setTargetFolder, center}: { folders: FolderType[], - depth: number, - selectedFolder: FolderType, + depth?: number, + selectedFolder?: FolderType, targetFolder: FolderType, setTargetFolder: (folder: FolderType) => void, center?: boolean, @@ -35,13 +36,13 @@ function CategorySelectBox({folders, depth, selectedFolder, targetFolder, setTar
+ className={`${folderOpen ? "" : "hidden"} h-72 min-h-16 overflow-y-scroll absolute z-50 w-full top-12 left-0 bg-white divide-y divide-gray-300 rounded-lg shadow-sm`}> {folders.map((folder) => - void, setFolderOpen: (open: boolean) => void, }) { - return folder.id !== selectedFolder.id ? ( + + return !selectedFolder || folder.id !== selectedFolder.id ? (
{folder.subFolders.length > 0 && folder.subFolders.map((subFolder => - ; } -export default CategorySelectBox; \ No newline at end of file +export default FolderSelectBox; \ No newline at end of file diff --git a/src/components/post/PostCard.tsx b/src/components/post/PostCard.tsx index 32c0464..a3305a1 100644 --- a/src/components/post/PostCard.tsx +++ b/src/components/post/PostCard.tsx @@ -4,6 +4,7 @@ import DOMPurify from "dompurify"; import {MdImage} from "react-icons/md"; import {dateToKorean} from "../../common/util/date.tsx"; import {Link} from "react-router-dom"; +import {FaRegComment, FaRegHeart} from "react-icons/fa6"; function PostCard(post: PostResponse) { @@ -22,13 +23,25 @@ function PostCard(post: PostResponse) {
}
-
- - {post.username} - -
- {dateToKorean(post.createdAt)} +
+
+ + {post.username} + +
+ {dateToKorean(post.createdAt)} +
+
+
+
+ +

20

+
+
+ +

10

+
diff --git a/src/components/setting/FolderAddModal.tsx b/src/components/setting/FolderAddModal.tsx deleted file mode 100644 index ee9d235..0000000 --- a/src/components/setting/FolderAddModal.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import ModalLayout from "../../layout/ModalLayout.tsx"; -import {useState} from "react"; -import {FillButton} from "../common/FillButton.tsx"; -import {TextButton} from "../common/TextButton.tsx"; -import {MdOutlineArrowDropDown} from "react-icons/md"; -import {FolderType} from "../../common/types/blog.tsx"; - -function FolderAddModal({folders, setShowFolderAddModal}: { - folders: FolderType[], - setShowFolderAddModal: (modal: boolean) => void -}) { - - const [inputFolder, setInputFolder] = useState(""); - const [folderOpen, setFolderOpen] = useState(false); - const [selectedFolder, setSelectedFolder] = useState("블로그"); - - return ( - -
-

폴더 추가

- -
-
- -
- {folders.map((folder) => { - if (!folder.subFolders) { - return
- -
- } else { - return
- - {folder.subFolders.map((subFolder: FolderType) => - - )} -
; - } - })} -
- setInputFolder(e.target.value)} - placeholder="폴더 이름을 입력해주세요." - className="border border-gray-400 p-4 font-bold"/> -
- setShowFolderAddModal(false)}/> - { - alert("폴더가 추가되었습니다."); - setShowFolderAddModal(false); - }}/> -
-
-
- ); -} - -export default FolderAddModal; \ No newline at end of file diff --git a/src/components/setting/SettingSideBar.tsx b/src/components/setting/SettingSideBar.tsx new file mode 100644 index 0000000..fcebca3 --- /dev/null +++ b/src/components/setting/SettingSideBar.tsx @@ -0,0 +1,41 @@ +interface TabType { + section: string; + title: string; +} + +function SettingSideBar({setSelectedSection}: { + setSelectedSection: (section: string) => void, + side?: boolean, +}) { + + const tabList: TabType[] = [ + {section: "profile", title: "프로필"}, + {section: "folder", title: "폴더"}, + {section: "post", title: "게시글"}, + ]; + + const handleSelectedTab = (tabSection: string) => { + const tab = tabList.find(tab => tab.section === tabSection); + if (tab) { + setSelectedSection(tab.section); + } + } + + return ( +
+
    + {tabList.map((tab) => +
  • + +
  • )} +
+
+ ); +} + +export default SettingSideBar; \ No newline at end of file diff --git a/src/pages/blog/BlogPage.tsx b/src/pages/blog/BlogPage.tsx index 113b51a..a2972f7 100644 --- a/src/pages/blog/BlogPage.tsx +++ b/src/pages/blog/BlogPage.tsx @@ -1,27 +1,93 @@ import BasicLayout from "../../layout/BasicLayout.tsx"; -import {useParams, useSearchParams} from "react-router-dom"; +import {useNavigate, useParams} from "react-router-dom"; import {faker} from "@faker-js/faker/locale/ko"; import PostCard from "../../components/post/PostCard.tsx"; -import TagCard from "../../components/post/TagCard.tsx"; import {useEffect, useRef, useState} from "react"; import {MdMenu, MdOutlineExitToApp} from "react-icons/md"; import PaginationButton from "../../components/common/PaginationButton.tsx"; -import TagChip from "../../components/post/TagChip.tsx"; -import {OutlineLink} from "../../components/common/OutlineButton.tsx"; -import {useSelector} from "react-redux"; -import {RootState} from "../../store.tsx"; +import {FolderType} from "../../common/types/blog.tsx"; +import BlogSideBar from "../../components/blog/BlogSideBar.tsx"; +import IconButton from "../../components/common/IconButton.tsx"; +import {PageResponse} from "../../common/types/common.tsx"; function BlogPage() { const {username} = useParams(); - const [searchParams, setSearchParams] = useSearchParams({"folder": ""}); + const [page, setPage] = useState(0); + const [pageInfo, setPageInfo] = useState({number: 0, size: 5, totalElements: 53, totalPages: 11}); + const folderData: FolderType[] = [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + ], + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + ] + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + ], + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + ] + }, + ]; + const [folders, setFolders] = useState([]); const [isOpen, setIsOpen] = useState(false); - const [selectedFolder, setSelectedFolder] = useState(searchParams.get("folder") || ""); + const [selectedFolder, setSelectedFolder] = useState(null); const [selectedTagList, setSelectedTagList] = useState([]); - const mainRef = useRef(null); const sideBarRef = useRef(null); const handleMenuOpen = () => { @@ -37,22 +103,12 @@ function BlogPage() { setSelectedTagList([...selectedTagList, selectTag]); } - const removeTag = (selectTag: string) => { - setSelectedTagList(prevState => prevState.filter(tag => tag !== selectTag)); - } - - const removeFolder = (selectFolder: string) => { - console.log(selectFolder); - setSelectedFolder(""); - } - useEffect(() => { - if (sideBarRef.current && mainRef.current) { - sideBarRef.current.style.height = `${mainRef.current.offsetHeight + 220}px`; - } + // todo: 내 게시글 불러오기 api + console.log(page, setPageInfo.toString()); + setFolders(folderData); }, []); - useEffect(() => { document.addEventListener('mousedown', handleClickOutside); document.title = username || "DIGLOG"; @@ -63,44 +119,36 @@ function BlogPage() { }; }, []); + const navigate = useNavigate(); useEffect(() => { - setSearchParams({ - "folder": selectedFolder - }) + navigate(`/blog/${username}?folder=${selectedFolder?.id || ""}`); }, [selectedFolder]); useEffect(() => { if (isOpen) { - document.body.classList.remove('overflow-x-hidden'); + document.body.style.overflow = 'hidden'; } else { - document.body.classList.add('overflow-x-hidden'); + document.body.style.overflow = 'auto'; } return () => { - document.body.classList.remove('overflow-x-hidden'); + document.body.style.overflow = 'auto'; }; }, [isOpen]); return ( -
-
+
+
{username}의 블로그
- -
-
-
- 폴더 {selectedFolder !== "" && } -
-
- 태그 {selectedTagList.map((tag) => )} -
+ } + onClick={handleMenuOpen} + addStyle="lg:hidden"/>
-
+
{[Array.from({length: 3}).map(() => ( `} username={username || faker.animal.cat()} tags={[{ - id: faker.number.int().toString(), + id: crypto.randomUUID(), name: faker.word.sample() - }, {id: faker.number.int().toString(), name: faker.word.sample()}]} + }, {id: crypto.randomUUID(), name: faker.word.sample()}]} createdAt={new Date()}/> ))]} { - }}/> + pageInfo={pageInfo} setPage={setPage}/>
- @@ -136,78 +184,16 @@ function BlogPage() { onClick={() => setIsOpen(false)}> - + bgColor={"bg-gray-50"} + side={true}/>
); } -function SideBar({username, addTag, setSelectedFolder, bgColor}: { - username: string | undefined, - addTag: (tagName: string) => void, - setSelectedFolder: (folder: string) => void, - bgColor?: string -}) { - - const loginState = useSelector((state: RootState) => state.loginSlice); - - return ( -
-
- username -
- {username} -
- {username === loginState.username && ( -
- - -
- )} -
-
-
폴더
-
- {[Array.from({length: 10}).map((_, i) => ( -
- -
- {Array.from({length: 3}).map((_, i) => ( - - ))} -
-
- ))]} -
-
-
-
태그
-
- {[Array.from({length: 24}).map(() => ( - - ))]} -
-
-
- ); -} - export default BlogPage; \ No newline at end of file diff --git a/src/pages/member/CodePage.tsx b/src/pages/member/CodePage.tsx index b0ecab0..f64804a 100644 --- a/src/pages/member/CodePage.tsx +++ b/src/pages/member/CodePage.tsx @@ -14,27 +14,30 @@ function CodePage() { const [loading, setLoading] = useState(false); const inputRefs = useRef([]); - const [code, setCode] = useState(Array(6).fill("")); + const [code, setCode] = useState(""); const [timer, setTimer] = useState(600); const handleChange = (index: number, value: string) => { - if (/[^0-9]/g.test(value)) { - return; - } + let newCode = code; + for (const digit of value.split("")) { + if (/[^0-9]/g.test(digit)) { + return; + } - const newCode = [...code]; + newCode += digit; + } - newCode[index] = value.replace(/[^0-9]/g, ""); - setCode(newCode); + setCode(newCode.substring(0, 6)); if (value && index < inputRefs.current.length - 1) { - inputRefs.current[index + 1].focus(); + inputRefs.current[index + Math.min(value.length, 5)].focus(); } }; const handleBackspace = (event: React.KeyboardEvent, index: number) => { - if (event.key === "Backspace" && !event.currentTarget.value && index > 0) { + if (event.key === "Backspace" && index > 0) { + setCode(code.substring(0, index - 1)); inputRefs.current[index - 1].focus(); } }; @@ -61,14 +64,19 @@ function CodePage() { }, [timer]); useEffect(() => { - if (code[5] !== "") { + if (code.length >= 6) { setLoading(true); - checkCode(email, code.join("")) + checkCode(email, code) .then(() => { - navigate("/signup", {state: {email: email, code: code.join("")}}); + navigate("/signup", {state: {email: email, code: code}}); + }) + .catch((error) => { + alert(error.response.data.message); + if (inputRefs.current) { + inputRefs.current[5].focus(); + } }) - .catch((error) => alert(error.response.data.message)) .finally(() => setLoading(false)); } }, [code]); @@ -82,7 +90,7 @@ function CodePage() {

인증코드 6자리를 입력해주세요.

- {code.map((digit, index) => ( + {Array.from({length: 6}).map((_, index) => ( { @@ -90,10 +98,10 @@ function CodePage() { inputRefs.current[index] = el; } }} - type=" text" - maxLength={1} + type="text" + maxLength={6} className="w-12 h-16 rounded-lg font-bold text-lg appearance-none border border-gray-200 text-center focus:outline-1" - value={digit} + value={code[index] ?? ""} onChange={(e) => handleChange(index, e.target.value)} onKeyDown={(e) => { handleBackspace(e, index) diff --git a/src/pages/post/PostPage.tsx b/src/pages/post/PostPage.tsx index 42dab10..5ad2f13 100644 --- a/src/pages/post/PostPage.tsx +++ b/src/pages/post/PostPage.tsx @@ -8,15 +8,11 @@ import {useEffect, useState} from "react"; import {PostResponse} from "../../common/types/post.tsx"; import {checkUUID} from "../../common/util/regex.tsx"; import {sortTagByName} from "../../common/util/sort.tsx"; -import {useSelector} from "react-redux"; -import {RootState} from "../../store.tsx"; -import {FillLink} from "../../components/common/FillButton.tsx"; function PostPage() { const {id} = useParams(); const navigate = useNavigate(); - const loginState = useSelector((state: RootState) => state.loginSlice); const [post, setPost] = useState({ id: "", @@ -53,8 +49,6 @@ function PostPage() {
- {(loginState.username === post.username) - &&
}
Home
{` > `}
@@ -62,8 +56,6 @@ function PostPage() {
{` > `}
{post.title}
- {(loginState.username === post.username) - && }
state.loginSlice); const navigate = useNavigate(); - const folderRef = useRef(null); const path = useLocation().pathname.substring(0, location.pathname.lastIndexOf("/")); const {id} = useParams(); @@ -43,13 +43,9 @@ function WritePage() { }); const [showTag, setShowTag] = useState(false); - const [folderOpen, setFolderOpen] = useState(false); - const [selectedFolder, setSelectedFolder] = useState("폴더 선택"); + const [targetFolder, setTargetFolder] = useState({id: crypto.randomUUID(), title: "", subFolders: []}); const [uploadCount, setUploadCount] = useState(0); const [exitPage, setExitPage] = useState(false); - const handleFolderOpen = () => { - setFolderOpen(prev => !prev); - } const removeTag = (tag: string | null) => { setPost({...post, tags: post.tags.filter(prevTag => prevTag !== tag)}); @@ -131,12 +127,6 @@ function WritePage() { .catch((error) => alert(error.response.data.message)); } - const handleClickOutside = (event: MouseEvent) => { - if (folderRef.current && !folderRef.current.contains(event.target as Node)) { - setFolderOpen(false); - } - }; - // 뒤로가기 방지 useBlocker(() => { return (!!post.title || !!post.content) && @@ -151,12 +141,10 @@ function WritePage() { event.preventDefault(); }; - document.addEventListener('mousedown', handleClickOutside); window.addEventListener('beforeunload', handleBeforeUnload); return () => { window.removeEventListener('beforeunload', handleBeforeUnload); - document.removeEventListener('mousedown', handleClickOutside); }; }, []); @@ -168,7 +156,13 @@ function WritePage() { { id: crypto.randomUUID(), title: faker.lorem.words(), - subFolders: [], + subFolders: [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + ], }, { id: crypto.randomUUID(), @@ -180,7 +174,13 @@ function WritePage() { { id: crypto.randomUUID(), title: faker.lorem.words(), - subFolders: [], + subFolders: [ + { + id: crypto.randomUUID(), + title: faker.lorem.words(), + subFolders: [], + }, + ], }, { id: crypto.randomUUID(), @@ -245,54 +245,10 @@ function WritePage() {
-
- -
- {folderData.map((folder) => { - if (!folder.subFolders) { - return
- -
- } else { - return
- - {folder.subFolders.map((subFolder: FolderType) => - - )} -
; - } - })} -
+
+
diff --git a/src/pages/setting/FolderSettingPage.tsx b/src/pages/setting/FolderSettingPage.tsx index b34bb39..623b7f5 100644 --- a/src/pages/setting/FolderSettingPage.tsx +++ b/src/pages/setting/FolderSettingPage.tsx @@ -3,10 +3,10 @@ import {useEffect, useRef, useState} from "react"; import {FolderResponse, FolderType, toFolderRequestList, toFolderTypeList} from "../../common/types/blog.tsx"; import {FillButton} from "../../components/common/FillButton.tsx"; import ModalLayout from "../../layout/ModalLayout.tsx"; -import CategorySelectBox from "../../components/blog/CategorySelectBox.tsx"; import {DragEndEvent} from "@dnd-kit/core"; -import FolderCardList from "../../components/setting/FolderCardList.tsx"; +import FolderCardList from "../../components/folder/FolderCardList.tsx"; import {arrayMove} from "@dnd-kit/sortable"; +import FolderSelectBox from "../../components/folder/FolderSelectBox.tsx"; function FolderSettingPage() { @@ -361,7 +361,6 @@ function FolderSettingPage() {

폴더 관리

{selectedFolder.title} 폴더를

- ([]); + const [page, setPage] = useState(0); + const [pageInfo, setPageInfo] = useState({number: 0, size: 5, totalElements: 0, totalPages: 0}); + + useEffect(() => { + // todo: 본인 게시글 api로 변경 + getPosts({ + sorts: ["createdAt"], + page: page, + size: pageInfo.size, + isDescending: true, + }) + .then((res) => { + setPosts([...res.data.content]); + setPageInfo(res.data.page); + }) + .catch((error) => alert(error.response.data.message)); + }, [page]); + return (
-

게시글 관리

+
+

게시글 관리

+
+ + +
+
+
+ {posts.map((post: PostResponse) => ( +
+
+

{post.title}

+

{fullDateToKorean(post.createdAt)}

+
+
+ +
+
+ ))} +
+
); } diff --git a/src/pages/setting/SettingPage.tsx b/src/pages/setting/SettingPage.tsx index c422191..099c9a2 100644 --- a/src/pages/setting/SettingPage.tsx +++ b/src/pages/setting/SettingPage.tsx @@ -1,40 +1,34 @@ import BasicLayout from "../../layout/BasicLayout.tsx"; -import {useState} from "react"; +import {useEffect, useState} from "react"; import PostSettingPage from "./PostSettingPage.tsx"; import ProfileSettingPage from "./ProfileSettingPage.tsx"; import FolderSettingPage from "./FolderSettingPage.tsx"; +import {useNavigate, useParams} from "react-router-dom"; +import SettingSideBar from "../../components/setting/SettingSideBar.tsx"; function SettingPage() { - const tabList = ["프로필", "폴더", "게시글"]; + const {section} = useParams(); + const navigate = useNavigate(); + const [selectedSection, setSelectedSection] = useState(section || "profile"); - const [selectedTab, setSelectedTab] = useState("프로필"); + useEffect(() => { + navigate(`/setting/${selectedSection}`); + }, [selectedSection]); return (
-
-
    - {tabList.map((tab) => -
  • - -
  • )} -
-
- {(selectedTab === "프로필") && + + {(selectedSection === "profile") &&
} - {(selectedTab === "폴더") && + {(selectedSection === "folder") &&
} - {(selectedTab === "게시글") && + {(selectedSection === "post") &&
}