From 03e2c03460855b29cfcc44a7cae493aaecd7a6ab Mon Sep 17 00:00:00 2001 From: Kalidou Diagne Date: Wed, 28 Feb 2024 09:54:02 -0700 Subject: [PATCH 1/4] keep track of opened tab --- global.d.ts | 1 + src/components/AppFooter.tsx | 13 ++++++++++++- src/components/Tabs.tsx | 19 +++++++++++++++---- src/pages/_app.tsx | 2 ++ src/pages/index.tsx | 22 +++++++++++++++++++++- 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/global.d.ts b/global.d.ts index ce8b9bd1..22af8652 100644 --- a/global.d.ts +++ b/global.d.ts @@ -13,5 +13,6 @@ declare module "little-state-machine" { register: RegisterType; profile: ProfileType; profileView: ProfileDisplayState; + profileActiveTab: string; } } diff --git a/src/components/AppFooter.tsx b/src/components/AppFooter.tsx index 8e7dcce7..d029e270 100644 --- a/src/components/AppFooter.tsx +++ b/src/components/AppFooter.tsx @@ -3,6 +3,8 @@ import Link from "next/link"; import { Icons } from "./Icons"; import { cn } from "@/lib/client/utils"; import { usePathname } from "next/navigation"; +import { useStateMachine } from "little-state-machine"; +import updateStateFromAction from "@/lib/shared/updateAction"; interface RouterItem { label: string; @@ -13,12 +15,21 @@ interface RouterItem { } const TabItem = ({ label, href, icon, isActive, iconSize }: RouterItem) => { + const { actions, getState } = useStateMachine({ updateStateFromAction }); const Icon: any = icon; const textColor = isActive ? "text-white" : "text-gray-10"; return ( - + { + actions.updateStateFromAction({ + ...getState(), + profileActiveTab: "activity-feed", + }); + }} + >
void; items: TabProps[]; + defaultTab?: string; } const TabButton = classed.div("pb-4", { @@ -27,16 +31,23 @@ const TabBadge = classed.div( "absolute -top-0.5 -right-2 bg-[#D40018] rounded-full text-white w-[6px] h-[6px] text-[8px]" ); -const Tabs = ({ items }: TabsProps) => { +const Tabs = ({ items, defaultTab, onChange }: TabsProps) => { + const defaultTabIndex = items.findIndex((item) => item.id === defaultTab); + return ( - + - {items.map(({ label, badge }, index) => { + {items.map(({ label, badge, id }, index) => { return ( {({ selected }) => (
- + { + onChange?.(id); + }} + > {label} {badge && } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 599b4737..7e98afac 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -12,6 +12,7 @@ import { } from "@tanstack/react-query"; import { StateMachineProvider } from "little-state-machine"; import type { AppProps } from "next/app"; +import { useRouter } from "next/router"; import { useEffect, useState } from "react"; import { toast, Toaster } from "sonner"; @@ -23,6 +24,7 @@ const queryClient = new QueryClient({ export default function App({ Component, pageProps }: AppProps) { const { isIncognito } = useSettings(); + const router = useRouter(); const [isMenuOpen, setIsMenuOpen] = useState(false); const [pageHeight, setPageHeight] = useState(0); const showFooter = pageProps?.showFooter ?? true; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 37f66803..dcfc742a 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -25,6 +25,8 @@ import { formatDate } from "@/lib/shared/utils"; import { loadMessages } from "@/lib/client/jubSignalClient"; import { Spinner } from "@/components/Spinner"; import { CircleCard } from "@/components/cards/CircleCard"; +import { useStateMachine } from "little-state-machine"; +import updateStateFromAction from "@/lib/shared/updateAction"; interface ContactCardProps { name: string; @@ -179,6 +181,8 @@ export default function Social() { const [tabsItems, setTabsItems] = useState(); const [isLoading, setLoading] = useState(false); + const { actions, getState } = useStateMachine({ updateStateFromAction }); + // Helper function to compute data needed to populate tabs const computeTabsItems = ( profileData: Profile, @@ -244,6 +248,7 @@ export default function Social() { return [ { + id: "activity-feed", label: "Activity Feed", children: (
@@ -277,6 +282,7 @@ export default function Social() { ), }, { + id: "contacts", label: "Contacts", children: (
@@ -315,6 +321,7 @@ export default function Social() { ), }, { + id: "pending", label: "Pending", badge: sortedPendingUserList.length > 0, children: ( @@ -409,6 +416,9 @@ export default function Social() { } if (!profile || !tabsItems) return null; + + const currentActiveTab = getState().profileActiveTab ?? tabsItems[0].id; + return ( <>
- + { + actions.updateStateFromAction({ + ...getState(), + // keep track of the active tab + profileActiveTab: activeTabId, + }); + }} + /> ); } From 8464c1081eaad22ec18c9b6cf2737ae169dd96a8 Mon Sep 17 00:00:00 2001 From: Kalidou Diagne Date: Wed, 28 Feb 2024 09:54:59 -0700 Subject: [PATCH 2/4] add comment --- src/components/AppFooter.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/AppFooter.tsx b/src/components/AppFooter.tsx index d029e270..1d15674e 100644 --- a/src/components/AppFooter.tsx +++ b/src/components/AppFooter.tsx @@ -26,6 +26,7 @@ const TabItem = ({ label, href, icon, isActive, iconSize }: RouterItem) => { onClick={() => { actions.updateStateFromAction({ ...getState(), + // on navigation, reset the active tab to the default profileActiveTab: "activity-feed", }); }} From 832a35ac7c29447bd5d3c3f239f4bb3daec71add Mon Sep 17 00:00:00 2001 From: Kalidou Diagne Date: Wed, 28 Feb 2024 10:09:37 -0700 Subject: [PATCH 3/4] fixed header for activity feed page --- src/components/AppHeader.tsx | 10 ++++++++-- src/lib/shared/utils.ts | 6 ++++++ src/pages/_app.tsx | 11 ++++++++--- src/pages/index.tsx | 4 ++++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/components/AppHeader.tsx b/src/components/AppHeader.tsx index c2302f4b..664214d0 100644 --- a/src/components/AppHeader.tsx +++ b/src/components/AppHeader.tsx @@ -8,6 +8,7 @@ import Profile from "./Profile"; import { useStateMachine } from "little-state-machine"; import updateStateFromAction from "@/lib/shared/updateAction"; import { ProfileDisplayState } from "@/types"; +import { cn } from "@/lib/client/utils"; const Title = classed.h3("block text-base text-gray-12 font-light leading-5"); const Subtitle = classed.h4("text-sm text-gray-12 leading-5"); @@ -213,15 +214,20 @@ const AppHeaderContent = ({ interface AppHeaderProps { isMenuOpen: boolean; setIsMenuOpen: (value: boolean) => void; + fixed?: boolean; // if true, the header will be fixed } -const AppHeader = ({ isMenuOpen, setIsMenuOpen }: AppHeaderProps) => { +const AppHeader = ({ isMenuOpen, setIsMenuOpen, fixed }: AppHeaderProps) => { const handleSignout = () => { deleteAccountFromLocalStorage(); window.location.href = "/"; }; return ( -
+
{!isMenuOpen && (