import { useState, useRef, useEffect, useCallback } from 'react' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { FilterBuilder } from './FilterBuilder' import { EmojiPicker } from './EmojiPicker' import type { FilterGroup, ViewDefinition } from '../types' type SaveViewResult = boolean | void type SaveViewHandler = (definition: ViewDefinition) => SaveViewResult | Promise type InitialViewFormValues = Pick interface CreateViewDialogProps { open: boolean onClose: () => void onCreate: SaveViewHandler availableFields: string[] /** When provided, the dialog operates in edit mode with pre-populated fields. */ editingView?: ViewDefinition | null } interface CreateViewDialogFormProps { availableFields: string[] initialName: string initialIcon: string initialColor: string | null initialFilters: FilterGroup isEditing: boolean onClose: () => void onCreate: SaveViewHandler } function CreateViewDialogForm({ availableFields, initialName, initialIcon, initialColor, initialFilters, isEditing, onClose, onCreate, }: CreateViewDialogFormProps) { const [name, setName] = useState(initialName) const [icon, setIcon] = useState(initialIcon) const [showEmojiPicker, setShowEmojiPicker] = useState(false) const [filters, setFilters] = useState(initialFilters) const [saveError, setSaveError] = useState(null) const [isSaving, setIsSaving] = useState(false) const inputRef = useRef(null) useEffect(() => { const timeoutId = window.setTimeout(() => inputRef.current?.focus(), 50) return () => window.clearTimeout(timeoutId) }, []) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() if (isSaving) return const trimmed = name.trim() if (!trimmed) return const definition: ViewDefinition = { name: trimmed, icon: icon || null, color: initialColor, sort: null, filters, } setSaveError(null) setIsSaving(true) let shouldClose = false try { const result = await onCreate(definition) if (result === false) { setSaveError('Could not save view.') } else { shouldClose = true } } catch { setSaveError('Could not save view.') } setIsSaving(false) if (shouldClose) onClose() } const handleSelectEmoji = useCallback((emoji: string) => { setIcon(emoji) setShowEmojiPicker(false) }, []) const handleCloseEmojiPicker = useCallback(() => { setShowEmojiPicker(false) }, []) const isCreateDisabled = !name.trim() return (
{showEmojiPicker && ( )}
{ setName(e.target.value) if (saveError) setSaveError(null) }} />
{saveError && (

{saveError}

)}
) } function getInitialViewFormValues( editingView: ViewDefinition | null | undefined, availableFields: string[], ): InitialViewFormValues { return { name: editingView?.name ?? '', icon: editingView?.icon ?? '', color: editingView?.color ?? null, filters: editingView?.filters ?? { all: [{ field: availableFields[0] ?? 'type', op: 'equals', value: '' }] }, } } function getDialogDescription(isEditing: boolean) { return isEditing ? 'Update the name, icon, and filters for this saved view.' : 'Create a saved view by choosing a name, icon, and filter rules.' } export function CreateViewDialog({ open, onClose, onCreate, availableFields, editingView }: CreateViewDialogProps) { const isEditing = !!editingView const initialValues = getInitialViewFormValues(editingView, availableFields) const formKey = editingView ? `edit:${editingView.name}` : `create:${availableFields[0] ?? 'type'}` return ( { if (!isOpen) onClose() }}> {isEditing ? 'Edit View' : 'Create View'} {getDialogDescription(isEditing)} {open && ( )} ) }