import { faPlus, faSpinner } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useState } from "react"; import { useMutation } from "urql"; import { AddFeedDocument } from "../graphql/generated/graphql"; interface Props { onFeedAdded?: () => void; } export function AddFeedForm({ onFeedAdded }: Props) { const [url, setUrl] = useState(""); const [error, setError] = useState(null); const [{ fetching }, addFeed] = useMutation(AddFeedDocument); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!url.trim()) return; setError(null); try { const result = await addFeed({ url: url.trim() }); if (result.error) { setError(result.error.message); } else if (result.data) { setUrl(""); onFeedAdded?.(); } } catch (error) { setError( error instanceof Error ? error.message : "Failed to subscribe to feed", ); } }; const isValidUrl = (urlString: string) => { try { const url = new URL(urlString); return url.protocol === "http:" || url.protocol === "https:"; } catch { return false; } }; const isUrlValid = !url || isValidUrl(url); return (

Subscribe to New Feed

setUrl(e.target.value)} placeholder="https://example.com/feed.xml" className={`w-full rounded-md border px-3 py-2 text-sm focus:outline-none focus:ring-2 ${ isUrlValid ? "border-gray-300 focus:border-blue-500 focus:ring-blue-500" : "border-red-300 focus:border-red-500 focus:ring-red-500" }`} disabled={fetching} /> {!isUrlValid && (

Please enter a valid URL (http:// or https://)

)} {error &&

{error}

}
); }