"use client"; import { useState, useEffect } from "react"; import { useParticipants, useSetSplits, useTransactionSplits, useBulkAction } from "@/lib/hooks"; interface Split { participant_id: number; share_percent: number; } interface Props { transactionId?: number; transactionIds?: number[]; amount?: number; description: string; onClose: () => void; } export function SplitModal({ transactionId, transactionIds, amount, description, onClose }: Props) { const isBulk = !!transactionIds && transactionIds.length > 0; const singleId = transactionId ?? 0; const { data: participants } = useParticipants(); const { data: existingSplits } = useTransactionSplits(isBulk ? 0 : singleId); const setSplits = useSetSplits(); const bulkAction = useBulkAction(); const [splits, setSplitsState] = useState([]); const [error, setError] = useState(""); // Initialise: bulk always defaults to 100% Me; single loads existing splits useEffect(() => { if (!participants || participants.length === 0) return; const me = participants.find((p) => p.name === "Me"); if (isBulk) { if (me) setSplitsState([{ participant_id: me.id, share_percent: 100 }]); } else if (existingSplits && existingSplits.length > 0) { setSplitsState( existingSplits.map((s: { participant_id: number; share_percent: number }) => ({ participant_id: s.participant_id, share_percent: Number(s.share_percent), })) ); } else if (me) { setSplitsState([{ participant_id: me.id, share_percent: 100 }]); } }, [existingSplits, participants, isBulk]); const total = splits.reduce((sum, s) => sum + s.share_percent, 0); const toggleParticipant = (id: number) => { setSplitsState((prev) => { const exists = prev.find((s) => s.participant_id === id); if (exists) { return prev.filter((s) => s.participant_id !== id); } // Add with equal split const count = prev.length + 1; const equal = Math.floor(100 / count); const remainder = 100 - equal * count; return [ ...prev.map((s, i) => ({ ...s, share_percent: equal + (i === 0 ? remainder : 0) })), { participant_id: id, share_percent: equal }, ]; }); }; const updateShare = (id: number, value: number) => { setSplitsState((prev) => prev.map((s) => (s.participant_id === id ? { ...s, share_percent: value } : s)) ); }; const splitEvenly = () => { if (splits.length === 0) return; const each = Math.floor(100 / splits.length); const remainder = 100 - each * splits.length; setSplitsState((prev) => prev.map((s, i) => ({ ...s, share_percent: each + (i === 0 ? remainder : 0) })) ); }; const isPending = isBulk ? bulkAction.isPending : setSplits.isPending; const handleSave = async () => { setError(""); if (Math.abs(total - 100) > 0.01) { setError(`Shares must sum to 100% (currently ${total.toFixed(1)}%)`); return; } try { if (isBulk) { await bulkAction.mutateAsync({ action: "split", ids: transactionIds!, splits }); } else { await setSplits.mutateAsync({ transactionId: singleId, splits }); } onClose(); } catch (e) { setError(e instanceof Error ? e.message : "Failed to save splits"); } }; return (
e.stopPropagation()} >

{isBulk ? `Split ${transactionIds!.length} Transactions` : "Split Transaction"}

{description}

{!isBulk && amount !== undefined && (

${Number(amount).toFixed(2)}

)} {/* Participant toggles */}
{participants?.map((p) => { const split = splits.find((s) => s.participant_id === p.id); const active = !!split; return (
{p.name} {active && (
updateShare(p.id, Number(e.target.value))} className="w-24 accent-blue-600" /> {split.share_percent}% {!isBulk && amount !== undefined && ( ${((amount * split.share_percent) / 100).toFixed(2)} )}
)}
); })}
{/* Total indicator */}
0.01 ? "text-red-400" : "text-green-400"}`}> Total: {total.toFixed(1)}%
{error &&

{error}

}
); }