From 3a992b9255254ec63c067a9776a052221cf10759 Mon Sep 17 00:00:00 2001 From: Lim Ke En Date: Wed, 7 Aug 2024 23:58:37 +0800 Subject: [PATCH 1/6] infinite scrolling implementation --- .../src/components/common/BackButton.tsx | 8 +- checkers-app/src/components/common/Layout.tsx | 5 +- .../src/components/myvotes/MessageCard.tsx | 6 +- .../components/myvotes/MessagesDisplay.tsx | 82 ++++++++++++------- checkers-app/src/components/myvotes/index.tsx | 2 + .../api/handlers/getCheckerVotes.ts | 1 + 6 files changed, 68 insertions(+), 36 deletions(-) diff --git a/checkers-app/src/components/common/BackButton.tsx b/checkers-app/src/components/common/BackButton.tsx index cac81b07..db8f1095 100644 --- a/checkers-app/src/components/common/BackButton.tsx +++ b/checkers-app/src/components/common/BackButton.tsx @@ -7,7 +7,13 @@ export function BackButton() { const regex = /^\/messages\/[^/]+\/voteRequests\/[^/]+\/?$/; function onClick() { if (regex.test(location.pathname)) { - navigate("/votes"); + const path = location.pathname + console.log(location) + console.log(location.state.status) + const segments = path.split('/'); + const messageId = segments[2]; + console.log(messageId); + navigate("/votes", {state: location.state}); } else { navigate(-1); } diff --git a/checkers-app/src/components/common/Layout.tsx b/checkers-app/src/components/common/Layout.tsx index b272df60..f425d6ff 100644 --- a/checkers-app/src/components/common/Layout.tsx +++ b/checkers-app/src/components/common/Layout.tsx @@ -14,7 +14,7 @@ export default function Layout({ showMenu = false, }: LayoutProps) { return ( -
+
{/*
*/}
+ {/* {pageHeader}
*/} -
{children}
+
{children}
); diff --git a/checkers-app/src/components/myvotes/MessageCard.tsx b/checkers-app/src/components/myvotes/MessageCard.tsx index 67be1bbb..29c988b1 100644 --- a/checkers-app/src/components/myvotes/MessageCard.tsx +++ b/checkers-app/src/components/myvotes/MessageCard.tsx @@ -76,8 +76,8 @@ export default function MessageCard(props: MessageCardProps) { const dateString = dateToDateString(new Date(createdTimestamp)); // If the message is PENDING, clicking the button should go to the voting page - const viewVote = (firestorePath: string) => { - navigate(`/${firestorePath}`); + const viewVote = (firestorePath: string, status: string) => { + navigate(`/${firestorePath}`, {state: {status: status}}); }; const textStyle = "font-normal"; //add bold in future @@ -128,7 +128,7 @@ export default function MessageCard(props: MessageCardProps) { return (
viewVote(firestorePath)} + onClick={() => viewVote(firestorePath, status )} > {/* Coloured dot if needs review*/} diff --git a/checkers-app/src/components/myvotes/MessagesDisplay.tsx b/checkers-app/src/components/myvotes/MessagesDisplay.tsx index 93d28145..29b5ff0a 100644 --- a/checkers-app/src/components/myvotes/MessagesDisplay.tsx +++ b/checkers-app/src/components/myvotes/MessagesDisplay.tsx @@ -16,16 +16,16 @@ Idea: - Have a nested component for each button */ -import { useState, useEffect, FC } from "react"; +import { useState, useEffect, FC, useCallback, useRef } from "react"; import { useUser } from "../../providers/UserContext"; -import Loading from "../common/Loading"; +// import Loading from "../common/Loading"; import MessageCard from "./MessageCard"; import { Typography } from "@material-tailwind/react"; import { getCheckerVotes } from "../../services/api"; import { VoteSummary, VoteSummaryApiResponse } from "../../types"; -import Pagination from "./Pagination"; // Make sure to create this component +//import Pagination from "./Pagination"; // Make sure to create this component -const MessagesDisplay: FC = () => { +const MessagesDisplayTest: FC = () => { const { checkerDetails } = useUser(); const [isLoading, setIsLoading] = useState(false); const [votes, setVotes] = useState([]); @@ -34,42 +34,60 @@ const MessagesDisplay: FC = () => { const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [error, setError] = useState(""); + const [page, setPage] = useState(1); - useEffect(() => { - const fetchMessages = async () => { - setIsLoading(true); - try { + const fetchMessages = async () => { + setIsLoading(true); + try { if (!checkerDetails.checkerId) { - throw new Error("Checker Id missing."); + throw new Error("Checker Id missing."); } const response: VoteSummaryApiResponse = await getCheckerVotes( - checkerDetails.checkerId, - activeTab.toLowerCase(), - 5, - lastPath + checkerDetails.checkerId, + activeTab.toLowerCase(), + 5, + lastPath ); - // Assuming your API correctly maps to the ApiResponse interface if (response.votes) { - setVotes(response.votes); + setVotes((prevVotes) => [...prevVotes, ...response.votes]) } setTotalPages(response.totalPages); setLastPath(response.lastPath); setIsLoading(false); - } catch (err) { + } catch(err) { setError("Failed to fetch messages"); setIsLoading(false); - } - }; + } + } + + useEffect(() => { if (checkerDetails.checkerId) { fetchMessages(); } - }, [checkerDetails.checkerId, activeTab, currentPage]); + }, [checkerDetails.checkerId, activeTab, currentPage, page]); + const handleTabChange = (tab: "pending" | "voted") => { + setVotes([]); setActiveTab(tab); + setPage(1); handlePageChange(1); // Reset to the first page whenever the tab changes }; + const observer = useRef(null); + // Function to use the Intersection Observer API + const lastMessageElementRef = useCallback((node: any) => { + if (isLoading) return; + if (observer.current) observer.current.disconnect(); + + observer.current = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting && page !== totalPages) { + setPage((prevPage) => prevPage + 1); + } + }); + if (node) observer.current.observe(node); + }, [isLoading]) + // Function to handle page change from the Pagination component const handlePageChange = (page: number) => { setCurrentPage(page); @@ -78,13 +96,15 @@ const MessagesDisplay: FC = () => { } }; - if (isLoading) { - return ; - } + + // if (isLoading) { + // return ; + // } return (
-
+
+
+
{error &&
{error}
} {!error && votes.length === 0 && ( @@ -118,20 +138,22 @@ const MessagesDisplay: FC = () => { )} {!error && votes.map((voteSummary, index) => ( -
- +
+
))}
- {!error && votes.length > 0 && ( + {/* {!error && votes.length > 0 && ( - )} + )} */}
); }; -export default MessagesDisplay; +export default MessagesDisplayTest; diff --git a/checkers-app/src/components/myvotes/index.tsx b/checkers-app/src/components/myvotes/index.tsx index 1f11e0a0..0bde4bc0 100644 --- a/checkers-app/src/components/myvotes/index.tsx +++ b/checkers-app/src/components/myvotes/index.tsx @@ -1,10 +1,12 @@ import MessagesDisplay from "./MessagesDisplay"; +// import MessagesDisplayTest from "./MessagesDisplayTest"; export default function MyVotes() { return (
+ {/* */}
); diff --git a/functions/src/definitions/api/handlers/getCheckerVotes.ts b/functions/src/definitions/api/handlers/getCheckerVotes.ts index 29eb1ab3..055f04d6 100644 --- a/functions/src/definitions/api/handlers/getCheckerVotes.ts +++ b/functions/src/definitions/api/handlers/getCheckerVotes.ts @@ -151,6 +151,7 @@ const getCheckerVotesHandler = async (req: Request, res: Response) => { lastPath: lastVotePath, totalPages, } + return res.status(200).send(response) } catch (error) { logger.error("Error fetching documents: ", error) From 9a3990ff877e5484a7efe91d98c05b606425ac8a Mon Sep 17 00:00:00 2001 From: Lim Ke En Date: Fri, 9 Aug 2024 00:29:11 +0800 Subject: [PATCH 2/6] back button feature --- .../src/components/myvotes/MessageCard.tsx | 8 +++-- .../components/myvotes/MessagesDisplay.tsx | 33 ++++++++++++++++--- checkers-app/src/components/myvotes/index.tsx | 17 +++++++++- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/checkers-app/src/components/myvotes/MessageCard.tsx b/checkers-app/src/components/myvotes/MessageCard.tsx index 29c988b1..f706e5d9 100644 --- a/checkers-app/src/components/myvotes/MessageCard.tsx +++ b/checkers-app/src/components/myvotes/MessageCard.tsx @@ -6,6 +6,7 @@ import "./MessageCard.css"; interface MessageCardProps { voteSummary: VoteSummary; status: string; + scrollPosition: number; } type ColourMap = { @@ -71,13 +72,14 @@ export default function MessageCard(props: MessageCardProps) { firestorePath, } = props.voteSummary; const status = props.status; + const scrollPosition = props.scrollPosition; // const colour: string = colours[category]; const navigate = useNavigate(); const dateString = dateToDateString(new Date(createdTimestamp)); // If the message is PENDING, clicking the button should go to the voting page - const viewVote = (firestorePath: string, status: string) => { - navigate(`/${firestorePath}`, {state: {status: status}}); + const viewVote = (firestorePath: string, status: string, scrollPosition: number) => { + navigate(`/${firestorePath}`, {state: {status: status, scrollPosition: scrollPosition}}); }; const textStyle = "font-normal"; //add bold in future @@ -128,7 +130,7 @@ export default function MessageCard(props: MessageCardProps) { return (
viewVote(firestorePath, status )} + onClick={() => viewVote(firestorePath, status, scrollPosition)} > {/* Coloured dot if needs review*/} diff --git a/checkers-app/src/components/myvotes/MessagesDisplay.tsx b/checkers-app/src/components/myvotes/MessagesDisplay.tsx index 29b5ff0a..cf82ca53 100644 --- a/checkers-app/src/components/myvotes/MessagesDisplay.tsx +++ b/checkers-app/src/components/myvotes/MessagesDisplay.tsx @@ -16,6 +16,11 @@ Idea: - Have a nested component for each button */ +interface MessagesDisplayTestProps { + status: "pending" | "voted", + scrollPosition: number +} + import { useState, useEffect, FC, useCallback, useRef } from "react"; import { useUser } from "../../providers/UserContext"; // import Loading from "../common/Loading"; @@ -25,16 +30,36 @@ import { getCheckerVotes } from "../../services/api"; import { VoteSummary, VoteSummaryApiResponse } from "../../types"; //import Pagination from "./Pagination"; // Make sure to create this component -const MessagesDisplayTest: FC = () => { +const MessagesDisplayTest: FC = ({status, scrollPosition}) => { const { checkerDetails } = useUser(); const [isLoading, setIsLoading] = useState(false); const [votes, setVotes] = useState([]); const [lastPath, setLastPath] = useState(null); - const [activeTab, setActiveTab] = useState<"pending" | "voted">("pending"); + const [activeTab, setActiveTab] = useState<"pending" | "voted">(status); const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [error, setError] = useState(""); const [page, setPage] = useState(1); + const [scrollY, setScrollY] = useState(0); + + // Scroll Functions + const scrollRef = useRef(null); + const handleScroll = () => { + const scrollY = window.scrollY; + console.log(scrollY) + setScrollY(scrollY); + } + + useEffect(() => { + setTimeout(() => { + window.scrollTo(0, scrollPosition); + }, 200) + + window.addEventListener('scroll', handleScroll); + return () => { + window.removeEventListener('scroll', handleScroll); + } + }, []); const fetchMessages = async () => { setIsLoading(true); @@ -66,7 +91,6 @@ const MessagesDisplayTest: FC = () => { } }, [checkerDetails.checkerId, activeTab, currentPage, page]); - const handleTabChange = (tab: "pending" | "voted") => { setVotes([]); setActiveTab(tab); @@ -129,6 +153,7 @@ const MessagesDisplayTest: FC = () => {
{error &&
{error}
} {!error && votes.length === 0 && ( @@ -141,7 +166,7 @@ const MessagesDisplayTest: FC = () => {
- +
))}
diff --git a/checkers-app/src/components/myvotes/index.tsx b/checkers-app/src/components/myvotes/index.tsx index 0bde4bc0..dc06ceba 100644 --- a/checkers-app/src/components/myvotes/index.tsx +++ b/checkers-app/src/components/myvotes/index.tsx @@ -1,11 +1,26 @@ import MessagesDisplay from "./MessagesDisplay"; // import MessagesDisplayTest from "./MessagesDisplayTest"; +import { useState, useEffect } from "react"; +import { useLocation } from "react-router-dom"; export default function MyVotes() { + const [activeTab, setActiveTab] = useState<"pending" | "voted">("pending"); + const location = useLocation(); + + useEffect(() => { + console.log(location) + if (location.state) { + if (location.state.status) { + setActiveTab(location.state.status) + console.log(location.state.scrollPosition) + } + } + }, [location, activeTab]) + return (
- + {/* */}
From 0c61ef40ee8b197233f894a6bf64c4454fd46f6b Mon Sep 17 00:00:00 2001 From: Lim Ke En Date: Mon, 12 Aug 2024 22:01:25 +0800 Subject: [PATCH 3/6] Restore scrolling position --- .../components/myvotes/MessagesDisplay.tsx | 29 ++++++++++++++----- checkers-app/src/components/myvotes/index.tsx | 3 +- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/checkers-app/src/components/myvotes/MessagesDisplay.tsx b/checkers-app/src/components/myvotes/MessagesDisplay.tsx index cf82ca53..aa037a01 100644 --- a/checkers-app/src/components/myvotes/MessagesDisplay.tsx +++ b/checkers-app/src/components/myvotes/MessagesDisplay.tsx @@ -18,7 +18,7 @@ Idea: interface MessagesDisplayTestProps { status: "pending" | "voted", - scrollPosition: number + scrollPosition: number, } import { useState, useEffect, FC, useCallback, useRef } from "react"; @@ -42,25 +42,38 @@ const MessagesDisplayTest: FC = ({status, scrollPositi const [page, setPage] = useState(1); const [scrollY, setScrollY] = useState(0); - // Scroll Functions const scrollRef = useRef(null); + + // Scroll Functions const handleScroll = () => { const scrollY = window.scrollY; - console.log(scrollY) - setScrollY(scrollY); + console.log('Scroll Y: ',scrollY) + setScrollY(scrollY) } useEffect(() => { - setTimeout(() => { - window.scrollTo(0, scrollPosition); - }, 200) - window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); } }, []); + useEffect(() => { + if (scrollY >= scrollPosition) { + return; + } + else if (scrollPosition !== 0) { + console.log("Changing scroll"); + setTimeout(() => { + window.scrollTo({ + top: scrollPosition, + behavior: 'smooth' + }) + }, 200); + + } + },[votes]) + const fetchMessages = async () => { setIsLoading(true); try { diff --git a/checkers-app/src/components/myvotes/index.tsx b/checkers-app/src/components/myvotes/index.tsx index dc06ceba..f8ea06b0 100644 --- a/checkers-app/src/components/myvotes/index.tsx +++ b/checkers-app/src/components/myvotes/index.tsx @@ -12,7 +12,6 @@ export default function MyVotes() { if (location.state) { if (location.state.status) { setActiveTab(location.state.status) - console.log(location.state.scrollPosition) } } }, [location, activeTab]) @@ -20,7 +19,7 @@ export default function MyVotes() { return (
- + {/* */}
From 854ab296c68bca75c436da1ff3ef922f6bfca7ac Mon Sep 17 00:00:00 2001 From: Bing Wen Tan Date: Sat, 17 Aug 2024 09:34:41 +0800 Subject: [PATCH 4/6] changed to 10 per page, removed unnecessary vars --- .../components/myvotes/MessagesDisplay.tsx | 172 +++++++++--------- 1 file changed, 81 insertions(+), 91 deletions(-) diff --git a/checkers-app/src/components/myvotes/MessagesDisplay.tsx b/checkers-app/src/components/myvotes/MessagesDisplay.tsx index aa037a01..f3e62f69 100644 --- a/checkers-app/src/components/myvotes/MessagesDisplay.tsx +++ b/checkers-app/src/components/myvotes/MessagesDisplay.tsx @@ -16,9 +16,9 @@ Idea: - Have a nested component for each button */ -interface MessagesDisplayTestProps { - status: "pending" | "voted", - scrollPosition: number, +interface MessagesDisplayProps { + status: "pending" | "voted"; + scrollPosition: number; } import { useState, useEffect, FC, useCallback, useRef } from "react"; @@ -30,13 +30,15 @@ import { getCheckerVotes } from "../../services/api"; import { VoteSummary, VoteSummaryApiResponse } from "../../types"; //import Pagination from "./Pagination"; // Make sure to create this component -const MessagesDisplayTest: FC = ({status, scrollPosition}) => { +const MessagesDisplay: FC = ({ + status, + scrollPosition, +}) => { const { checkerDetails } = useUser(); const [isLoading, setIsLoading] = useState(false); const [votes, setVotes] = useState([]); const [lastPath, setLastPath] = useState(null); const [activeTab, setActiveTab] = useState<"pending" | "voted">(status); - const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [error, setError] = useState(""); const [page, setPage] = useState(1); @@ -47,127 +49,117 @@ const MessagesDisplayTest: FC = ({status, scrollPositi // Scroll Functions const handleScroll = () => { const scrollY = window.scrollY; - console.log('Scroll Y: ',scrollY) - setScrollY(scrollY) - } + setScrollY(scrollY); + }; useEffect(() => { - window.addEventListener('scroll', handleScroll); + window.addEventListener("scroll", handleScroll); return () => { - window.removeEventListener('scroll', handleScroll); - } + window.removeEventListener("scroll", handleScroll); + }; }, []); useEffect(() => { if (scrollY >= scrollPosition) { return; - } - else if (scrollPosition !== 0) { - console.log("Changing scroll"); + } else if (scrollPosition !== 0) { setTimeout(() => { window.scrollTo({ top: scrollPosition, - behavior: 'smooth' - }) + behavior: "smooth", + }); }, 200); - } - },[votes]) + }, [votes]); const fetchMessages = async () => { setIsLoading(true); try { - if (!checkerDetails.checkerId) { - throw new Error("Checker Id missing."); - } - const response: VoteSummaryApiResponse = await getCheckerVotes( - checkerDetails.checkerId, - activeTab.toLowerCase(), - 5, - lastPath - ); - if (response.votes) { - setVotes((prevVotes) => [...prevVotes, ...response.votes]) - } - setTotalPages(response.totalPages); - setLastPath(response.lastPath); - setIsLoading(false); - } catch(err) { - setError("Failed to fetch messages"); - setIsLoading(false); + if (!checkerDetails.checkerId) { + throw new Error("Checker Id missing."); + } + const response: VoteSummaryApiResponse = await getCheckerVotes( + checkerDetails.checkerId, + activeTab.toLowerCase(), + 10, + lastPath + ); + if (response.votes) { + setVotes((prevVotes) => [...prevVotes, ...response.votes]); + } + setTotalPages(response.totalPages); + setLastPath(response.lastPath); + setIsLoading(false); + } catch (err) { + setError("Failed to fetch messages"); + setIsLoading(false); } - } + }; useEffect(() => { if (checkerDetails.checkerId) { fetchMessages(); } - }, [checkerDetails.checkerId, activeTab, currentPage, page]); + }, [checkerDetails.checkerId, activeTab, page]); const handleTabChange = (tab: "pending" | "voted") => { setVotes([]); setActiveTab(tab); - setPage(1); handlePageChange(1); // Reset to the first page whenever the tab changes }; const observer = useRef(null); // Function to use the Intersection Observer API - const lastMessageElementRef = useCallback((node: any) => { - if (isLoading) return; - if (observer.current) observer.current.disconnect(); + const lastMessageElementRef = useCallback( + (node: any) => { + if (isLoading) return; + if (observer.current) observer.current.disconnect(); - observer.current = new IntersectionObserver((entries) => { + observer.current = new IntersectionObserver((entries) => { if (entries[0].isIntersecting && page !== totalPages) { - setPage((prevPage) => prevPage + 1); + setPage((prevPage) => prevPage + 1); } - }); - if (node) observer.current.observe(node); - }, [isLoading]) + }); + if (node) observer.current.observe(node); + }, + [isLoading] + ); // Function to handle page change from the Pagination component const handlePageChange = (page: number) => { - setCurrentPage(page); + setPage(page); if (page === 1) { setLastPath(null); } }; - - // if (isLoading) { - // return ; - // } - return (
-
-
- - -
+
+
+ + +
-
+
{error &&
{error}
} {!error && votes.length === 0 && (
@@ -176,22 +168,20 @@ const MessagesDisplayTest: FC = ({status, scrollPositi )} {!error && votes.map((voteSummary, index) => ( -
- +
))}
- {/* {!error && votes.length > 0 && ( - - )} */}
); }; -export default MessagesDisplayTest; +export default MessagesDisplay; From 6e8b286bddce52c2b1a60b2204b35a766718cc1f Mon Sep 17 00:00:00 2001 From: Bing Wen Tan Date: Sat, 17 Aug 2024 09:36:40 +0800 Subject: [PATCH 5/6] removed pagination --- .../components/myvotes/MessagesDisplay.tsx | 2 - .../src/components/myvotes/Pagination.tsx | 73 ------------------- 2 files changed, 75 deletions(-) delete mode 100644 checkers-app/src/components/myvotes/Pagination.tsx diff --git a/checkers-app/src/components/myvotes/MessagesDisplay.tsx b/checkers-app/src/components/myvotes/MessagesDisplay.tsx index f3e62f69..1be8f91d 100644 --- a/checkers-app/src/components/myvotes/MessagesDisplay.tsx +++ b/checkers-app/src/components/myvotes/MessagesDisplay.tsx @@ -23,12 +23,10 @@ interface MessagesDisplayProps { import { useState, useEffect, FC, useCallback, useRef } from "react"; import { useUser } from "../../providers/UserContext"; -// import Loading from "../common/Loading"; import MessageCard from "./MessageCard"; import { Typography } from "@material-tailwind/react"; import { getCheckerVotes } from "../../services/api"; import { VoteSummary, VoteSummaryApiResponse } from "../../types"; -//import Pagination from "./Pagination"; // Make sure to create this component const MessagesDisplay: FC = ({ status, diff --git a/checkers-app/src/components/myvotes/Pagination.tsx b/checkers-app/src/components/myvotes/Pagination.tsx deleted file mode 100644 index 0a128be0..00000000 --- a/checkers-app/src/components/myvotes/Pagination.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { FC } from "react"; - -interface PaginationProps { - currentPage: number; - totalPages: number; - onPageChange: (page: number) => void; -} - -const Pagination: FC = ({ - currentPage, - totalPages, - onPageChange, -}) => { - const pageNumbers: number[] = []; - - // Determine page numbers to display - for (let i = 1; i <= totalPages; i++) { - pageNumbers.push(i); - } - - // Handle page change - const handlePageChange = (pageNumber: number) => { - onPageChange(pageNumber); - }; - - if (totalPages <= 1) return null; // Don't display pagination for single page - - return ( -
- - {/* - {pageNumbers.map((number) => ( - - ))} */} - - {/* */} -
- ); -}; - -export default Pagination; From bf3b830b316671b8a94904e64ac14a4eeb578d55 Mon Sep 17 00:00:00 2001 From: Bing Wen Tan Date: Sat, 17 Aug 2024 09:40:52 +0800 Subject: [PATCH 6/6] removed some redundant code --- checkers-app/src/components/common/BackButton.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/checkers-app/src/components/common/BackButton.tsx b/checkers-app/src/components/common/BackButton.tsx index db8f1095..faea16f5 100644 --- a/checkers-app/src/components/common/BackButton.tsx +++ b/checkers-app/src/components/common/BackButton.tsx @@ -7,13 +7,7 @@ export function BackButton() { const regex = /^\/messages\/[^/]+\/voteRequests\/[^/]+\/?$/; function onClick() { if (regex.test(location.pathname)) { - const path = location.pathname - console.log(location) - console.log(location.state.status) - const segments = path.split('/'); - const messageId = segments[2]; - console.log(messageId); - navigate("/votes", {state: location.state}); + navigate("/votes", { state: location.state }); //for resumption of old position } else { navigate(-1); }