"use client" import { useEffect, useMemo, useRef, useState } from "react" import type { IpsecPeerDto } from "@mmapp/contracts/ipsec" import { FormField, SectionTitle } from "@/components/form-kit" import { Button } from "@/components/ui/button" import { Switch } from "@/components/ui/switch" import { Input } from "@/components/ui/input" import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetFooter, SheetClose, } from "@/components/ui/sheet" export type IpsecPeerFormState = { name: string address: string exchangeMode: string passive: boolean profile: string disabled: boolean } export const defaultIpsecPeerForm = (): IpsecPeerFormState => ({ name: "", address: "0.0.0.0/0", exchangeMode: "ike2", passive: true, profile: "", disabled: false, }) const EXCHANGE_MODES = ["ike2", "main", "aggressive", "base"] /** Редактирование существующего peer (сервера) RouterOS. */ function IpsecPeerSheet({ open, onOpenChange, busy, editing, onSubmit, }: { open: boolean onOpenChange: (v: boolean) => void busy?: boolean editing: IpsecPeerDto | null onSubmit: (form: IpsecPeerFormState) => void | Promise }) { const [form, setForm] = useState(defaultIpsecPeerForm) const lock = useRef(false) const opened = useRef(false) const [submitting, setSubmitting] = useState(false) const [error, setError] = useState(null) const pending = busy || submitting const set = (k: K, v: IpsecPeerFormState[K]) => setForm((f) => ({ ...f, [k]: v })) useEffect(() => { if (!open) { opened.current = false; return } if (!editing || opened.current) return opened.current = true queueMicrotask(() => setError(null)) queueMicrotask(() => setForm({ name: editing.name, address: editing.address ?? "", exchangeMode: editing.exchangeMode ?? "ike2", passive: editing.passive ?? false, profile: editing.profile ?? "", disabled: editing.disabled, })) }, [open, editing]) const canSubmit = useMemo(() => form.name.trim().length > 0, [form.name]) const submit = async () => { if (!canSubmit || busy || lock.current) return lock.current = true setSubmitting(true) setError(null) try { await onSubmit(form) } catch (error) { setError(error instanceof Error ? error.message : "Не удалось сохранить peer") } finally { lock.current = false; setSubmitting(false) } } return ( { if (!lock.current && !busy) onOpenChange(value) }}> {editing ? `Peer «${editing.name}»` : "Peer"} {editing?.managed ? "Managed peer: изменения применяются напрямую на роутере" : "Существующий peer RouterOS: изменения применяются напрямую"}
Основные set("name", e.target.value)} /> set("address", e.target.value)} />

Сертификат аутентификации задаётся в identity. Эта форма изменяет только peer.

set("profile", e.target.value)} />
Состояние

Passive

set("passive", v)} />

Отключён

set("disabled", v)} />
{pending &&

Ожидание результата сохранения…

} {error &&

{error}

}
}> Отмена
) } export { IpsecPeerSheet }