| import { useState, type ReactNode } from "react"; |
| import { api, getErrorMessage } from "../api"; |
|
|
| interface Props { |
| docId: string; |
| children: ReactNode; |
| } |
|
|
| export default function DocumentViewer({ docId, children }: Props) { |
| const [expanded, setExpanded] = useState(false); |
| const [fullText, setFullText] = useState<string | null>(null); |
| const [loading, setLoading] = useState(false); |
| const [error, setError] = useState(""); |
|
|
| async function handleClick() { |
| if (expanded) { |
| setExpanded(false); |
| return; |
| } |
| if (fullText !== null) { |
| setExpanded(true); |
| return; |
| } |
| setLoading(true); setError(""); |
| try { |
| const res = await api.getDocument(docId); |
| setFullText(res.text); |
| setExpanded(true); |
| } catch (err) { |
| setError(getErrorMessage(err)); |
| } finally { |
| setLoading(false); |
| } |
| } |
|
|
| return ( |
| <div> |
| <div onClick={handleClick}> |
| {children} |
| </div> |
| {loading && ( |
| <div style={{ padding: "8px 12px", color: "var(--text-dim)", fontSize: "0.85rem" }}> |
| Loading document... |
| </div> |
| )} |
| {error && ( |
| <div style={{ padding: "8px 12px", color: "var(--danger)", fontSize: "0.85rem" }}> |
| {error} |
| </div> |
| )} |
| {expanded && fullText !== null && ( |
| <div style={{ |
| background: "var(--bg-elevated, #0d1117)", |
| border: "1px solid var(--border)", |
| borderTop: "none", |
| borderRadius: "0 0 var(--radius) var(--radius)", |
| padding: "12px 16px", |
| marginTop: -4, |
| marginBottom: 8, |
| maxHeight: 400, |
| overflowY: "auto", |
| fontSize: "0.82rem", |
| lineHeight: 1.7, |
| whiteSpace: "pre-wrap", |
| wordBreak: "break-word", |
| color: "var(--text)", |
| }}> |
| <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 8 }}> |
| <span style={{ fontWeight: 600 }}>{docId}</span> |
| <button |
| onClick={(e) => { e.stopPropagation(); setExpanded(false); }} |
| style={{ |
| background: "none", border: "none", color: "var(--text-dim)", |
| cursor: "pointer", fontSize: "0.8rem", |
| }}> |
| Close |
| </button> |
| </div> |
| {fullText} |
| </div> |
| )} |
| </div> |
| ); |
| } |
|
|