Files
sciagent/frontend_publisher/src/features/papers/presentation/PaperPdfDocument.tsx
T
Thinh Lam 688fac73e9
CI/CD / backend (push) Failing after 2m8s
CI/CD / frontend (push) Failing after 1m40s
CI/CD / deploy (push) Has been skipped
sciagent code + Gitea Actions CI/CD
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 09:38:30 +07:00

89 lines
3.3 KiB
TypeScript

import { Document, Font, Page, StyleSheet, Text, View } from '@react-pdf/renderer';
import type { Paper } from '../domain/paperModel';
/**
* Register a Unicode TTF so Vietnamese diacritics render (react-pdf's built-in Helvetica does not
* cover them). The Roboto TTFs are SELF-HOSTED under public/fonts so PDF export also works in
* air-gapped production deploys (no CDN fetch at render time). If glyphs ever render as blanks,
* replace the files with a Noto-with-Vietnamese TTF — registration is the only place it is configured.
*/
Font.register({
family: 'Roboto',
fonts: [
{ src: '/fonts/roboto-regular.ttf' },
{ src: '/fonts/roboto-bold.ttf', fontWeight: 'bold' },
],
});
const styles = StyleSheet.create({
page: { fontFamily: 'Roboto', fontSize: 11, lineHeight: 1.5, padding: 48, color: '#1f2937' },
title: { fontSize: 18, fontWeight: 'bold', marginBottom: 4 },
titleEn: { fontSize: 12, color: '#6b7280', marginBottom: 12 },
meta: { fontSize: 9, color: '#6b7280', marginBottom: 16 },
h2: { fontSize: 12, fontWeight: 'bold', marginTop: 14, marginBottom: 4 },
body: { textAlign: 'justify' },
source: { marginBottom: 3 },
badge: { fontSize: 9, color: '#047857', marginTop: 16 },
});
export function PaperPdfDocument({ paper, projectTitle }: { paper: Paper; projectTitle?: string }) {
return (
<Document title={paper.title || 'Bài báo'} author={paper.approval?.approvedByName}>
<Page size="A4" style={styles.page}>
<Text style={styles.title}>{paper.title || '(Chưa đặt tiêu đề)'}</Text>
{paper.titleEn ? <Text style={styles.titleEn}>{paper.titleEn}</Text> : null}
<Text style={styles.meta}>
{projectTitle ? `Đề tài: ${projectTitle}` : ''}
{paper.publishedAt
? ` · Xuất bản: ${new Date(paper.publishedAt).toLocaleDateString('vi-VN')}`
: ' · Bản thảo'}
{paper.approval ? ` · Phê duyệt: ${paper.approval.approvedByName}` : ''}
</Text>
{paper.abstractVi ? (
<View>
<Text style={styles.h2}>Tóm tắt</Text>
<Text style={styles.body}>{paper.abstractVi}</Text>
</View>
) : null}
{paper.abstractEn ? (
<View>
<Text style={styles.h2}>Abstract</Text>
<Text style={styles.body}>{paper.abstractEn}</Text>
</View>
) : null}
{paper.body ? (
<View>
<Text style={styles.h2}>Nội dung</Text>
<Text style={styles.body}>{paper.body}</Text>
</View>
) : null}
{paper.sources.length > 0 ? (
<View>
<Text style={styles.h2}>Tài liệu tham khảo</Text>
{paper.sources.map((s, i) => (
<Text key={s.id} style={styles.source}>
[{i + 1}] {s.title}
{s.authors ? ` — ${s.authors}` : ''}
{s.doiOrUrl ? ` (${s.doiOrUrl})` : ''}
{s.verifiedReal ? ' ✓' : ''}
</Text>
))}
</View>
) : null}
{paper.status === 'published' && paper.approval ? (
<Text style={styles.badge}>
Đã phê duyệt &amp; xuất bản bởi {paper.approval.approvedByName} {' '}
{new Date(paper.approval.approvedAt).toLocaleString('vi-VN')}
</Text>
) : null}
</Page>
</Document>
);
}