diff --git a/src/components/CitationManager.tsx b/src/components/CitationManager.tsx deleted file mode 100644 index 7aa148e..0000000 --- a/src/components/CitationManager.tsx +++ /dev/null @@ -1,835 +0,0 @@ -/** - * CitationManager Component - * Admin interface for managing the citation library. - */ - -import { useState, useEffect, useCallback } from 'react'; -import { - Plus, - Edit2, - Trash2, - Save, - X, - Search, - Copy, - RefreshCw, - CheckCircle, - AlertCircle, - ExternalLink, - BookOpen, - Scale, - FileText, - Gavel, - Globe, - BookMarked, -} from 'lucide-react'; -import type { Citation, CitationType } from '../utils/citationTypes'; -import { - CITATION_TYPES, - LEGAL_CATEGORIES, - JURISDICTIONS, - FEDERAL_REPORTERS, - COURTS, -} from '../utils/citationTypes'; -import { - createCitation, - updateCitation, - deleteCitation, - getAllCitations, - getCitationTypeCounts, -} from '../utils/citationService'; -import { buildCitationString, parseCitationString, validateCitation } from '../utils/citationFormatter'; -import { safeHref } from '../utils/safeHref'; - -// ============================================ -// Type Icons -// ============================================ - -const TYPE_ICONS: Record> = { - case: Gavel, - statute: BookOpen, - regulation: FileText, - constitution: Scale, - secondary: BookMarked, - treaty: Globe, -}; - -// ============================================ -// Sub-Components -// ============================================ - -interface CitationFormProps { - citation?: Citation; - onSave: (citation: Omit) => void; - onCancel: () => void; -} - -function CitationForm({ citation, onSave, onCancel }: CitationFormProps) { - const [type, setType] = useState(citation?.type || 'case'); - const [title, setTitle] = useState(citation?.title || ''); - const [citationStr, setCitationStr] = useState(citation?.citation || ''); - const [court, setCourt] = useState(citation?.court || ''); - const [year, setYear] = useState(citation?.year || ''); - const [volume, setVolume] = useState(citation?.volume || ''); - const [reporter, setReporter] = useState(citation?.reporter || ''); - const [page, setPage] = useState(citation?.page || ''); - const [pinpoint, setPinpoint] = useState(citation?.pinpoint || ''); - const [jurisdiction, setJurisdiction] = useState(citation?.jurisdiction || ''); - const [codeTitle, setCodeTitle] = useState(citation?.codeTitle || ''); - const [section, setSection] = useState(citation?.section || ''); - const [subdivision, setSubdivision] = useState(citation?.subdivision || ''); - const [shortForm, setShortForm] = useState(citation?.shortForm || ''); - const [parenthetical, setParenthetical] = useState(citation?.parenthetical || ''); - const [url, setUrl] = useState(citation?.url || ''); - const [category, setCategory] = useState(citation?.category || ''); - const [tags, setTags] = useState(citation?.tags || []); - const [tagInput, setTagInput] = useState(''); - const [notes, setNotes] = useState(citation?.notes || ''); - const [isVerified, setIsVerified] = useState(citation?.isVerified || false); - const [errors, setErrors] = useState([]); - - // Auto-build citation string when components change - useEffect(() => { - if (type === 'case' && title && (volume || reporter || page)) { - const built = buildCitationString({ - type, - title, - volume, - reporter, - page, - court, - year: year || undefined, - }); - if (built && built !== citationStr) { - setCitationStr(built); - } - } else if ((type === 'statute' || type === 'regulation') && codeTitle && section) { - const built = buildCitationString({ - type, - codeTitle, - section, - subdivision, - year: year || undefined, - }); - if (built && built !== citationStr) { - setCitationStr(built); - } - } - }, [type, title, volume, reporter, page, court, year, codeTitle, section, subdivision]); - - // Parse citation string to extract components - const handleParseCitation = () => { - if (!citationStr) return; - const parsed = parseCitationString(citationStr); - if (parsed.type) setType(parsed.type as CitationType); - if (parsed.title) setTitle(parsed.title); - if (parsed.volume) setVolume(parsed.volume); - if (parsed.reporter) setReporter(parsed.reporter); - if (parsed.page) setPage(parsed.page); - if (parsed.pinpoint) setPinpoint(parsed.pinpoint); - if (parsed.court) setCourt(parsed.court); - if (parsed.year) setYear(parsed.year); - if (parsed.codeTitle) setCodeTitle(parsed.codeTitle); - if (parsed.section) setSection(parsed.section); - if (parsed.subdivision) setSubdivision(parsed.subdivision); - }; - - const handleAddTag = () => { - if (tagInput.trim() && !tags.includes(tagInput.trim())) { - setTags([...tags, tagInput.trim()]); - setTagInput(''); - } - }; - - const handleRemoveTag = (tag: string) => { - setTags(tags.filter(t => t !== tag)); - }; - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - - const citationData = { - title: title.trim(), - citation: citationStr.trim(), - type, - court: court || undefined, - year: year || undefined, - volume: volume || undefined, - reporter: reporter || undefined, - page: page || undefined, - pinpoint: pinpoint || undefined, - jurisdiction: jurisdiction || undefined, - codeTitle: codeTitle || undefined, - section: section || undefined, - subdivision: subdivision || undefined, - shortForm: shortForm || undefined, - parenthetical: parenthetical || undefined, - url: url || undefined, - category: category || undefined, - tags, - notes: notes || undefined, - isVerified, - lastUsedAt: citation?.lastUsedAt, - createdBy: citation?.createdBy, - }; - - const validation = validateCitation(citationData); - if (!validation.valid) { - setErrors(validation.errors); - return; - } - - setErrors([]); - onSave(citationData); - }; - - return ( -
- {/* Errors */} - {errors.length > 0 && ( -
-
- - Please fix the following errors: -
-
    - {errors.map((error, i) => ( -
  • {error}
  • - ))} -
-
- )} - - {/* Citation Type */} -
- -
- {CITATION_TYPES.map((t) => { - const Icon = TYPE_ICONS[t.value]; - return ( - - ); - })} -
-
- - {/* Quick Parse */} -
- -
- setCitationStr(e.target.value)} - className="input flex-1" - placeholder="e.g., Brown v. Board of Education, 347 U.S. 483 (1954)" - required - /> - -
-

