6 Commits

3 changed files with 45 additions and 18 deletions

View File

@@ -5,7 +5,7 @@ import CarteOWrapper from '../vue/CarteOWrapper.vue';
import ChatbotV2 from '../vue/ChatbotV2.vue';
import EmbedDynamique from '../vue/EmbedDynamique.vue';
---
<div id="col-centre-grid" class="h-full grid grid-rows-2 gap-2 p-2">
<div id="col-centre-grid" class="h-full grid gap-2 p-2" style="grid-template-rows: 1fr 2fr;">
<!-- HAUT 50% : tabs Carte O / Chatbot -->
<section id="col-centre-haut" class="border border-neutral-200 rounded flex flex-col overflow-hidden bg-white" style="min-height: 0;">
<nav role="tablist" aria-label="Vues centrales" class="flex border-b border-neutral-200 px-1 pt-1">
@@ -97,8 +97,8 @@ import EmbedDynamique from '../vue/EmbedDynamique.vue';
haut.style.minHeight = '0';
poignee?.setAttribute('aria-label', 'Deployer la Carte O');
} else {
grid.classList.add('grid-rows-2');
grid.style.gridTemplateRows = '';
grid.classList.remove('grid-rows-2');
grid.style.gridTemplateRows = '1fr 2fr';
haut.style.overflow = '';
haut.style.minHeight = '';
poignee?.setAttribute('aria-label', 'Replier la Carte O');
@@ -141,7 +141,7 @@ import EmbedDynamique from '../vue/EmbedDynamique.vue';
const parts = rows.split(' ');
return parseFloat(parts[0]) || 50;
}
return 50;
return 33.33;
};
dragHandle.addEventListener('mousedown', (e: MouseEvent) => {
@@ -182,10 +182,10 @@ import EmbedDynamique from '../vue/EmbedDynamique.vue';
gridEl.classList.remove('grid-rows-2');
}
// Double-click sur drag handle = reset 50/50
// Double-click sur drag handle = reset default 1/3 + 2/3
dragHandle.addEventListener('dblclick', () => {
gridEl.style.gridTemplateRows = '';
gridEl.classList.add('grid-rows-2');
gridEl.style.gridTemplateRows = '1fr 2fr';
gridEl.classList.remove('grid-rows-2');
sessionStorage.removeItem('tf-centre-rows');
});
}

View File

@@ -5,19 +5,19 @@ const categories = [
{
id: 'politique',
label: 'Politique',
color: '#1d4ed8',
color: '#B5443A',
hashtags: ['#politique', '#aep-politique'],
plateformes: [
{ id: 'instagram', label: '@aep.politique', url: 'https://www.instagram.com/aep.politique/' },
{ id: 'instagram', label: 'Court', url: 'https://www.instagram.com/aep.politique/' },
{ id: 'castopod', label: 'Podcast', url: 'https://podcast.trans-former.fr' },
{ id: 'substack', label: 'Substack', url: 'https://julesneny.substack.com' },
{ id: 'substack', label: 'Article', url: 'https://julesneny.substack.com' },
],
hasSelector: true,
},
{
id: 'art',
label: 'Art',
color: '#dc2626',
color: '#5B6B3A',
hashtags: ['#peinture', '#art'],
plateformes: [
{ id: 'instagram', label: '@julesneny', url: 'https://www.instagram.com/julesneny/' },
@@ -27,7 +27,7 @@ const categories = [
{
id: 'outils',
label: 'Outils',
color: '#16a34a',
color: '#475569',
hashtags: ['#stack', '#building-public'],
plateformes: [
{ id: 'gitea', label: 'Gitea', url: 'https://git.trans-former.fr/jules' },
@@ -68,7 +68,7 @@ const categories = [
type="button"
data-platform-id={p.id}
class="platform-pill"
style="font-family:'Courier New',Courier,monospace;font-size:12px;padding:2px 8px;border-radius:12px;cursor:pointer;border:1px solid #1d4ed8;background:transparent;color:#1d4ed8;"
style="font-family:'Courier New',Courier,monospace;font-size:12px;padding:2px 8px;border-radius:12px;cursor:pointer;border:1px solid #B5443A;background:transparent;color:#B5443A;"
>
{p.label}
</button>
@@ -219,11 +219,11 @@ const categories = [
pills.forEach((pill) => {
const pid = pill.dataset.platformId;
if (!active || pid === active) {
pill.style.background = '#1d4ed8';
pill.style.background = '#B5443A';
pill.style.color = '#fff';
} else {
pill.style.background = 'transparent';
pill.style.color = '#1d4ed8';
pill.style.color = '#B5443A';
}
});
};

View File

@@ -14,8 +14,27 @@ interface JournalItem {
const selectedItem = ref<JournalItem | null>(null)
const iframeRef = ref<HTMLIFrameElement | null>(null)
const wrapperRef = ref<HTMLDivElement | null>(null)
const skeletonHidden = ref(false)
// Force rendu desktop de l'iframe AEP : viewport simulée 1440px + scale dynamique
const VIEWPORT_W = 1440
const iframeScale = ref(0.42)
let resizeObs: ResizeObserver | null = null
const updateScale = () => {
if (!wrapperRef.value) return
const w = wrapperRef.value.clientWidth
if (w > 0) iframeScale.value = w / VIEWPORT_W
}
const iframeStyle = computed(() => ({
width: VIEWPORT_W + 'px',
height: (100 / iframeScale.value) + '%',
transform: `scale(${iframeScale.value})`,
transformOrigin: '0 0',
}))
const onJournalItemClick = (e: Event) => {
const ce = e as CustomEvent
if (ce.detail?.item) selectedItem.value = ce.detail.item
@@ -23,9 +42,16 @@ const onJournalItemClick = (e: Event) => {
onMounted(() => {
window.addEventListener('journal-item-click', onJournalItemClick as EventListener)
if (wrapperRef.value && typeof ResizeObserver !== 'undefined') {
updateScale()
resizeObs = new ResizeObserver(updateScale)
resizeObs.observe(wrapperRef.value)
}
})
onUnmounted(() => {
window.removeEventListener('journal-item-click', onJournalItemClick as EventListener)
resizeObs?.disconnect()
resizeObs = null
})
const reset = () => {
@@ -89,18 +115,19 @@ const formatDate = (iso: string) => {
<!-- DEFAULT : iframe AEP (aucun item selectionne) -->
<div v-if="!selectedItem" class="h-full">
<div class="relative h-full bg-neutral-100">
<div ref="wrapperRef" class="relative h-full bg-neutral-100 overflow-hidden">
<div
v-if="!skeletonHidden"
id="embed-skeleton"
class="absolute inset-0 flex items-center justify-center bg-neutral-50 animate-pulse"
class="absolute inset-0 flex items-center justify-center bg-neutral-50 animate-pulse z-10"
>
<span class="text-neutral-400 text-sm">Chargement de la carte AEP...</span>
</div>
<iframe
src="https://aep.trans-former.fr/agences"
title="Carte AEP"
class="w-full h-full border-0 opacity-0 transition-opacity duration-500"
class="absolute top-0 left-0 border-0 opacity-0 transition-opacity duration-500"
:style="iframeStyle"
sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
@load="onIframeLoad"
ref="iframeRef"