"use client"; import { useRef, useEffect, useState } from "react"; import { Heart, Shield, Zap, ChevronDown } from "lucide-react"; import { useAddFollow, useIsFollowing, useRemoveFollow, useUpdateFollowMode } from "@/lib/hooks/useFollows"; import { useAuthStore } from "@/stores/authStore"; import { AuthModal } from "./AuthModal"; import { cn } from "@/lib/utils"; const MODES = { neutral: { label: "Following", icon: Heart, color: "bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-400", }, pocket_veto: { label: "Pocket Veto", icon: Shield, color: "bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400", }, pocket_boost: { label: "Pocket Boost", icon: Zap, color: "bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400", }, } as const; type FollowMode = keyof typeof MODES; interface FollowButtonProps { type: "bill" | "member" | "topic"; value: string; label?: string; supportsModes?: boolean; } export function FollowButton({ type, value, label, supportsModes = false }: FollowButtonProps) { const existing = useIsFollowing(type, value); const add = useAddFollow(); const remove = useRemoveFollow(); const updateMode = useUpdateFollowMode(); const token = useAuthStore((s) => s.token); const [open, setOpen] = useState(false); const [showAuthModal, setShowAuthModal] = useState(false); const dropdownRef = useRef(null); function requireAuth(action: () => void) { if (!token) { setShowAuthModal(true); return; } action(); } const isFollowing = !!existing; const currentMode: FollowMode = (existing?.follow_mode as FollowMode) ?? "neutral"; const isPending = add.isPending || remove.isPending || updateMode.isPending; // Close dropdown on outside click useEffect(() => { if (!open) return; const handler = (e: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { setOpen(false); } }; document.addEventListener("mousedown", handler); return () => document.removeEventListener("mousedown", handler); }, [open]); // Simple toggle for non-bill follows if (!supportsModes) { const handleClick = () => { requireAuth(() => { if (isFollowing && existing) { remove.mutate(existing.id); } else { add.mutate({ type, value }); } }); }; return ( <> setShowAuthModal(false)} /> ); } // Mode-aware follow button for bills if (!isFollowing) { return ( <> setShowAuthModal(false)} /> ); } const { label: modeLabel, icon: ModeIcon, color } = MODES[currentMode]; const otherModes = (Object.keys(MODES) as FollowMode[]).filter((m) => m !== currentMode); const switchMode = (mode: FollowMode) => { requireAuth(() => { if (existing) updateMode.mutate({ id: existing.id, mode }); setOpen(false); }); }; const handleUnfollow = () => { requireAuth(() => { if (existing) remove.mutate(existing.id); setOpen(false); }); }; const modeDescriptions: Record = { neutral: "Alert me on all material changes", pocket_veto: "Alert me only if this bill advances toward passage", pocket_boost: "Alert me on all changes + remind me to contact my rep", }; return ( <>
{open && (
{otherModes.map((mode) => { const { label: optLabel, icon: OptIcon } = MODES[mode]; return ( ); })}
)}
setShowAuthModal(false)} /> ); }