'use client'; import { useRouter, useSearchParams } from 'next/navigation'; import { Settings, MessageSquare, Tag, User, Palette, UsersRound, } from 'lucide-react'; import { Tabs, TabsList, TabsTrigger, TabsContent } from '@/components/ui/tabs'; import { WhatsAppConfig } from '@/components/settings/whatsapp-config'; import { TemplateManager } from '@/components/settings/template-manager'; import { TagManager } from '@/components/settings/tag-manager'; import { ProfileForm } from '@/components/settings/profile-form'; import { PasswordForm } from '@/components/settings/password-form'; import { SessionsCard } from '@/components/settings/sessions-card'; import { AppearancePanel } from '@/components/settings/appearance-panel'; import { MembersTab } from '@/components/settings/members-tab'; import { useAuth } from '@/hooks/use-auth'; const BASE_TAB_VALUES = [ 'profile', 'whatsapp', 'templates', 'tags', 'appearance', ] as const; const FLAGGED_TAB_VALUES = ['members'] as const; const TAB_VALUES = [...BASE_TAB_VALUES, ...FLAGGED_TAB_VALUES] as const; type TabValue = (typeof TAB_VALUES)[number]; function isTabValue(v: string | null): v is TabValue { return !!v && (TAB_VALUES as readonly string[]).includes(v); } // Flag key matches what migration 011 introduced. The Members tab // stays hidden until the user's profile.beta_features array contains // this string; flip it via Supabase Studio: // UPDATE profiles SET beta_features = beta_features || ARRAY['account_sharing'] // WHERE user_id = ''; const ACCOUNT_SHARING_FLAG = 'account_sharing'; export default function SettingsPage() { const router = useRouter(); const searchParams = useSearchParams(); const { profile, profileLoading } = useAuth(); const accountSharingEnabled = !profileLoading && !!profile?.beta_features?.includes(ACCOUNT_SHARING_FLAG); // The URL is the single source of truth for the active tab — no // local state, no sync effect. A previous revision duplicated this // into `useState` + a sync effect, which tripped React 19's // set-state-in-effect rule and was also redundant. const queryTab = searchParams.get('tab'); const requestedTab: TabValue = isTabValue(queryTab) ? queryTab : 'profile'; // If a user lands on /settings?tab=members but the flag is off // (e.g. their profile was reset, or they followed a stale link), // fall back to the profile tab silently rather than rendering an // empty TabsContent. const tab: TabValue = requestedTab === 'members' && !accountSharingEnabled ? 'profile' : requestedTab; const onChange = (next: TabValue) => { const params = new URLSearchParams(searchParams.toString()); params.set('tab', next); router.replace(`/settings?${params.toString()}`, { scroll: false }); }; return (

Settings

Manage your profile, WhatsApp® integration, message templates, and tags.

onChange(v as TabValue)}> Profile WhatsApp Config Templates Tags Appearance {/* Members tab is feature-flagged. We render the trigger only when the flag is enabled, so users without the flag see the original 5-tab layout. */} {accountSharingEnabled && ( Members )} {accountSharingEnabled && ( )}
); }