import React, { useEffect, useMemo } from "react"; import { motion } from "framer-motion"; import { checkIsMobile } from "../../utils/checkIsMobile"; import { useTabStore } from "../../context/zustand-store/appStore"; type Tab = { label: string; visible?: boolean; disabled?: boolean; path?: string; }; type TabsProps = { tabs: Tab[]; onChange: (index: number) => void; size?: "small" | "medium" | "large"; tabKey?: string; }; const Tabs: React.FC = ({ tabs, onChange, size = "medium", tabKey = "default", }) => { const isMobile = checkIsMobile(); const { tabState, setActiveTab } = useTabStore(); const isTabVisible = (tab: Tab): boolean => { if (tab.visible === false) return false; return tab.visible === undefined || tab.visible === true; }; const visibleTabs = useMemo(() => tabs.filter(isTabVisible), [tabs]); const hasSingleVisibleTab = visibleTabs.length === 1; const getFirstVisibleTabIndex = () => { return tabs.findIndex(isTabVisible); }; const isValidTabIndex = (index: number) => { return index >= 0 && index < tabs.length && isTabVisible(tabs[index]); }; const storedTab = tabState.activeTabs?.[tabKey]; const storedIndex = storedTab?.index ?? 0; const firstVisibleIndex = getFirstVisibleTabIndex(); const selectedIndex = isValidTabIndex(storedIndex) ? storedIndex : firstVisibleIndex !== -1 ? firstVisibleIndex : 0; useEffect(() => { if (hasSingleVisibleTab) { const singleTabIndex = tabs.findIndex(isTabVisible); if (singleTabIndex !== -1 && singleTabIndex !== selectedIndex) { setActiveTab({ index: singleTabIndex, path: tabs[singleTabIndex]?.path || window.location.pathname, label: tabs[singleTabIndex].label, tabKey, }); onChange(singleTabIndex); } } }, [hasSingleVisibleTab, tabs, tabKey]); useEffect(() => { if (!isValidTabIndex(selectedIndex)) { const firstVisible = getFirstVisibleTabIndex(); if (firstVisible !== -1) { setActiveTab({ index: firstVisible, path: tabs[firstVisible]?.path || window.location.pathname, label: tabs[firstVisible].label, tabKey, }); onChange(firstVisible); } } else { onChange(selectedIndex); } }, [tabs, selectedIndex, tabKey]); useEffect(() => { if (typeof window === "undefined") return; const currentPath = window.location.pathname; if (storedTab) { const storedTabStillExists = tabs.some( (tab) => tab.label === storedTab.label && (tab.path === storedTab.path || !tab.path) && isTabVisible(tab) ); if (storedTabStillExists) { const storedIndex = tabs.findIndex( (tab) => tab.label === storedTab.label && (tab.path === storedTab.path || !tab.path) && isTabVisible(tab) ); if (storedIndex !== -1 && storedIndex !== selectedIndex) { setActiveTab({ index: storedIndex, path: tabs[storedIndex]?.path || currentPath, label: tabs[storedIndex].label, tabKey, }); onChange(storedIndex); } return; } } const pathMatchIndex = tabs.findIndex( (tab) => tab.path === currentPath && isTabVisible(tab) ); if (pathMatchIndex !== -1) { setActiveTab({ index: pathMatchIndex, path: currentPath, label: tabs[pathMatchIndex].label, tabKey, }); onChange(pathMatchIndex); return; } if (!isValidTabIndex(selectedIndex)) { const firstVisible = getFirstVisibleTabIndex(); if (firstVisible !== -1) { setActiveTab({ index: firstVisible, path: tabs[firstVisible]?.path || currentPath, label: tabs[firstVisible].label, tabKey, }); onChange(firstVisible); } } }, [tabs, tabKey, storedTab, selectedIndex]); const handleTabClick = (index: number) => { if (!tabs[index].disabled) { setActiveTab({ index, path: tabs[index]?.path || window.location.pathname, label: tabs[index].label, tabKey, }); onChange(index); } }; const sizeClasses: Record, string> = { small: "text-xs py-1 px-2", medium: "text-sm py-1.5 px-3", large: "text-base py-2 px-4", }; if (hasSingleVisibleTab) { return null; } if (isMobile) { return (
{tabs.map((tab, index) => !isTabVisible(tab) ? null : ( ) )}
); } return (
{tabs.map((tab, index) => !isTabVisible(tab) ? null : ( ) )}
); }; export default Tabs;