"use client"; import type React from "react"; import { useEffect, useRef } from "react"; import DatePicker from "@/components/date-picker"; import TagInput from "@/components/tag-input"; import ToggleButtonGroup from "@/components/toggle-button-group"; import type { ScheduleEndCondition, ScheduleFrequency } from "@/lib/shared/types"; export type NewScheduleForm = { amountDollars: string; startsOn: string; necessity: "NECESSARY" | "BOTH" | "UNNECESSARY"; notes: string; tags: string[]; entryType: "SPENDING" | "INCOME"; frequency: ScheduleFrequency; intervalCount: number; endCondition: ScheduleEndCondition; endCount: string; endDate: string; createEntryNow: boolean; }; type NewScheduleModalProps = { isOpen: boolean; form: NewScheduleForm; error: string; onClose: () => void; onSubmit: (event: React.FormEvent) => void; onChange: (next: Partial) => void; tagSuggestions: string[]; emptyTagActionLabel?: string; emptyTagActionDisabled?: boolean; onEmptyTagAction?: () => void; }; export default function NewScheduleModal({ isOpen, form, error, onClose, onSubmit, onChange, tagSuggestions, emptyTagActionLabel, emptyTagActionDisabled = false, onEmptyTagAction }: NewScheduleModalProps) { const formRef = useRef(null); useEffect(() => { if (!isOpen) return; function handleKeyDown(event: KeyboardEvent) { if (event.key === "Escape") onClose(); } if (!form.startsOn) { const today = new Date().toISOString().slice(0, 10); onChange({ startsOn: today }); } window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [form.startsOn, isOpen, onChange, onClose]); if (!isOpen) return null; return (
event.stopPropagation()}>

New Schedule

onChange({ entryType })} ariaLabel="Entry type" className="flex items-center gap-[-50px] rounded-full border border-accent-weak bg-panel" sizeClassName="px-4 py-2.5 text-xs font-semibold" options={[ { value: "SPENDING", label: "Spending", className: "mr-[-10px]" }, { value: "INCOME", label: "Income" } ]} /> onChange({ createEntryNow: value === "NOW" })} ariaLabel="Create behavior" sizeClassName="px-3 py-2 text-xs font-semibold" options={[ { value: "NOW", label: "Create Entry Now" }, { value: "NEXT", label: "Start Next Schedule" } ]} />
{ 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({ startsOn })} required className="mt-1" />
onChange({ necessity })} ariaLabel="Necessity" className="mt-1 flex items-center gap-2 rounded-full border border-accent-weak bg-panel" sizeClassName="px-3 py-2.5 text-xs font-semibold" options={[ { value: "NECESSARY", label: "Necessary", className: "flex-1" }, { value: "BOTH", label: "Both", className: "flex-1" }, { value: "UNNECESSARY", label: "Unnecessary", className: "flex-1" } ]} />
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} />
Every
onChange({ intervalCount: Number(e.target.value || 1) })} /> onChange({ endCondition })} ariaLabel="End condition" className="flex items-center gap-1 rounded-full border border-accent-weak bg-panel" sizeClassName="px-3 py-3 text-xs font-semibold" options={[ { value: "NEVER", label: "Forever" }, { value: "BY_DATE", label: "Until" }, { value: "AFTER_COUNT", label: "After" } ]} /> {form.endCondition === "AFTER_COUNT" ? ( onChange({ endCount: e.target.value })} /> ) : null} {form.endCondition === "BY_DATE" ? ( onChange({ endDate })} showWeekButtons={false} centerInput /> ) : null}