From d32e49454fbe3799c6d943f2fad1bdfb636ef544 Mon Sep 17 00:00:00 2001 From: Ayana Sarkar Date: Tue, 21 Apr 2026 23:55:28 +0530 Subject: [PATCH 1/4] added new tab and fixed bugs --- src/components/ui/form.tsx | 844 +++++++++++++++++++++++++++++-------- 1 file changed, 677 insertions(+), 167 deletions(-) diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx index 4f02ae6..9b21b7b 100644 --- a/src/components/ui/form.tsx +++ b/src/components/ui/form.tsx @@ -1,178 +1,688 @@ -"use client" +"use client"; -import * as React from "react" -import * as LabelPrimitive from "@radix-ui/react-label" -import { Slot } from "@radix-ui/react-slot" +import * as React from "react"; +import Link from 'next/link'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { Button } from "@/components/ui/button"; +import { RainbowButton } from "@/components/ui/rainbow-button"; +import { Input } from "@/components/ui/input"; +import AuthPresetGenerator from "./auth-preset-generator"; +import { Badge } from "@/components/ui/badge"; import { - Controller, - FormProvider, - useFormContext, - type ControllerProps, - type FieldPath, - type FieldValues, -} from "react-hook-form" - -import { cn } from "@/lib/utils" -import { Label } from "@/components/ui/label" - -const Form = FormProvider - -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath -> = { - name: TName -} + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { ToastAction } from "@/components/ui/toast"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + Trash2, Copy, FileText, Plus, Database, Power, Code, Eye, + MoreHorizontal, Edit, CopyPlus, PauseCircle, PlayCircle, + Search, Filter, ArrowUpDown, ChevronDown, CheckCircle2, + Activity, Play, Globe, Terminal, Zap, Shield, Settings2, + ExternalLink +} from "lucide-react"; +import { toast } from "@/hooks/use-toast"; +import { cn } from "@/lib/utils"; +import { useRouter, useSearchParams } from "next/navigation"; +import { deleteFormAction, duplicateFormAction, toggleFormStatusAction, deleteAuthPresetAction } from "@/app/actions/dashboard"; +import IsoLevelWarp from "@/components/ui/isometric-wave-grid-background"; +import { FormSearchBar } from "@/components/ui/animated-search-bar"; +import { motion, AnimatePresence } from "framer-motion"; + +type Form = { + id: string; + name: string; + connectorName: string; + submissions: number; + lastSubmission: string; + status: "Live" | "Paused"; + fields: any[]; +}; -const FormFieldContext = React.createContext( - {} as FormFieldContextValue -) - -const FormField = < - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath ->({ - ...props -}: ControllerProps) => { - return ( - - - - ) +interface FormsClientProps { + initialForms: any[]; + initialPresets?: any[]; } -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext) - const itemContext = React.useContext(FormItemContext) - const { getFieldState, formState } = useFormContext() +export default function FormsClient({ initialForms = [], initialPresets = [] }: FormsClientProps) { + const router = useRouter(); + const [isCreatingPreset, setIsCreatingPreset] = React.useState(false); + const [editingPreset, setEditingPreset] = React.useState(null); + const [presets, setPresets] = React.useState(initialPresets); + const [searchQuery, setSearchQuery] = React.useState(""); + const [statusFilter, setStatusFilter] = React.useState("all"); + const [dbFilter, setDbFilter] = React.useState("all"); + const [sortBy, setSortBy] = React.useState("name"); + const [expandedFormId, setExpandedFormId] = React.useState(null); + const [copiedId, setCopiedId] = React.useState(null); + const [searchExpanded, setSearchExpanded] = React.useState(false); + const pendingDeletions = React.useRef>({}); - const fieldState = getFieldState(fieldContext.name, formState) - if (!fieldContext) { - throw new Error("useFormField should be used within ") - } + const searchParams = useSearchParams(); - const { id } = itemContext + React.useEffect(() => { + const tab = searchParams.get('tab'); + if (tab === 'presets') { + // Since we're using Radix/Shadcn Tabs, we might need to control the state if we want to programmatically switch. + // But if we just want to open the 'isCreatingPreset' dialog if an action is specified: + const action = searchParams.get('action'); + if (action === 'new-preset') { + setIsCreatingPreset(true); + } + } + }, [searchParams]); - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - } -} + React.useEffect(() => { setPresets(initialPresets); }, [initialPresets]); -type FormItemContextValue = { - id: string -} + const mapForms = (data: any[]): Form[] => data.map((f: any) => { + const subCount = f.submissionCount !== undefined ? f.submissionCount : (f.submissions?.length || 0); + let lastSub = "Never"; + if (subCount > 0 && f.submissions?.length > 0) { + const sorted = [...f.submissions].sort((a: any, b: any) => + new Date(b.submittedAt).getTime() - new Date(a.submittedAt).getTime() + ); + if (sorted[0]) { + const diffMs = Date.now() - new Date(sorted[0].submittedAt).getTime(); + const m = Math.round(diffMs / 60000); + const h = Math.round(m / 60); + const d = Math.round(h / 24); + if (m < 60) lastSub = `${m}m ago`; + else if (h < 24) lastSub = `${h}h ago`; + else lastSub = `${d}d ago`; + } + } + return { + id: f.id, name: f.name, + connectorName: f.targetDatabase || f.connectorName || "Default Connector", + submissions: subCount, lastSubmission: lastSub, + status: f.status || "Live", fields: f.fields || [] + }; + }); -const FormItemContext = React.createContext( - {} as FormItemContextValue -) - -const FormItem = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => { - const id = React.useId() - - return ( - -
- - ) -}) -FormItem.displayName = "FormItem" - -const FormLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => { - const { error, formItemId } = useFormField() - - return ( -