Files
JWE/app/src/lib/components/WikiFiche.svelte
T

274 lines
6.0 KiB
Svelte
Raw Normal View History

<script lang="ts">
import { onMount } from 'svelte';
import { t } from '$lib/i18n/store.svelte';
import type { WikiSummary } from '$lib/types';
interface Props {
nom: string;
wikidataId: string | null;
tonPositif?: string;
tonNeutre?: string;
}
let { nom, wikidataId, tonPositif, tonNeutre }: Props = $props();
// undefined = chargement, null = pas de fiche, WikiSummary = Cas A
let wiki = $state<WikiSummary | null | undefined>(undefined);
// Cas intermédiaire (audit A3) : QID présent, fiche Wikidata existante,
// mais pas d'article Wikipédia en français (404 {reason:'no-frwiki'}).
let sansFrwiki = $state(false);
onMount(() => {
if (!wikidataId) {
wiki = null;
return;
}
let annule = false;
void (async () => {
try {
const res = await fetch(`/api/wiki/${wikidataId}`);
if (annule) return;
if (res.ok) {
wiki = (await res.json()) as WikiSummary;
} else {
if (res.status === 404) {
try {
const corps = (await res.json()) as { reason?: string };
sansFrwiki = corps.reason === 'no-frwiki';
} catch {
sansFrwiki = false;
}
}
wiki = null;
}
} catch {
if (!annule) wiki = null;
}
})();
return () => {
annule = true;
};
});
const lienContribution = $derived(
`https://fr.wikipedia.org/w/index.php?search=${encodeURIComponent(nom)}&title=Sp%C3%A9cial:Recherche`
);
const lienWikidata = $derived(`https://www.wikidata.org/wiki/${wikidataId}`);
</script>
{#if wiki === undefined}
<div class="panneau chargement">
<p>{t().explorer.chargerFiche}</p>
</div>
{:else if wiki}
<!-- Cas A : fiche Wikipédia existante -->
<article class="panneau cas-a">
<h2>
<a href={wiki.url} target="_blank" rel="noopener noreferrer">{wiki.title}</a>
</h2>
{#if tonPositif || tonNeutre}
<p class="ton">{tonPositif ?? tonNeutre}</p>
{/if}
{#if wiki.thumbnail}
<img src={wiki.thumbnail} alt="" loading="lazy" decoding="async" />
{/if}
<p class="extrait">{wiki.extract}</p>
<a class="lien-wiki" href={wiki.url} target="_blank" rel="noopener noreferrer">
{t().resultat.lireWiki}
</a>
</article>
{:else if sansFrwiki}
<!-- Variante Cas B : fiche Wikidata OK mais pas d'article FR — appel à traduire/créer -->
<article class="panneau cas-b">
<h2><span class="icone" aria-hidden="true"></span> {t().lacuneFr.titre}</h2>
<p class="texte">{t().lacuneFr.texte}</p>
<div class="ctas">
<a class="btn btn-cta" href={lienContribution} target="_blank" rel="noopener noreferrer">
{t().lacuneFr.cta}
</a>
<a class="lien-wikidata" href={lienWikidata} target="_blank" rel="noopener noreferrer">
{t().lacuneFr.ctaWikidata}
</a>
</div>
</article>
{:else}
<!-- Cas B : lacune documentaire — panneau volontairement distinct (Peak-End) -->
<article class="panneau cas-b">
<h2><span class="icone" aria-hidden="true"></span> {t().lacune.titre}</h2>
<p class="texte">{t().lacune.texte}</p>
<a class="btn btn-cta" href={lienContribution} target="_blank" rel="noopener noreferrer">
{t().lacune.cta}
</a>
<p class="guide">
{t().lacune.guide}
<a href="https://fr.wikipedia.org/wiki/Aide:Premiers_pas" target="_blank" rel="noopener noreferrer">
{t().lacune.guideLien}
</a>
</p>
</article>
{/if}
<style>
.panneau {
border-radius: var(--radius-md);
padding: 1.1rem 1.25rem;
box-shadow: var(--oki-ombre);
}
.chargement {
background: var(--noir-profond);
color: var(--muted);
text-align: center;
border: 1px solid var(--line);
}
/* Cas A : fiche existante — liseré vert OKI */
.cas-a {
background: var(--card-bg);
border: 1px solid var(--line);
border-left: 4px solid var(--vert-oki);
color: var(--blanc-creme);
}
.cas-a h2 {
margin: 0 0 0.3rem;
font-size: 1.25rem;
}
.cas-a h2 a {
color: var(--blanc-creme);
text-decoration: none;
}
.cas-a h2 a:hover {
color: var(--or-oki);
text-decoration: underline;
}
.cas-a .ton {
margin: 0 0 0.6rem;
font-weight: 600;
color: var(--vert-oki);
font-size: 0.9rem;
}
.cas-a img {
float: right;
width: 96px;
height: auto;
margin: 0 0 0.5rem 0.8rem;
border-radius: var(--radius-sm);
border: 1px solid var(--line);
}
.cas-a .extrait {
margin: 0 0 0.6rem;
line-height: 1.55;
color: var(--blanc-creme);
}
.lien-wiki {
color: var(--or-oki);
font-weight: 700;
text-decoration: none;
display: inline-block;
margin-top: 0.3rem;
}
.lien-wiki:hover {
text-decoration: underline;
}
/* Cas B : lacune documentaire — liseré or OKI, teinte distincte */
.cas-b {
background: var(--oki-lacune-fond);
border: 1.5px solid var(--or-oki);
border-left: 5px solid var(--or-oki);
color: var(--blanc-creme);
}
.cas-b h2 {
margin: 0 0 0.5rem;
font-size: 1.25rem;
color: var(--or-oki);
display: flex;
align-items: center;
gap: 0.5rem;
}
.cas-b .icone {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1.6rem;
height: 1.6rem;
border: 2px dashed var(--or-oki);
border-radius: 50%;
font-size: 1rem;
color: var(--or-oki);
}
.cas-b .texte {
margin: 0 0 0.9rem;
font-size: 0.98rem;
line-height: 1.55;
color: var(--blanc-creme);
}
.btn-cta {
background: var(--or-oki);
color: #0d0d0d;
font-weight: 700;
font-family: var(--font-display);
text-transform: uppercase;
letter-spacing: 0.03em;
padding: 0.65rem 1.1rem;
border-radius: var(--radius-sm);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 0.4rem;
}
:global(html.light-theme) .btn-cta {
color: #ffffff;
}
.btn-cta:hover {
background: var(--or-clair);
}
.ctas {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.9rem;
}
.lien-wikidata {
color: var(--or-oki);
font-weight: 650;
text-decoration: none;
}
.lien-wikidata:hover {
text-decoration: underline;
}
.guide {
margin: 0.8rem 0 0;
font-size: 0.88rem;
color: var(--muted);
}
.guide a {
color: var(--or-oki);
font-weight: 600;
text-decoration: none;
}
.guide a:hover {
text-decoration: underline;
}
</style>