import { useEffect, useRef, useState } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { feedsApi } from '../api/feeds'; import { ApiError } from '../api/client'; interface AddFeedModalProps { onClose: () => void; } export function AddFeedModal({ onClose }: AddFeedModalProps) { const [url, setUrl] = useState(''); const [importResult, setImportResult] = useState(null); const fileInputRef = useRef(null); const previousFocus = useRef(null); const queryClient = useQueryClient(); const addFeedMutation = useMutation({ mutationFn: (u: string) => feedsApi.add({ url: u.trim() }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['feeds'] }); onClose(); }, }); const importMutation = useMutation({ mutationFn: (file: File) => feedsApi.importOPML(file), onSuccess: (res) => { queryClient.invalidateQueries({ queryKey: ['feeds'] }); setImportResult( `${res.imported} flux importé${res.imported > 1 ? 's' : ''}, ${res.skipped} ignoré${res.skipped > 1 ? 's' : ''}.`, ); }, }); useEffect(() => { previousFocus.current = document.activeElement as HTMLElement | null; const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; window.addEventListener('keydown', onKey); return () => { window.removeEventListener('keydown', onKey); previousFocus.current?.focus?.(); }; }, [onClose]); const addError = addFeedMutation.error instanceof ApiError && addFeedMutation.error.status === 409 ? 'Vous êtes déjà abonné à ce flux.' : 'Échec de l’ajout. Vérifiez l’adresse du flux.'; return (
e.stopPropagation()}>

Nouveau flux

Entrez l'URL d'un flux RSS ou Atom. FlowReader récupérera le titre et les articles automatiquement.

{ e.preventDefault(); addFeedMutation.mutate(url); }} className="space-y-5" >
setUrl(e.target.value)} className="input-field" placeholder="https://exemple.com/feed" required autoFocus aria-invalid={addFeedMutation.isError} aria-describedby={addFeedMutation.isError ? 'feed-url-error' : undefined} />
{addFeedMutation.isError && ( )}
{/* OPML import */}
{ const file = e.target.files?.[0]; if (file) importMutation.mutate(file); e.target.value = ''; }} />

{importResult && {importResult}} {importMutation.isError && Fichier OPML invalide ou trop volumineux.}

); }