- Enter the full citation and click Parse to auto-fill fields -

-
- - {/* Title */} -
- - setTitle(e.target.value)} - className="input" - placeholder={type === 'case' ? 'e.g., Brown v. Board of Education' : 'e.g., Civil Rights Act'} - required - /> -
- - {/* Case-specific fields */} - {type === 'case' && ( - <> -
-
- - setVolume(e.target.value)} - className="input" - placeholder="347" - /> -
-
- - -
-
- - setPage(e.target.value)} - className="input" - placeholder="483" - /> -
-
- - setPinpoint(e.target.value)} - className="input" - placeholder="495" - /> -
-
-
-
- - -
-
- - setYear(e.target.value ? parseInt(e.target.value, 10) : '')} - className="input" - placeholder="1954" - min="1700" - max={new Date().getFullYear()} - /> -
-
- - )} - - {/* Statute/Regulation fields */} - {(type === 'statute' || type === 'regulation') && ( - <> -
-
- - setCodeTitle(e.target.value)} - className="input" - placeholder="e.g., 42 U.S.C." - /> -
-
- - setSection(e.target.value)} - className="input" - placeholder="e.g., 1983" - /> -
-
- - setSubdivision(e.target.value)} - className="input" - placeholder="e.g., a, b(1)" - /> -
-
-
-
- - -
-
- - setYear(e.target.value ? parseInt(e.target.value, 10) : '')} - className="input" - min="1700" - max={new Date().getFullYear()} - /> -
-
- - )} - - {/* Additional fields */} -
-
- - setShortForm(e.target.value)} - className="input" - placeholder="e.g., Brown, 347 U.S. at 495" - /> -
-
- - -
-
- -
- - setParenthetical(e.target.value)} - className="input" - placeholder="e.g., holding that separate but equal is unconstitutional" - /> -
- -
- - setUrl(e.target.value)} - className="input" - placeholder="https://..." - /> -
- - {/* Tags */} -
- -
- setTagInput(e.target.value)} - onKeyDown={(e) => e.key === 'Enter' && (e.preventDefault(), handleAddTag())} - className="input flex-1" - placeholder="Add a tag..." - /> - -
- {tags.length > 0 && ( -
- {tags.map((tag) => ( - - {tag} - - - ))} -
- )} -
- - {/* Notes & Verified */} -
-
- -