71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { fileHwpPreviewUrl } from '../../lib/apiClient';
|
|
import { FilePreviewFallback } from './FilePreviewFallback';
|
|
|
|
interface HwpPreviewProps {
|
|
fileId: string;
|
|
fileName: string;
|
|
}
|
|
|
|
export function HwpPreview({ fileId, fileName }: HwpPreviewProps) {
|
|
const [html, setHtml] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
setLoading(true);
|
|
setError(null);
|
|
setHtml(null);
|
|
|
|
fetch(fileHwpPreviewUrl(fileId))
|
|
.then(async (res) => {
|
|
if (!res.ok) {
|
|
const body = (await res.json().catch(() => null)) as { message?: string } | null;
|
|
throw new Error(body?.message ?? '한글 미리보기를 불러올 수 없습니다.');
|
|
}
|
|
return res.json() as Promise<{ html: string }>;
|
|
})
|
|
.then((data) => {
|
|
if (!cancelled) {
|
|
setHtml(data.html);
|
|
setLoading(false);
|
|
}
|
|
})
|
|
.catch((e) => {
|
|
if (!cancelled) {
|
|
setError(e instanceof Error ? e.message : '한글 미리보기 실패');
|
|
setLoading(false);
|
|
}
|
|
});
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [fileId]);
|
|
|
|
if (error) {
|
|
return (
|
|
<FilePreviewFallback
|
|
fileId={fileId}
|
|
fileName={fileName}
|
|
error={error}
|
|
message="한글 미리보기 변환에 실패했습니다. 다운로드 후 한/글에서 확인해 주세요."
|
|
/>
|
|
);
|
|
}
|
|
|
|
if (loading || !html) {
|
|
return <FilePreviewFallback fileId={fileId} fileName={fileName} loading />;
|
|
}
|
|
|
|
return (
|
|
<div className="h-full w-full min-h-0 overflow-auto bg-white">
|
|
<div
|
|
className="hwp-preview mx-auto max-w-4xl p-6 text-[15px] leading-relaxed text-slate-800 [&_img]:max-w-full [&_table]:my-3 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-slate-200 [&_td]:px-2 [&_td]:py-1 [&_th]:border [&_th]:border-slate-300 [&_th]:bg-slate-50 [&_th]:px-2 [&_th]:py-1"
|
|
dangerouslySetInnerHTML={{ __html: html }}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|