'use client'; import { useState } from 'react'; import { motion } from 'framer-motion'; import { useRouter } from 'next/navigation'; import { MagnifyingGlass as Search, Dna, CircleNotch as LoaderCircle, CheckCircle, WarningCircle as AlertCircle, BookOpen, ArrowRight, Flask as Beaker } from '@phosphor-icons/react'; import { fadeUp, stagger } from '@/lib/animations'; import { fetchSequence, validateSequence, searchSequences } from '@/lib/api'; import { extractErrorMessage } from '@/lib/errors'; import type { SequenceResult, SequenceValidation, SequenceSearchResult } from '@/types/pipeline'; type InputMode = 'accession' | 'sequence' | 'name'; export function SequenceRetrieval() { const router = useRouter(); const [mode, setMode] = useState('accession'); const [input, setInput] = useState(''); const [loading, setLoading] = useState(false); const [result, setResult] = useState(null); const [validation, setValidation] = useState(null); const [searchResults, setSearchResults] = useState(null); const [error, setError] = useState(null); const [copied, setCopied] = useState(false); const handleSearch = async () => { if (!input.trim()) return; setLoading(true); setError(null); setResult(null); setValidation(null); setSearchResults(null); try { if (mode === 'accession') { const res = await fetchSequence(input.trim()); if (res.error) { setError(res.error); } else { setResult(res); } } else if (mode === 'sequence') { const res = await validateSequence(input); setValidation(res); } else if (mode === 'name') { const res = await searchSequences(input.trim()); if (res.error) { setError(res.error); } else { setSearchResults(res.results); } } } catch (err: unknown) { setError(extractErrorMessage(err)); } finally { setLoading(false); } }; const handleSelectAccession = async (accession: string) => { setInput(accession); setMode('accession'); setLoading(true); setError(null); setSearchResults(null); try { const res = await fetchSequence(accession); if (res.error) setError(res.error); else setResult(res); } catch (err: unknown) { setError(extractErrorMessage(err)); } finally { setLoading(false); } }; const copySequence = () => { if (result?.sequence) { navigator.clipboard.writeText(result.sequence); setCopied(true); setTimeout(() => setCopied(false), 2000); } }; const seqTypeColor = (type?: string) => { switch (type) { case 'protein': return 'text-molecule-protein bg-molecule-protein/10'; case 'dna': return 'text-molecule-dna bg-molecule-dna/10'; case 'rna': return 'text-molecule-rna bg-molecule-rna/10'; default: return 'text-text-muted bg-surface-0'; } }; return (

Sequence Retrieval

Look up a sequence by accession number, paste raw sequence data, or search by gene/protein name

{([ { id: 'accession' as const, label: 'Accession' }, { id: 'name' as const, label: 'Gene / Protein Name' }, { id: 'sequence' as const, label: 'Raw Sequence' }, ]).map((m) => ( ))}
{ setInput(e.target.value); setResult(null); setValidation(null); setSearchResults(null); setError(null); }} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} placeholder={ mode === 'accession' ? 'e.g. NP_000509.1, P04637, 1TIM' : mode === 'name' ? 'e.g. p53, BRCA1, TP53 human' : 'Paste FASTA or raw sequence...' } className="flex-1 px-4 py-3 rounded-xl border border-glass-border focus:border-accent-cyan focus:ring-2 focus:ring-accent-cyan/20 outline-none transition text-sm" />
{error && (

{error}

)} {validation && mode === 'sequence' && (
{validation.valid ? ( ) : ( )}

{validation.valid ? 'Valid Sequence' : 'Invalid Sequence'}

Type
{validation.sequence_type}
Length
{validation.length.toLocaleString()} residues
Format
{validation.format}
{validation.issues.length > 0 && (

Issues

{validation.issues.map((issue, i) => (

{issue}

))}
)}
)} {searchResults && mode === 'name' && (

Search Results ({searchResults.length})

{searchResults.length === 0 ? (

No results found

) : ( {searchResults.map((r, i) => ( ))} )}
)} {result && mode === 'accession' && (
{result.accession} {result.sequence_type} {result.db_source}

{result.description}

{result.organism && (

{result.organism}

)}
{result.length.toLocaleString()}
residues
Sequence
                {result.sequence}
              
{(result.gene_names && result.gene_names.length > 0) && (

Gene Names

{result.gene_names.map((g, i) => ( {g} ))}
)} {result.functions && result.functions.length > 0 && (

Functions

{result.functions.map((f, i) => (

{f}

))}
)} {result.pdb_ids && result.pdb_ids.length > 0 && (

PDB Structures

{result.pdb_ids.map((pdb, i) => ( {pdb} ))}
)} {result.features && result.features.length > 0 && (

Features

{result.features.slice(0, 10).map((f, i) => (
{f.type} {f.description} {f.begin && f.end && ( {f.begin}-{f.end} )}
))} {result.features.length > 10 && (

+{result.features.length - 10} more features

)}
)}
Source: {result.db_source} {result.from_cache && '(cached)'}
{(result.sequence_type === 'dna' || result.sequence_type === 'rna') && ( <> )}
)}
); }