"use client"; import type React from "react"; import { useEffect, useRef } from "react"; import TagInput from "@/components/tag-input"; type NewEntryForm = { amountDollars: string; occurredAt: string; necessity: string; notes: string; tags: string[]; entryType: "SPENDING" | "INCOME"; isRecurring: boolean; frequency: "DAILY" | "WEEKLY" | "BIWEEKLY" | "MONTHLY" | "QUARTERLY" | "YEARLY"; intervalCount: number; endCondition: "NEVER" | "AFTER_COUNT" | "BY_DATE"; endCount: string; endDate: string; }; type NewEntryModalProps = { isOpen: boolean; form: NewEntryForm; error: string; onClose: () => void; onSubmit: (event: React.FormEvent) => void; onChange: (next: Partial) => void; tagSuggestions: string[]; emptyTagActionLabel?: string; emptyTagActionDisabled?: boolean; onEmptyTagAction?: () => void; amountInputRef?: React.Ref; tagsInputRef?: React.Ref; }; export default function NewEntryModal({ isOpen, form, error, onClose, onSubmit, onChange, tagSuggestions, emptyTagActionLabel, emptyTagActionDisabled = false, onEmptyTagAction, amountInputRef, tagsInputRef }: NewEntryModalProps) { const recurrenceLabel = form.isRecurring ? "Recurring" : "One-Time"; const typeLabel = form.entryType === "INCOME" ? "Income" : "Expense"; const formRef = useRef(null); useEffect(() => { if (!isOpen) return; function handleKeyDown(event: KeyboardEvent) { if (event.key === "Escape") onClose(); } if (!form.occurredAt) { const today = new Date().toISOString().slice(0, 10); onChange({ occurredAt: today, endDate: form.endDate || today }); } window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [form.endDate, form.occurredAt, isOpen, onChange, onClose]); function shiftDate(days: number) { const base = form.occurredAt ? new Date(form.occurredAt) : new Date(); if (Number.isNaN(base.getTime())) return; base.setDate(base.getDate() + days); onChange({ occurredAt: base.toISOString().slice(0, 10) }); } if (!isOpen) return null; return (
event.stopPropagation()} >

New {recurrenceLabel} {typeLabel} Entry

{ if (event.key !== "Enter" || event.defaultPrevented || event.shiftKey) return; const target = event.target as HTMLElement; if (target?.tagName === "TEXTAREA") return; event.preventDefault(); formRef.current?.requestSubmit(); }} className="mt-3 grid gap-3 md:grid-cols-2" >
onChange({ occurredAt: e.target.value })} required />
{([ { value: "NECESSARY", label: "Necessary" }, { value: "BOTH", label: "Both" }, { value: "UNNECESSARY", label: "Unnecessary" } ] as const).map(option => ( ))}
{/* TAGS */} onChange({ tags: form.tags.filter(item => item !== tag) })} onAddTag={tag => onChange({ tags: [...form.tags, tag] })} emptySuggestionLabel={emptyTagActionLabel} emptySuggestionDisabled={emptyTagActionDisabled} onEmptySuggestionClick={onEmptyTagAction} invalid={!form.tags.length} inputRef={tagsInputRef} /> {/* RECURRING OPTIONS */} {form.isRecurring ? (
Frequency Conditions
onChange({ intervalCount: Number(e.target.value || 1) })} />
{([ { value: "NEVER", label: "Forever" }, { value: "BY_DATE", label: "Until" }, { value: "AFTER_COUNT", label: "After" } ] as const).map(option => ( ))}
{form.endCondition === "AFTER_COUNT" ? ( onChange({ endCount: e.target.value })} /> ) : null} {form.endCondition === "BY_DATE" ? (
onChange({ endDate: e.target.value })} />
) : null}
) : null}