"use client"; import { useState, useEffect } from "react"; import { Check, X, Loader2, AlertCircle } from "lucide-react"; import { cn } from "@/utils/cn"; export type StatusType = "idle" | "loading" | "success" | "error"; interface InlineStatusProps { status: StatusType; message?: string; className?: string; showIcon?: boolean; autoClear?: boolean; // Auto-clear success/error after delay clearDelay?: number; // Delay in ms before clearing (default 3000) onClear?: () => void; } /** * Inline status indicator for form fields and buttons * Shows success/error/loading states without overlay toasts */ export function InlineStatus({ status, message, className, showIcon = true, autoClear = true, clearDelay = 3000, onClear, }: InlineStatusProps) { const [visible, setVisible] = useState(status !== "idle"); useEffect(() => { if (status === "success" || status === "error") { setVisible(true); if (autoClear) { const timer = setTimeout(() => { setVisible(false); onClear?.(); }, clearDelay); return () => clearTimeout(timer); } } else if (status === "loading") { setVisible(true); } else { setVisible(false); } }, [status, autoClear, clearDelay, onClear]); if (status === "idle" || !visible) return null; return ( {showIcon && ( <> {status === "success" && } {status === "error" && } {status === "loading" && } )} {message && {message}} ); } /** * Hook for managing inline status state */ export function useInlineStatus(initialStatus: StatusType = "idle") { const [status, setStatus] = useState(initialStatus); const [message, setMessage] = useState(""); const setSuccess = (msg?: string) => { setStatus("success"); setMessage(msg || ""); }; const setError = (msg?: string) => { setStatus("error"); setMessage(msg || ""); }; const setLoading = (msg?: string) => { setStatus("loading"); setMessage(msg || ""); }; const reset = () => { setStatus("idle"); setMessage(""); }; return { status, message, setSuccess, setError, setLoading, reset, props: { status, message, onClear: reset }, }; } /** * Connection test button with inline status */ interface ConnectionTestButtonProps { label: string; onTest: () => Promise; className?: string; disabled?: boolean; } export function ConnectionTestButton({ label, onTest, className, disabled, }: ConnectionTestButtonProps) { const { status, message, setSuccess, setError, setLoading, reset, props } = useInlineStatus(); const handleTest = async () => { setLoading("Testing..."); try { const result = await onTest(); if (result === false || result === null) { setError("Failed"); } else if (typeof result === "string") { setSuccess(result); } else { setSuccess("Connected"); } } catch (err: any) { setError(err.message || "Failed"); } }; return (
); } /** * Save button with inline status */ interface SaveButtonProps { onSave: () => Promise; label?: string; className?: string; disabled?: boolean; } export function SaveButton({ onSave, label = "Save", className, disabled, }: SaveButtonProps) { const { status, setSuccess, setError, setLoading, props } = useInlineStatus(); const handleSave = async () => { setLoading(); try { await onSave(); setSuccess("Saved"); } catch (err: any) { setError(err.message || "Failed"); } }; return (
); }