"use client"; import { useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { HeadersInput } from "@app/components/HeadersInput"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Credenza, CredenzaBody, CredenzaClose, CredenzaContent, CredenzaDescription, CredenzaFooter, CredenzaHeader, CredenzaTitle } from "@/components/Credenza"; import { toast } from "@/hooks/useToast"; import { useTranslations } from "next-intl"; type HealthCheckConfig = { hcEnabled: boolean; hcPath: string; hcMethod: string; hcInterval: number; hcTimeout: number; hcStatus: number | null; hcHeaders?: { name: string; value: string }[] | null; hcScheme?: string; hcHostname: string; hcPort: number; hcFollowRedirects: boolean; hcMode: string; hcUnhealthyInterval: number; }; type HealthCheckDialogProps = { open: boolean; setOpen: (val: boolean) => void; targetId: number; targetAddress: string; targetMethod?: string; initialConfig?: Partial; onChanges: (config: HealthCheckConfig) => Promise; }; export default function HealthCheckDialog({ open, setOpen, targetId, targetAddress, targetMethod, initialConfig, onChanges }: HealthCheckDialogProps) { const t = useTranslations(); const healthCheckSchema = z.object({ hcEnabled: z.boolean(), hcPath: z.string().min(1, { message: t("healthCheckPathRequired") }), hcMethod: z .string() .min(1, { message: t("healthCheckMethodRequired") }), hcInterval: z .number() .int() .positive() .min(5, { message: t("healthCheckIntervalMin") }), hcTimeout: z .number() .int() .positive() .min(1, { message: t("healthCheckTimeoutMin") }), hcStatus: z.number().int().positive().min(100).optional().nullable(), hcHeaders: z.array(z.object({ name: z.string(), value: z.string() })).nullable().optional(), hcScheme: z.string().optional(), hcHostname: z.string(), hcPort: z.number().positive().gt(0).lte(65535), hcFollowRedirects: z.boolean(), hcMode: z.string(), hcUnhealthyInterval: z.number().int().positive().min(5) }); const form = useForm>({ resolver: zodResolver(healthCheckSchema), defaultValues: {} }); useEffect(() => { if (!open) return; // Determine default scheme from target method const getDefaultScheme = () => { if (initialConfig?.hcScheme) { return initialConfig.hcScheme; } // Default to target method if it's http or https, otherwise default to http if (targetMethod === "https") { return "https"; } return "http"; }; form.reset({ hcEnabled: initialConfig?.hcEnabled, hcPath: initialConfig?.hcPath, hcMethod: initialConfig?.hcMethod, hcInterval: initialConfig?.hcInterval, hcTimeout: initialConfig?.hcTimeout, hcStatus: initialConfig?.hcStatus, hcHeaders: initialConfig?.hcHeaders, hcScheme: getDefaultScheme(), hcHostname: initialConfig?.hcHostname, hcPort: initialConfig?.hcPort, hcFollowRedirects: initialConfig?.hcFollowRedirects, hcMode: initialConfig?.hcMode, hcUnhealthyInterval: initialConfig?.hcUnhealthyInterval }); }, [open]); const watchedEnabled = form.watch("hcEnabled"); const handleFieldChange = async (fieldName: string, value: any) => { try { const currentValues = form.getValues(); const updatedValues = { ...currentValues, [fieldName]: value }; await onChanges({ ...updatedValues, hcStatus: updatedValues.hcStatus || null }); } catch (error) { toast({ title: t("healthCheckError"), description: t("healthCheckErrorDescription"), variant: "destructive" }); } }; return ( {t("configureHealthCheck")} {t("configureHealthCheckDescription", { target: targetAddress })}
{/* Enable Health Checks */} (
{t("enableHealthChecks")} {t( "enableHealthChecksDescription" )}
{ field.onChange(value); handleFieldChange( "hcEnabled", value ); }} />
)} /> {watchedEnabled && (
( {t("healthScheme")} )} /> ( {t("healthHostname")} { field.onChange( e ); handleFieldChange( "hcHostname", e.target .value ); }} /> )} /> ( {t("healthPort")} { const value = parseInt( e.target .value ); field.onChange( value ); handleFieldChange( "hcPort", value ); }} /> )} /> ( {t("healthCheckPath")} { field.onChange( e ); handleFieldChange( "hcPath", e.target .value ); }} /> )} />
{/* HTTP Method */} ( {t("httpMethod")} )} /> {/* Check Interval, Timeout, and Retry Attempts */}
( {t( "healthyIntervalSeconds" )} { const value = parseInt( e.target .value ); field.onChange( value ); handleFieldChange( "hcInterval", value ); }} /> )} /> ( {t( "unhealthyIntervalSeconds" )} { const value = parseInt( e.target .value ); field.onChange( value ); handleFieldChange( "hcUnhealthyInterval", value ); }} /> )} /> ( {t("timeoutSeconds")} { const value = parseInt( e.target .value ); field.onChange( value ); handleFieldChange( "hcTimeout", value ); }} /> )} /> {t("timeIsInSeconds")}
{/* Expected Response Codes */} ( {t("expectedResponseCodes")} { const value = parseInt( e.target .value ); field.onChange( value ); handleFieldChange( "hcStatus", value ); }} /> {t( "expectedResponseCodesDescription" )} )} /> {/* Custom Headers */} ( {t("customHeaders")} { field.onChange(value); handleFieldChange( "hcHeaders", value ); }} rows={4} /> {t( "customHeadersDescription" )} )} />
)}
); }