feat(mapa): panell de consum també a / + capçalera + altura
- Extract ConsumoDistribucion.astro (panel abans inline a mapa.astro).
Aquest panell (105.632 vacants, 13.466 testimonial, etc.) ara apareix
TANT a /mapa com a /. A /, va entre la taula per illa i les story cards.
- mapa.astro ja no té markup propi: <Mapa /> + <ConsumoDistribucion />.
- Capçalera del mapa més petita (py-8 → py-2/3, text-2xl/3xl → text-lg/xl,
lead més curt) perquè el mapa sigui la peça dominant.
- Alçada del mapa adaptable:
height: calc(100vh - 60px); min-height: 480px;
↓
height: clamp(420px, 62vh, 640px);
Així el mapa s'adapta a la finestra sense cobrir la pantalla en monitors
grans, i no obliga a fer scroll horitzontal en mòbils.
- Llegenda (bottom-right) i panell de capes (top-left) ara amb
max-h-[calc(100%-1.5rem)] overflow-y-auto — el desbordament es controla
dins la caixa en lloc de quedar tallat per la vora del mapa.
astro-check: 0 errors nous.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
---
|
||||
import { t, tArray, type Lang } from "../i18n";
|
||||
|
||||
interface Props {
|
||||
lang: Lang;
|
||||
}
|
||||
const { lang } = Astro.props;
|
||||
const fmt = new Intl.NumberFormat(lang === "ca" ? "ca-ES" : "es-ES");
|
||||
const buckets = tArray<{
|
||||
label: string;
|
||||
viviendas: number;
|
||||
pct: number;
|
||||
interpretacion: string;
|
||||
}>(lang, "map.consumo_distribucion_buckets");
|
||||
const totalViviendas = buckets.reduce((s, b) => s + b.viviendas, 0);
|
||||
const maxPct = buckets.length ? Math.max(...buckets.map((b) => b.pct)) : 1;
|
||||
---
|
||||
|
||||
<section class="max-w-6xl mx-auto px-4 py-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-2">
|
||||
{t(lang, "map.consumo_distribucion_title")}
|
||||
</h2>
|
||||
<p class="text-stone-600 mb-6 max-w-3xl" set:html={t(lang, "map.consumo_distribucion_intro")} />
|
||||
|
||||
<div class="bg-white border border-stone-200 rounded-lg p-6 mb-4">
|
||||
<div class="flex items-baseline gap-3 mb-6">
|
||||
<span class="text-sm text-stone-500">
|
||||
{t(lang, "map.consumo_distribucion_total_label")}:
|
||||
</span>
|
||||
<span class="text-3xl font-bold text-stone-900 tabular-nums">
|
||||
{fmt.format(totalViviendas)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ul class="space-y-4">
|
||||
{buckets.map((b) => (
|
||||
<li>
|
||||
<div class="flex items-baseline justify-between mb-1 gap-3 flex-wrap">
|
||||
<span class="text-sm font-medium text-stone-800">{b.label}</span>
|
||||
<span class="text-sm text-stone-600 tabular-nums">
|
||||
<strong class="text-stone-900">{fmt.format(b.viviendas)}</strong>
|
||||
<span class="text-stone-400"> · </span>
|
||||
{b.pct.toFixed(1)}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="h-7 bg-stone-100 rounded relative overflow-hidden">
|
||||
<div
|
||||
class="absolute inset-y-0 left-0 bg-orange-600"
|
||||
style={`width: ${(b.pct / maxPct) * 100}%`}
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-stone-600 mt-1" set:html={b.interpretacion} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="text-xs text-stone-500 italic" set:html={t(lang, "map.consumo_distribucion_footer")} />
|
||||
</section>
|
||||
@@ -22,18 +22,18 @@ const popupTitleTmpl = t(lang, "map.popup_title");
|
||||
---
|
||||
|
||||
<section class="border-b border-stone-200 bg-white">
|
||||
<div class="max-w-6xl mx-auto px-4 py-8">
|
||||
<h1 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-2">
|
||||
<div class="max-w-6xl mx-auto px-4 py-2 sm:py-3">
|
||||
<h1 class="text-lg sm:text-xl font-bold text-stone-900 leading-tight mb-0.5">
|
||||
{t(lang, "map.title")}
|
||||
</h1>
|
||||
<p class="text-stone-600">{t(lang, "map.lead")}</p>
|
||||
<p class="text-xs sm:text-sm text-stone-600 leading-snug">{t(lang, "map.lead")}</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div
|
||||
id="map-shell"
|
||||
class="relative w-full"
|
||||
style="height: calc(100vh - 60px); min-height: 480px;"
|
||||
style="height: clamp(420px, 62vh, 640px);"
|
||||
data-lang={lang}
|
||||
data-popup-title-tmpl={popupTitleTmpl}
|
||||
>
|
||||
@@ -47,7 +47,7 @@ const popupTitleTmpl = t(lang, "map.popup_title");
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="absolute top-3 left-3 z-20 bg-white/95 backdrop-blur border border-stone-200 rounded-lg shadow-sm p-3 w-64 max-w-[calc(100vw-1.5rem)]"
|
||||
class="absolute top-3 left-3 z-20 bg-white/95 backdrop-blur border border-stone-200 rounded-lg shadow-sm p-3 w-64 max-w-[calc(100vw-1.5rem)] max-h-[calc(100%-1.5rem)] overflow-y-auto"
|
||||
>
|
||||
<div class="mb-2">
|
||||
<p class="text-xs font-medium text-stone-700 mb-2">
|
||||
@@ -100,7 +100,7 @@ const popupTitleTmpl = t(lang, "map.popup_title");
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="absolute bottom-3 right-3 z-20 bg-white/95 backdrop-blur border border-stone-200 rounded-lg shadow-sm p-3 max-w-xs text-xs"
|
||||
class="absolute bottom-3 right-3 z-20 bg-white/95 backdrop-blur border border-stone-200 rounded-lg shadow-sm p-3 max-w-xs text-xs max-h-[calc(100%-1.5rem)] overflow-y-auto"
|
||||
>
|
||||
<p class="font-medium text-stone-800 mb-2">
|
||||
{t(lang, "map.legend_title")}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
export const prerender = false;
|
||||
import Base from "../layouts/Base.astro";
|
||||
import CifraImpacto from "../components/CifraImpacto.astro";
|
||||
import ConsumoDistribucion from "../components/ConsumoDistribucion.astro";
|
||||
import { getDataset, totals } from "../data/dataset";
|
||||
import { getLangFromAstroCookies, t, type Lang } from "../i18n";
|
||||
|
||||
@@ -128,6 +129,8 @@ const fmtPct = (x: number) => `${(x * 100).toFixed(0)}%`;
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ConsumoDistribucion lang={lang} />
|
||||
|
||||
<section class="max-w-6xl mx-auto px-4 py-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-6">
|
||||
{t(lang, "home.section_story_title")}
|
||||
|
||||
@@ -2,62 +2,13 @@
|
||||
export const prerender = false;
|
||||
import Base from "../layouts/Base.astro";
|
||||
import Mapa from "../components/Mapa.astro";
|
||||
import { getLangFromAstroCookies, t, tArray, type Lang } from "../i18n";
|
||||
import ConsumoDistribucion from "../components/ConsumoDistribucion.astro";
|
||||
import { getLangFromAstroCookies, type Lang } from "../i18n";
|
||||
|
||||
const lang: Lang = getLangFromAstroCookies(Astro.cookies);
|
||||
const fmt = new Intl.NumberFormat(lang === "ca" ? "ca-ES" : "es-ES");
|
||||
const buckets = tArray<{
|
||||
label: string;
|
||||
viviendas: number;
|
||||
pct: number;
|
||||
interpretacion: string;
|
||||
}>(lang, "map.consumo_distribucion_buckets");
|
||||
const totalViviendas = buckets.reduce((s, b) => s + b.viviendas, 0);
|
||||
const maxPct = buckets.length ? Math.max(...buckets.map((b) => b.pct)) : 1;
|
||||
---
|
||||
|
||||
<Base lang={lang} active="map" title={undefined} description={undefined}>
|
||||
<Mapa />
|
||||
|
||||
<section class="max-w-6xl mx-auto px-4 py-12">
|
||||
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-2">
|
||||
{t(lang, "map.consumo_distribucion_title")}
|
||||
</h2>
|
||||
<p class="text-stone-600 mb-6 max-w-3xl" set:html={t(lang, "map.consumo_distribucion_intro")} />
|
||||
|
||||
<div class="bg-white border border-stone-200 rounded-lg p-6 mb-4">
|
||||
<div class="flex items-baseline gap-3 mb-6">
|
||||
<span class="text-sm text-stone-500">
|
||||
{t(lang, "map.consumo_distribucion_total_label")}:
|
||||
</span>
|
||||
<span class="text-3xl font-bold text-stone-900 tabular-nums">
|
||||
{fmt.format(totalViviendas)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ul class="space-y-4">
|
||||
{buckets.map((b) => (
|
||||
<li>
|
||||
<div class="flex items-baseline justify-between mb-1 gap-3 flex-wrap">
|
||||
<span class="text-sm font-medium text-stone-800">{b.label}</span>
|
||||
<span class="text-sm text-stone-600 tabular-nums">
|
||||
<strong class="text-stone-900">{fmt.format(b.viviendas)}</strong>
|
||||
<span class="text-stone-400"> · </span>
|
||||
{b.pct.toFixed(1)}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="h-7 bg-stone-100 rounded relative overflow-hidden">
|
||||
<div
|
||||
class="absolute inset-y-0 left-0 bg-orange-600"
|
||||
style={`width: ${(b.pct / maxPct) * 100}%`}
|
||||
></div>
|
||||
</div>
|
||||
<p class="text-xs text-stone-600 mt-1" set:html={b.interpretacion} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="text-xs text-stone-500 italic" set:html={t(lang, "map.consumo_distribucion_footer")} />
|
||||
</section>
|
||||
<ConsumoDistribucion lang={lang} />
|
||||
</Base>
|
||||
|
||||
Reference in New Issue
Block a user