"use client"; import type React from "react"; import { useEffect, useMemo, useRef, useState } from "react"; import TagInput from "@/components/tag-input"; import { bucketIcons } from "@/lib/shared/bucket-icons"; import ToggleButtonGroup from "@/components/toggle-button-group"; type BucketForm = { name: string; description: string; iconKey: string; budgetLimitDollars: string; tags: string[]; necessity: string; windowDays: string; }; type NewBucketModalProps = { isOpen: boolean; title: string; form: BucketForm; error: string; onClose: () => void; onSubmit: (event: React.FormEvent) => void; onChange: (next: Partial) => void; tagSuggestions: string[]; canDelete?: boolean; onDelete?: () => void; }; export default function NewBucketModal({ isOpen, title, form, error, onClose, onSubmit, onChange, tagSuggestions, canDelete = false, onDelete }: NewBucketModalProps) { const [iconModalOpen, setIconModalOpen] = useState(false); const [iconSearch, setIconSearch] = useState(""); const formRef = useRef(null); const normalizedSearch = iconSearch.trim().toLowerCase(); const filteredIcons = useMemo(() => { if (!normalizedSearch) return bucketIcons; return bucketIcons.filter(item => item.label.toLowerCase().includes(normalizedSearch) || item.key.toLowerCase().includes(normalizedSearch)); }, [normalizedSearch]); const iconMap = useMemo(() => new Map(bucketIcons.map(item => [item.key, item.icon])), []); const selectedIcon = form.iconKey ? iconMap.get(form.iconKey) : iconMap.get("none"); useEffect(() => { if (!isOpen) return; function handleKeyDown(event: KeyboardEvent) { if (event.key === "Escape") { if (iconModalOpen) setIconModalOpen(false); else onClose(); } } window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [iconModalOpen, isOpen, onClose]); if (!isOpen) return null; return (
event.stopPropagation()} >
{title}
{ 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({ 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" } ]} />