From 44522e9d728155a40b756f39b674f9f1ae2794bb Mon Sep 17 00:00:00 2001 From: 21120447 Date: Sun, 9 Jun 2024 11:44:13 +0700 Subject: [PATCH] refactor: clean code for novel chapter --- src/components/Reading/ChapterInfo.tsx | 27 +++ src/components/Reading/Content.tsx | 27 +++ src/components/Reading/GroupButtonControl.tsx | 39 +++++ .../Reading/GroupHandleChapterBottom.tsx | 35 ++++ .../Reading/GroupHandleChapterTop.tsx | 32 ++++ src/hooks/useChangeChapter.tsx | 55 +++++++ src/pages/NovelChapter.tsx | 155 ++++-------------- 7 files changed, 243 insertions(+), 127 deletions(-) create mode 100644 src/components/Reading/ChapterInfo.tsx create mode 100644 src/components/Reading/Content.tsx create mode 100644 src/components/Reading/GroupButtonControl.tsx create mode 100644 src/components/Reading/GroupHandleChapterBottom.tsx create mode 100644 src/components/Reading/GroupHandleChapterTop.tsx create mode 100644 src/hooks/useChangeChapter.tsx diff --git a/src/components/Reading/ChapterInfo.tsx b/src/components/Reading/ChapterInfo.tsx new file mode 100644 index 0000000..1241ccd --- /dev/null +++ b/src/components/Reading/ChapterInfo.tsx @@ -0,0 +1,27 @@ +import { Link } from "react-router-dom"; +import GuideText from "./GuideText"; +import { HiUser } from "react-icons/hi2"; +import { IChapter } from "../../types/novel"; + +const ChapterInfo = ({ chapter, server }: { chapter: IChapter; server: string }) => { + return ( + <> + + {chapter.novelName} + + + + {chapter.author.name} + + + + ); +}; + +export default ChapterInfo; diff --git a/src/components/Reading/Content.tsx b/src/components/Reading/Content.tsx new file mode 100644 index 0000000..957ee88 --- /dev/null +++ b/src/components/Reading/Content.tsx @@ -0,0 +1,27 @@ +import { useContext } from "react"; +import { AppState } from "../../store"; +import { useSelector } from "react-redux"; +import { SettingsContext } from "../../contexts/SettingsContext"; + +const Content = ({ content }: { content: string }) => { + const { color } = useContext(SettingsContext)!; + const settings = useSelector((state: AppState) => state.settings); + + return ( +
+ ); +}; + +export default Content; diff --git a/src/components/Reading/GroupButtonControl.tsx b/src/components/Reading/GroupButtonControl.tsx new file mode 100644 index 0000000..fc8e1ea --- /dev/null +++ b/src/components/Reading/GroupButtonControl.tsx @@ -0,0 +1,39 @@ +import { Dispatch, SetStateAction } from "react"; +import ButtonBookmark from "../Button/ButtonBookmark"; +import ButtonUtils from "../Button/ButtonUtils"; + +import { IoSettingsOutline } from "react-icons/io5"; +import { MdOutlineFormatListBulleted } from "react-icons/md"; +import { IChapter } from "../../types/novel"; + +interface Props { + setOpenSettingPopup: Dispatch>; + setOpenChapterPopup: Dispatch>; + chapter: IChapter; +} + +const GroupButtonControl = (props: Props) => { + return ( +
+ props.setOpenSettingPopup(true)}> + + Cấu hình + + + props.setOpenChapterPopup(true)}> + + Mục lục + + + +
+ ); +}; + +export default GroupButtonControl; diff --git a/src/components/Reading/GroupHandleChapterBottom.tsx b/src/components/Reading/GroupHandleChapterBottom.tsx new file mode 100644 index 0000000..272feab --- /dev/null +++ b/src/components/Reading/GroupHandleChapterBottom.tsx @@ -0,0 +1,35 @@ +import ButtonChangeChapter from "../Button/ButtonChangeChapter"; + +import { RiSkipLeftLine } from "react-icons/ri"; +import { RiSkipRightLine } from "react-icons/ri"; + +const GroupHandleChapterBottom = ({ + isShowPrevButton, + isShowNextButton, + handlePrevChapter, + handleNextChapter, +}: { + isShowPrevButton: boolean; + isShowNextButton: boolean; + handlePrevChapter: () => void; + handleNextChapter: () => void; +}) => { + return ( +
+ {isShowPrevButton && ( + + + TRƯỚC + + )} + {isShowNextButton && ( + + + SAU + + )} +
+ ); +}; + +export default GroupHandleChapterBottom; diff --git a/src/components/Reading/GroupHandleChapterTop.tsx b/src/components/Reading/GroupHandleChapterTop.tsx new file mode 100644 index 0000000..3b87bda --- /dev/null +++ b/src/components/Reading/GroupHandleChapterTop.tsx @@ -0,0 +1,32 @@ +import { GrNext } from "react-icons/gr"; +import { GrPrevious } from "react-icons/gr"; + +const GroupHandleChapterTop = ({ + handlePrevChapter, + handleNextChapter, + chapterName, +}: { + handlePrevChapter: () => void; + handleNextChapter: () => void; + chapterName: string; +}) => { + return ( +
+ +
{chapterName}
+ +
+ ); +}; + +export default GroupHandleChapterTop; diff --git a/src/hooks/useChangeChapter.tsx b/src/hooks/useChangeChapter.tsx new file mode 100644 index 0000000..4e4f74a --- /dev/null +++ b/src/hooks/useChangeChapter.tsx @@ -0,0 +1,55 @@ +import { useNavigate } from "react-router-dom"; +import { toast } from "react-toastify"; +import { IChapter } from "../types/novel"; +import { useKeyboardShortcut } from "./useKeyboardShortcut"; + +interface Props { + chapter: IChapter | null; + chapterId: string | undefined; + novelId: string | undefined; + isActive: boolean; +} + +const useChangeChapter = ({ chapter, chapterId, novelId, isActive }: Props) => { + const navigate = useNavigate(); + + const handleNextChapter = () => { + if (chapter == null || chapterId == null) return; + if (!chapter.nextChapterId || chapter.nextChapterId.length <= 0) { + toast.error("Hiện tại đây đã là chương cuối", { + toastId: "last-chapter", + }); + return; + } + toast.dismiss(); + navigate(`/truyen/${novelId}/${chapter.nextChapterId}`); + }; + + const handlePrevChapter = () => { + if (chapter == null || chapterId == null) return; + if (!chapter.preChapterId || chapter.preChapterId.length <= 0) { + toast.error("Đây đã là chương đầu tiên", { + toastId: "first-chapter", + }); + return; + } + toast.dismiss(); + navigate(`/truyen/${novelId}/${chapter.preChapterId}`); + }; + + useKeyboardShortcut({ + isActive, + key: "ArrowLeft", + onKeyPressed: handlePrevChapter, + }); + + useKeyboardShortcut({ + isActive, + key: "ArrowRight", + onKeyPressed: handleNextChapter, + }); + + return { handleNextChapter, handlePrevChapter }; +}; + +export default useChangeChapter; diff --git a/src/pages/NovelChapter.tsx b/src/pages/NovelChapter.tsx index 27e4b62..92eaad8 100644 --- a/src/pages/NovelChapter.tsx +++ b/src/pages/NovelChapter.tsx @@ -1,9 +1,8 @@ import { useContext, useEffect, useState } from "react"; import Slider from "../components/Slider"; -import { Link, useNavigate, useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { IChapter } from "../types/novel"; -import ButtonUtils from "../components/Button/ButtonUtils"; import { SettingsContext } from "../contexts/SettingsContext"; import SettingPopup from "../components/Popup/SettingPopup"; import ChapterPopup from "../components/Popup/ChapterPopup"; @@ -11,28 +10,21 @@ import { IResponse } from "../types/response"; import { useQuery } from "@tanstack/react-query"; import { ApiGetOneChapter } from "../api/apiNovel"; import NovelChapterSkeleton from "../components/Loading/NovelChapterSkeleton"; -import ButtonChangeChapter from "../components/Button/ButtonChangeChapter"; -import { RiSkipLeftLine } from "react-icons/ri"; -import { RiSkipRightLine } from "react-icons/ri"; -import { IoSettingsOutline } from "react-icons/io5"; -import { MdOutlineFormatListBulleted } from "react-icons/md"; -import { GrNext } from "react-icons/gr"; -import { GrPrevious } from "react-icons/gr"; -import { HiUser } from "react-icons/hi2"; - -import ButtonBookmark from "../components/Button/ButtonBookmark"; import { useDispatch, useSelector } from "react-redux"; import { AppDispatch, AppState } from "../store"; import { updateNovelReaded } from "../store/history"; import { addNovelReaded } from "../store/readed"; import { setIsOpen } from "../store/chapterOpen"; -import { toast } from "react-toastify"; import KanbanSelectServer from "../components/Button/KanbanSelectServer"; -import { useKeyboardShortcut } from "../hooks/useKeyboardShortcut"; -import GuideText from "../components/Reading/GuideText"; import MyHelmet from "../components/MyHelmet"; import { subSlugChapter } from "../utils/helpers"; +import useChangeChapter from "../hooks/useChangeChapter"; +import Content from "../components/Reading/Content"; +import ChapterInfo from "../components/Reading/ChapterInfo"; +import GroupHandleChapterTop from "../components/Reading/GroupHandleChapterTop"; +import GroupButtonControl from "../components/Reading/GroupButtonControl"; +import GroupHandleChapterBottom from "../components/Reading/GroupHandleChapterBottom"; const NovelChapter = () => { const navigate = useNavigate(); @@ -42,9 +34,8 @@ const NovelChapter = () => { const [openChapterPopup, setOpenChapterPopup] = useState(false); const [successServer, setSuccessServer] = useState(""); - const { color, background } = useContext(SettingsContext)!; + const { background } = useContext(SettingsContext)!; - const settings = useSelector((state: AppState) => state.settings); const { server, listServer } = useSelector((state: AppState) => state.server); const dispatch = useDispatch(); const [indexServer, setIndexServer] = useState(0); @@ -101,30 +92,6 @@ const NovelChapter = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [chapter]); - const handleNextChapter = () => { - if (chapter == null || chapterId == null) return; - if (!chapter.nextChapterId || chapter.nextChapterId.length <= 0) { - toast.error("Hiện tại đây đã là chương cuối", { - toastId: "last-chapter", - }); - return; - } - toast.dismiss(); - navigate(`/truyen/${novelId}/${chapter.nextChapterId}`); - }; - - const handlePrevChapter = () => { - if (chapter == null || chapterId == null) return; - if (!chapter.preChapterId || chapter.preChapterId.length <= 0) { - toast.error("Đây đã là chương đầu tiên", { - toastId: "first-chapter", - }); - return; - } - toast.dismiss(); - navigate(`/truyen/${novelId}/${chapter.preChapterId}`); - }; - useEffect(() => { setFlagListServer(listServer); setIndexServer(0); @@ -143,17 +110,8 @@ const NovelChapter = () => { const _isLoading = chapter === null || isFetching || novelId == null || chapterId == undefined; - useKeyboardShortcut({ - isActive: !openChapterPopup && !openSettingPopup && !_isLoading, - key: "ArrowLeft", - onKeyPressed: handlePrevChapter, - }); - - useKeyboardShortcut({ - isActive: !openChapterPopup && !openSettingPopup && !_isLoading, - key: "ArrowRight", - onKeyPressed: handleNextChapter, - }); + const isActive = !openChapterPopup && !openSettingPopup && !_isLoading; + const { handleNextChapter, handlePrevChapter } = useChangeChapter({ chapter, chapterId, novelId, isActive }); if (_isLoading) return ; @@ -179,55 +137,18 @@ const NovelChapter = () => { />
- - {chapter.novelName} - - - - {chapter.author.name} - - -
- -
{chapter.name}
- -
- -
- setOpenSettingPopup(true)}> - - Cấu hình - - - setOpenChapterPopup(true)}> - - Mục lục - + + - -
+ { func={DoubleClickChangeServerSuccess} />
-
+ -
- {chapter.preChapterId && chapter.preChapterId.length >= 0 && ( - - - TRƯỚC - - )} - {chapter.nextChapterId && chapter.nextChapterId.length >= 0 && ( - - - SAU - - )} -
+ = 0} + isShowNextButton={chapter.nextChapterId?.length >= 0} + handlePrevChapter={handlePrevChapter} + handleNextChapter={handleNextChapter} + /> ); };