import React, { useMemo } from 'react'; import { ArrowDown, ArrowUp, Copy, GripVertical, History } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { scheduleLabel } from '@/lib/billingSchedule'; import type { Bill } from '@/types'; import type { DragProps, MoveControls } from '@/components/tracker/MobileTrackerRow'; function hasHistoricalVisibility(bill: Bill): boolean { const visibility = bill.history_visibility; return !!bill.has_history_ranges || (!!visibility && visibility !== 'default'); } interface MobileBillRowProps { bill: Bill; onEdit?: (id: number) => void; onToggle?: (bill: Bill) => void; onDelete?: (bill: Bill) => void; onHistory?: (bill: Bill) => void; onDuplicate?: (bill: Bill) => void; moveControls?: MoveControls; dragProps?: DragProps; } export const MobileBillRow = React.memo(function MobileBillRow({ bill, onEdit, onToggle, onDelete, onHistory, onDuplicate, moveControls, dragProps }: MobileBillRowProps) { const hasHistory = useMemo(() => hasHistoricalVisibility(bill), [bill]); const statusClass = useMemo(() => { return cn( 'rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide', bill.active ? 'bg-emerald-500/20 text-emerald-300' : 'bg-muted text-muted-foreground', ); }, [bill.active]); const toggleBtnClass = useMemo(() => { return cn( 'h-8 px-2.5 text-xs', bill.active ? 'text-muted-foreground hover:text-destructive' : 'text-emerald-500 hover:text-emerald-400', ); }, [bill.active]); return (
['onDragStart']} onDragEnter={dragProps?.onDragEnter as React.ComponentProps<'div'>['onDragEnter']} onDragOver={dragProps?.onDragOver as React.ComponentProps<'div'>['onDragOver']} onDragEnd={dragProps?.onDragEnd as React.ComponentProps<'div'>['onDragEnd']} onDrop={dragProps?.onDrop as React.ComponentProps<'div'>['onDrop']} className={cn( 'group rounded-xl border border-border/80 bg-card/90 p-3 shadow-sm shadow-black/10', dragProps?.isDragging && 'opacity-45', dragProps?.isDropTarget && 'ring-2 ring-primary/40', )} >
{hasHistory && ( )}
{bill.active ? 'Active' : 'Inactive'} {bill.autopay_enabled ? ( AP ) : null} {bill.has_2fa ? ( 2FA ) : null} {(bill.has_merchant_rule || bill.has_linked_transactions) ? ( L ) : null} {bill.is_subscription ? ( S ) : null}
${Number(bill.expected_amount).toFixed(2)}

Due

Day {bill.due_day}

Category

{bill.category_name || '—'}

Cycle

{scheduleLabel(bill)}

{!bill.active && ( )}
); }); MobileBillRow.displayName = 'MobileBillRow';