'use client';
import { useState, useEffect, useRef, useCallback } from 'react';
import { toast } from 'sonner';
import {
AlertTriangle, Building2, CheckCircle2, Loader2, Plus, Tag, Trash2, X,
} from 'lucide-react';
import { api } from '@/api';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import * as Portal from '@radix-ui/react-portal';
import { Input } from '@/components/ui/input';
// Debounce helper
function useDebounce(value, delay) {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const t = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(t);
}, [value, delay]);
return debounced;
}
function RuleChip({ rule, onDelete, deleting }) {
return (
{rule.merchant}
);
}
function ConflictWarning({ conflicts }) {
if (!conflicts?.length) return null;
return (
This pattern is already used by{' '}
{conflicts.map((c, i) => (
{i > 0 && ', '}
{c.name}
))}.
Transactions could match both bills — consider making your pattern more specific.
{retroFeedback} existing payment{retroFeedback === 1 ? '' : 's'} imported from your transaction history.
)}
{/* Add rule input */}
{ setInput(e.target.value); setShowSuggestions(true); setRetroFeedback(null); setPreviewError(false); }}
onFocus={() => setShowSuggestions(true)}
onKeyDown={e => {
if (e.key === 'Enter') { e.preventDefault(); handleAdd(); }
if (e.key === 'Escape') setShowSuggestions(false);
}}
placeholder="Type merchant name or pick from recent transactions…"
className="h-8 pr-20 text-xs"
disabled={adding}
/>
{/* Suggestions — rendered in a Portal so the list escapes the BillModal's
overflow-y-auto container and is fully clickable regardless of scroll */}
{showSuggestions && filteredSuggestions.length > 0 && inputRef.current && (