import { useState, type FormEvent } from "react"; import * as stylex from "@stylexjs/stylex"; import InlineError from "@/lib/InlineError"; import type { Upstream, UpstreamInput } from "@/lib/types"; import { styles as shared } from "@/ui/styles"; import { colors } from "@/ui/tokens.stylex"; import { READ_ONLY_HINT } from "@/features/settings/authority"; const DEFAULT_PRIORITY = "100"; interface UpstreamFormProps { initial?: Upstream; busy: boolean; /** File authority: the server answers 403, so the submit stays down. */ readOnly: boolean; error: Error | null; onSubmit: (input: UpstreamInput) => Promise; onCancel?: () => void; } const styles = stylex.create({ form: { display: "flex", flexDirection: "column", gap: "0.75rem", marginTop: "1rem", maxWidth: "36rem", }, heading: { fontSize: "1.125rem", lineHeight: "1.75rem", fontWeight: 500, }, fieldLabel: { display: "block", fontSize: "0.875rem", lineHeight: "1.25rem", fontWeight: 500, }, hint: { marginTop: "0.25rem", fontSize: "0.75rem", lineHeight: "1rem", color: colors.textMuted, }, checkboxLabel: { display: "flex", alignItems: "center", gap: "0.5rem", fontSize: "0.875rem", lineHeight: "1.25rem", fontWeight: 500, }, actions: { display: "flex", alignItems: "center", gap: "0.5rem", }, cancelButton: { fontWeight: 500, }, }); export default function UpstreamForm({ initial, busy, readOnly, error, onSubmit, onCancel }: UpstreamFormProps) { const [url, setUrl] = useState(initial?.url ?? ""); const [priority, setPriority] = useState(initial === undefined ? DEFAULT_PRIORITY : String(initial.priority)); const [enabled, setEnabled] = useState(initial?.enabled ?? true); const [tlsName, setTlsName] = useState(initial?.tls_name ?? ""); async function handleSubmit(event: FormEvent) { event.preventDefault(); const parsed = Number(priority); try { // PUT replaces the row, so every field goes on every submit. await onSubmit({ url: url.trim(), priority: Number.isFinite(parsed) ? parsed : 0, enabled, tls_name: tlsName.trim(), }); if (initial === undefined) { setUrl(""); setPriority(DEFAULT_PRIORITY); setEnabled(true); setTlsName(""); } } catch { // The page renders the mutation error inline below the form. } } return (

{initial === undefined ? "Add upstream" : `Edit ${initial.url}`}

setUrl(event.target.value)} placeholder="udp://1.1.1.1:53" {...stylex.props(shared.input, shared.focusRing)} />
setPriority(event.target.value)} {...stylex.props(shared.input, shared.focusRing)} />
setTlsName(event.target.value)} placeholder="one.one.one.one" {...stylex.props(shared.input, shared.focusRing)} />

The SNI and certificate name for a tls:// upstream. Leave empty for every other scheme.

{onCancel !== undefined && ( )}
); }