Skip to content

Commit

Permalink
pref: page slide animation (feat. route track)
Browse files Browse the repository at this point in the history
  • Loading branch information
SeungJL committed May 19, 2024
1 parent 4010a4f commit 782a951
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 140 deletions.
10 changes: 1 addition & 9 deletions components/atoms/buttons/ArrowBackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { faChevronLeft } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useRouter } from "next/navigation";
import { useRecoilState, useSetRecoilState } from "recoil";
import styled from "styled-components";

import { prevPageUrlState, slideDirectionState } from "../../../recoils/navigationRecoils";
interface IArrowBackButton {
url?: string;
}
export default function ArrowBackButton({ url }: IArrowBackButton) {
const router = useRouter();
const [prevPageUrl, setPrevPageUrl] = useRecoilState(prevPageUrlState);
const setSlideDirection = useSetRecoilState(slideDirectionState);

const handleGoBack = () => {
setSlideDirection("left");
if (prevPageUrl) {
router.push(prevPageUrl);
setPrevPageUrl(null);
} else if (url) router.push(url);
if (url) router.push(url);
else router.back();
};

Expand Down
8 changes: 4 additions & 4 deletions components/layouts/PageSlide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ interface IPageLayout {

function Slide({ children, isFixed, posZero }: IPageLayout) {
const [slideDirection, setSlideDirection] = useRecoilState(slideDirectionState);
console.log(slideDirection, 4);

useEffect(() => {
return () => {
setSlideDirection("right");
};
setSlideDirection("right");
}, []);

const variants = {
Expand All @@ -28,6 +26,7 @@ function Slide({ children, isFixed, posZero }: IPageLayout) {
opacity: 1,
},
};

const animationProps = slideDirection
? {
initial: "hidden",
Expand All @@ -37,6 +36,7 @@ function Slide({ children, isFixed, posZero }: IPageLayout) {
transition: { duration: 0.5 },
}
: {};

return (
<>
<motion.div
Expand Down
161 changes: 161 additions & 0 deletions components/layouts/PageTracker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { usePathname } from "next/navigation";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { useSetRecoilState } from "recoil";

import { BASE_BOTTOM_NAV_SEGMENT } from "../../pageTemplates/layout/Layout";
import { slideDirectionState } from "../../recoils/navigationRecoils";
import { parseUrlToSegments } from "../../utils/stringUtils";

const GATHER_WRITING_SEQUENCE = {
category: 1,
content: 2,
date: 3,
location: 4,
condition: 5,
};

const GROUP_WRITING_SEQUENCE = {
main: 1,
sub: 2,
guide: 3,
content: 4,
period: 5,
hasgTag: 6,
condition: 7,
};

function PageTracker() {
const router = useRouter();
const pathname = usePathname();
const setSlideDirection = useSetRecoilState(slideDirectionState);

useEffect(() => {
if (!pathname) return;

const determineSlideDirection = (currentSegments, prevSegments) => {
const curFirstSegment = currentSegments[0];

const setLeftSlide = () => setSlideDirection("left");
const setRightSlide = () => setSlideDirection("right");

switch (curFirstSegment) {
case "home":
setLeftSlide();
break;

case "study":
if (prevSegments[0] !== "home" && prevSegments[0] !== "studyList") {
setLeftSlide();
}
break;

case "user":
if (!currentSegments[1] && prevSegments[0] !== "home") {
setLeftSlide();
}
break;

case "event":
if (!currentSegments[1] && prevSegments[0] !== "home") {
setLeftSlide();
}
break;

case "store":
if (!currentSegments[1] && prevSegments[0] !== "event") {
setLeftSlide();
}
break;

case "member":
if (!currentSegments[2] && prevSegments[0] !== "home") {
setLeftSlide();
}
break;

case "gather":
handleWritingPage(
GATHER_WRITING_SEQUENCE,
currentSegments,
prevSegments,
setLeftSlide,
setRightSlide,
);
break;

case "group":
handleWritingPage(
GROUP_WRITING_SEQUENCE,
currentSegments,
prevSegments,
setLeftSlide,
setRightSlide,
);
break;

default:
break;
}
};

const handleWritingPage = (
pageSequence,
currentSegments,
prevSegments,
setLeftSlide,
setRightSlide,
) => {
if (!currentSegments[1]) {
setLeftSlide();
} else if (currentSegments[1] === "writing") {
if (!prevSegments[2]) {
setRightSlide();
} else {
const prevCategoryValue = pageSequence[prevSegments[2]];
const curCategoryValue = pageSequence[currentSegments[2]];

if (prevCategoryValue < curCategoryValue) {
setRightSlide();
} else {
setLeftSlide();
}
}
}
};

const handleRouterStart = (url) => {
if (!url || !pathname) return;
const prevSegments = parseUrlToSegments(pathname);
const currentSegments = parseUrlToSegments(url);

if (
prevSegments[0] !== currentSegments[0] &&
BASE_BOTTOM_NAV_SEGMENT.includes(prevSegments[0]) &&
BASE_BOTTOM_NAV_SEGMENT.includes(currentSegments[0])
) {
setSlideDirection(null);
return;
}

determineSlideDirection(currentSegments, prevSegments);
};

const handleRouterCompleted = (url) => {
if (url) {
setSlideDirection("right");
}
};

router.events.on("routeChangeStart", handleRouterStart);
router.events.on("routeChangeComplete", handleRouterCompleted);
return () => {
router.events.off("routeChangeStart", handleRouterStart);
router.events.off("routeChangeComplete", handleRouterCompleted);
};
}, [router.events, pathname, setSlideDirection]);

return null;
}

export default PageTracker;
2 changes: 1 addition & 1 deletion modals/home/writeDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default function WriteDrawer() {
color="red.400"
/>
<SocialButton
url="/group/writing/category/main"
url="/group/writing/main"
title="소그룹"
subTitle="비슷한 관심사의 인원들을 모아봐요"
icon={<FontAwesomeIcon icon={faCampfire} color="white" />}
Expand Down
7 changes: 2 additions & 5 deletions pageTemplates/gather/detail/GatherHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import dayjs from "dayjs";
import { useRouter } from "next/router";
import { useSession } from "next-auth/react";
import { useState } from "react";
import { useRecoilState, useSetRecoilState } from "recoil";
import { useSetRecoilState } from "recoil";
import styled from "styled-components";

import Header from "../../../components/layouts/Header";
import GatherKakaoShareModal from "../../../modals/gather/GatherKakaoShareModal";
import { isGatherEditState } from "../../../recoils/checkAtoms";
import { prevPageUrlState } from "../../../recoils/previousAtoms";
import { sharedGatherWritingState } from "../../../recoils/sharedDataAtoms";
import { IGather } from "../../../types/models/gatherTypes/gatherTypes";
import { IUserSummary } from "../../../types/models/userTypes/userInfoTypes";
Expand All @@ -30,20 +29,18 @@ function GatherHeader({ gatherData }: IGatherHeader) {
const { data: session } = useSession();
const setGatherWriting = useSetRecoilState(sharedGatherWritingState);
const setIsGatherEdit = useSetRecoilState(isGatherEditState);
const [prevPageUrl, setPrevPageUrl] = useRecoilState(prevPageUrlState);

const [isModal, setIsModal] = useState(false);

const onClick = () => {
setGatherWriting({ ...gatherData, date: dayjs(gatherData.date) });
setIsGatherEdit(true);
setPrevPageUrl(`/gather/${router.query.id}`);
router.push("/gather/writing/category");
};

return (
<>
<Header title="" url={prevPageUrl || "/gather"}>
<Header title="">
<Flex>
{session?.user.uid === (organizer as IUserSummary)?.uid && (
<IconWrapper onClick={onClick}>
Expand Down
2 changes: 1 addition & 1 deletion pageTemplates/group/detail/GroupHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function GroupHeader({ group }: IGroupHeader) {
const onClick = () => {
setGroupWriting(group);

router.push("/group/writing/category/main");
router.push("/group/writing/main");
};

const movePage = async () => {
Expand Down
54 changes: 9 additions & 45 deletions pageTemplates/layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@
import { config } from "@fortawesome/fontawesome-svg-core";
import { GoogleAnalytics } from "@next/third-parties/google";
import axios from "axios";
import { signOut, useSession } from "next-auth/react";
import { usePathname } from "next/navigation";
import { useRouter } from "next/router";
import { signOut, useSession } from "next-auth/react";
import { useEffect, useState } from "react";
import { useSetRecoilState } from "recoil";

import BottomNav from "../../components/BottomNav";
import GuestBottomNav from "../../components/layouts/atoms/GuestBottomNav";
import PageTracker from "../../components/layouts/PageTracker";
import { useToken } from "../../hooks/custom/CustomHooks";
import { useToast } from "../../hooks/custom/CustomToast";
import { slideDirectionState } from "../../recoils/navigationRecoils";
import { parseUrlToSegments } from "../../utils/stringUtils";
import BaseModal from "./BaseModal";
import BaseScript from "./BaseScript";
import Seo from "./Seo";

config.autoAddCss = false;

export const BASE_BOTTOM_NAV_SEGMENT = ["home", "statistics", "gather", "group"];
interface ILayout {
children: React.ReactNode;
}
Expand All @@ -34,23 +35,12 @@ function Layout({ children }: ILayout) {
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
const { data: session } = useSession();
const isGuest = session?.user.name === "guest";
const setSlideDirection = useSetRecoilState(slideDirectionState);

const [isErrorModal, setIsErrorModal] = useState(false);

function parseUrlToSegments(url) {
const queryStartIndex = url.indexOf("?");

const basePath = queryStartIndex >= 0 ? url.substring(0, queryStartIndex) : url;

const segments = basePath.split("/").filter(Boolean);

return segments;
}
const currentSegment = parseUrlToSegments(pathname)?.[0];

useEffect(() => {
console.log(3, pathname);
if (!pathname) return;
if (PUBLIC_SEGMENT.includes(segment)) return;
if (session === undefined) return;
const role = session?.user.role;
Expand All @@ -69,32 +59,7 @@ function Layout({ children }: ILayout) {
);
signOut({ callbackUrl: `/login/?status=logout` });
}

const handleRouterStart = (url) => {
if (!url) return;
const segments = parseUrlToSegments(url);
const prevSegemnts = parseUrlToSegments(pathname);
console.log(4, prevSegemnts);
if (segments[0] === "home") setSlideDirection("left");
if (prevSegemnts[0] === "profile") setSlideDirection("left");
console.log(222, pathname, url);
};

const handleRouterCompleted = (url) => {
console.log(111);
if (!url) return;
const segments = parseUrlToSegments(url);
setSlideDirection("right");
};

router.events.on("routeChangeStart", handleRouterStart);
router.events.on("routeChangeComplete", handleRouterCompleted);

return () => {
router.events.off("routeChangeStart", handleRouterStart);
router.events.off("routeChangeComplete", handleRouterCompleted);
};
}, [session, router.events, pathname]);
}, [session]);

return (
<>
Expand All @@ -104,8 +69,9 @@ function Layout({ children }: ILayout) {
{token && (
<>
<div id="root-modal">{children}</div>
{BASE_BOTTOM_NAV_URL.includes(pathname) && <BottomNav />}
{isGuest && BASE_BOTTOM_NAV_URL.includes(pathname) && <GuestBottomNav />}
<PageTracker />
{BASE_BOTTOM_NAV_SEGMENT.includes(currentSegment) && <BottomNav />}
{isGuest && BASE_BOTTOM_NAV_SEGMENT.includes(currentSegment) && <GuestBottomNav />}
<BaseModal isGuest={isGuest} isError={isErrorModal} setIsError={setIsErrorModal} />
</>
)}
Expand All @@ -114,6 +80,4 @@ function Layout({ children }: ILayout) {
);
}

const BASE_BOTTOM_NAV_URL = ["/home", "/statistics", "/gather", "/group"];

export default Layout;
Loading

0 comments on commit 782a951

Please sign in to comment.