import React, { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import { toast } from "sonner"; import { Bell, X } from "lucide-react"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { DialogFooter } from "@/components/ui/dialog"; import { Badge } from "@/components/ui/badge"; import { AddSSLCertificateDto } from "@/types/ssl.types"; import { alertConfigService, AlertConfiguration } from "@/services/alertConfigService"; import { sslNotificationTemplateService, SslNotificationTemplate } from "@/services/sslNotificationTemplateService"; import { useLanguage } from "@/contexts/LanguageContext"; const formSchema = z.object({ domain: z.string().min(1, "Domain is required"), warning_threshold: z.coerce.number().int().min(1).max(365), expiry_threshold: z.coerce.number().int().min(1).max(30), notification_channels: z.array(z.string()).optional(), alert_template: z.string().optional(), check_interval: z.coerce.number().int().min(1).max(30).optional() }); interface AddSSLCertificateFormProps { onSubmit: (data: AddSSLCertificateDto) => Promise; onCancel: () => void; isPending?: boolean; } export const AddSSLCertificateForm = ({ onSubmit, onCancel, isPending = false }: AddSSLCertificateFormProps) => { const { t } = useLanguage(); const [alertConfigs, setAlertConfigs] = useState([]); const [sslTemplates, setSslTemplates] = useState([]); const [isLoading, setIsLoading] = useState(false); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { domain: "", warning_threshold: 30, expiry_threshold: 7, notification_channels: [], alert_template: "none", check_interval: 1 } }); // Fetch notification channels and SSL templates when form loads useEffect(() => { const fetchData = async () => { setIsLoading(true); try { // Fetch notification channels const configs = await alertConfigService.getAlertConfigurations(); const enabledConfigs = configs.filter(config => { if (typeof config.enabled === 'string') { return config.enabled === "true"; } return config.enabled === true; }); setAlertConfigs(enabledConfigs); // Fetch SSL notification templates const templates = await sslNotificationTemplateService.getTemplates(); setSslTemplates(templates); } catch (error) { toast.error(t('failedToLoadCertificates')); } finally { setIsLoading(false); } }; fetchData(); }, [t]); const handleSubmit = async (values: z.infer) => { try { // Convert the form values to the required DTO format const certData: AddSSLCertificateDto = { domain: values.domain, warning_threshold: values.warning_threshold, expiry_threshold: values.expiry_threshold, notification_channel: values.notification_channels && values.notification_channels.length > 0 ? values.notification_channels.join(',') : '', notification_id: values.notification_channels && values.notification_channels.length > 0 ? values.notification_channels.join(',') : '', template_id: values.alert_template && values.alert_template !== 'none' ? values.alert_template : '', check_interval: values.check_interval }; await onSubmit(certData); form.reset(); } catch (error) { toast.error(t('failedToAddCertificate')); } }; const handleAddNotificationChannel = (channelId: string) => { const currentChannels = form.getValues("notification_channels") || []; if (!currentChannels.includes(channelId)) { form.setValue("notification_channels", [...currentChannels, channelId]); } }; const handleRemoveNotificationChannel = (channelId: string) => { const currentChannels = form.getValues("notification_channels") || []; form.setValue("notification_channels", currentChannels.filter(id => id !== channelId)); }; const selectedChannels = form.watch("notification_channels") || []; return (
( {t('domain')} )} />
( {t('warningThreshold')} {t('getNotifiedExpiration')} )} /> ( {t('expiryThreshold')} {t('getNotifiedCritical')} )} />
( Check Interval (Days) How often to check the SSL certificate (in days) )} /> ( {t('notificationChannel')} (Multi-select)
{/* Display selected channels */} {selectedChannels.length > 0 && (
{selectedChannels.map((channelId) => { const channel = alertConfigs.find(config => config.id === channelId); return ( {channel ? `${channel.notify_name} (${channel.notification_type})` : channelId} ); })}
)}
{t('whereToSend')}
)} /> ( Alert Template Template for SSL certificate alert messages )} /> ); };