128 lines
4.7 KiB
TypeScript
128 lines
4.7 KiB
TypeScript
export type EditorialArticle = {
|
|
id: number;
|
|
title: string;
|
|
description: string | null;
|
|
author: string | null;
|
|
body: string;
|
|
html?: string | null;
|
|
image_url: string | null;
|
|
original_url: string;
|
|
source_url?: string | null;
|
|
published_at?: string | null;
|
|
modified_at?: string | null;
|
|
legacy_id?: number | null;
|
|
image_source_url?: string | null;
|
|
image_notice?: string | null;
|
|
image_references?: string[];
|
|
metadata_version?: number;
|
|
private_preview?: boolean;
|
|
};
|
|
export default function EditorialReading({
|
|
article,
|
|
}: {
|
|
article: EditorialArticle;
|
|
}) {
|
|
return (
|
|
<div className="space-y-5">
|
|
{article.private_preview && (
|
|
<p
|
|
role="status"
|
|
className="rounded border border-amber-500 bg-amber-50 p-3 text-slate-900"
|
|
>
|
|
Prévia privada — não publica o artigo nem altera os direitos
|
|
do original.
|
|
</p>
|
|
)}
|
|
<h1 className="text-3xl font-bold">{article.title}</h1>
|
|
{article.description && <p>{article.description}</p>}
|
|
{article.author && <p>Autor / entidade: {article.author}</p>}
|
|
{article.legacy_id && (
|
|
<p>
|
|
Arquivo do portal antigo · artigo {article.legacy_id}.
|
|
Conteúdo editorial preservado; não corresponde por si a
|
|
oportunidade concreta ou regra executável.
|
|
</p>
|
|
)}
|
|
{(article.published_at || article.modified_at) && (
|
|
<p>
|
|
Origem: publicado em{' '}
|
|
{article.published_at ?? 'data não indicada'} · modificado
|
|
em {article.modified_at ?? 'data não indicada'}. A edição no
|
|
portal conserva estas datas de origem.
|
|
</p>
|
|
)}
|
|
{article.image_url && (
|
|
<img
|
|
className="max-h-96 w-full object-contain"
|
|
src={article.image_url}
|
|
alt={`Imagem do artigo ${article.title}`}
|
|
/>
|
|
)}
|
|
{article.image_notice && (
|
|
<p role="note" className="rounded border p-3">
|
|
{article.image_notice}
|
|
</p>
|
|
)}
|
|
{article.html ? (
|
|
<article
|
|
className="prose dark:prose-invert max-w-none overflow-x-auto"
|
|
dangerouslySetInnerHTML={{ __html: article.html }}
|
|
/>
|
|
) : (
|
|
<article className="space-y-5">
|
|
{article.body.split(/\n\s*\n/).map((p, i) => (
|
|
<p className="whitespace-pre-wrap" key={i}>
|
|
{p}
|
|
</p>
|
|
))}
|
|
</article>
|
|
)}
|
|
{!!article.image_references?.length && (
|
|
<section aria-label="Imagens referenciadas no corpo original">
|
|
<h2>Imagens referenciadas no corpo original</h2>
|
|
<p>
|
|
Referências preservadas; não confirmam um ficheiro
|
|
disponível na biblioteca.
|
|
</p>
|
|
<ul>
|
|
{article.image_references.map((url, i) => (
|
|
<li key={url}>
|
|
<a
|
|
className="underline"
|
|
href={url}
|
|
rel="noopener noreferrer"
|
|
>
|
|
Referência da imagem {i + 1}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</section>
|
|
)}
|
|
<nav aria-label="Origem do artigo" className="flex flex-wrap gap-4">
|
|
{article.source_url && (
|
|
<a
|
|
className="underline"
|
|
href={article.source_url}
|
|
rel="noopener noreferrer"
|
|
>
|
|
Consultar página de origem
|
|
</a>
|
|
)}
|
|
{article.image_source_url && (
|
|
<a
|
|
className="underline"
|
|
href={article.image_source_url}
|
|
rel="noopener noreferrer"
|
|
>
|
|
Referência da imagem de origem
|
|
</a>
|
|
)}
|
|
<a href={article.original_url} className="underline">
|
|
Consultar documento original
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
);
|
|
}
|