"use client"; import { useRef, useState, useEffect } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import Link from "next/link"; import { Bookmark, Check } from "lucide-react"; import { collectionsAPI } from "@/lib/api"; import { useAuthStore } from "@/stores/authStore"; import type { Collection } from "@/lib/types"; interface CollectionPickerProps { billId: string; } export function CollectionPicker({ billId }: CollectionPickerProps) { const token = useAuthStore((s) => s.token); const [open, setOpen] = useState(false); const ref = useRef(null); const qc = useQueryClient(); useEffect(() => { if (!open) return; function onClickOutside(e: MouseEvent) { if (ref.current && !ref.current.contains(e.target as Node)) { setOpen(false); } } document.addEventListener("mousedown", onClickOutside); return () => document.removeEventListener("mousedown", onClickOutside); }, [open]); const { data: collections } = useQuery({ queryKey: ["collections"], queryFn: collectionsAPI.list, enabled: !!token, }); const addMutation = useMutation({ mutationFn: (id: number) => collectionsAPI.addBill(id, billId), onSuccess: (_, id) => { qc.invalidateQueries({ queryKey: ["collections"] }); qc.invalidateQueries({ queryKey: ["collection", id] }); }, }); const removeMutation = useMutation({ mutationFn: (id: number) => collectionsAPI.removeBill(id, billId), onSuccess: (_, id) => { qc.invalidateQueries({ queryKey: ["collections"] }); qc.invalidateQueries({ queryKey: ["collection", id] }); }, }); if (!token) return null; // Determine which collections contain this bill // We check each collection's bill_count proxy by re-fetching detail... but since the list // endpoint doesn't return bill_ids, we use a lightweight approach: track via optimistic state. // The collection detail page has the bill list; for the picker we just check each collection. // To avoid N+1, we'll use a separate query to get the user's collection memberships for this bill. // For simplicity, we use the collections list and compare via a bill-membership query. return (
{open && (
{!collections || collections.length === 0 ? (
No collections yet.
) : (
    {collections.map((c: Collection) => ( addMutation.mutate(c.id)} onRemove={() => removeMutation.mutate(c.id)} /> ))}
)}
setOpen(false)} className="text-xs text-primary hover:underline" > New collection →
)}
); } function CollectionPickerRow({ collection, billId, onAdd, onRemove, }: { collection: Collection; billId: string; onAdd: () => void; onRemove: () => void; }) { // Fetch detail to know if this bill is in the collection const { data: detail } = useQuery({ queryKey: ["collection", collection.id], queryFn: () => collectionsAPI.get(collection.id), }); const inCollection = detail?.bills.some((b) => b.bill_id === billId) ?? false; return (
  • ); }