feat(web): afegir pagina /premsa amb kit per a periodistes

This commit is contained in:
2026-07-14 13:44:31 +02:00
parent 5511265e16
commit 776ad064b0
4 changed files with 247 additions and 4 deletions
+10 -2
View File
@@ -4,7 +4,7 @@ import LanguageToggle from "./LanguageToggle.astro";
interface Props {
lang?: Lang;
active: "home" | "map" | "methodology" | "islands" | "data";
active: "home" | "map" | "methodology" | "islands" | "data" | "press";
}
const { lang: langProp, active } = Astro.props;
@@ -15,8 +15,9 @@ const isMap = path.startsWith("/mapa");
const isMetod = path.startsWith("/metodologia");
const isIslands = path.startsWith("/illes");
const isData = path.startsWith("/dades");
const isPress = path.startsWith("/premsa");
const navLink = (key: "home" | "map" | "methodology" | "islands" | "data") =>
const navLink = (key: "home" | "map" | "methodology" | "islands" | "data" | "press") =>
`text-sm font-medium px-3 py-1.5 rounded transition-colors ${
active === key
? "text-orange-700 bg-orange-50"
@@ -63,6 +64,13 @@ const navLink = (key: "home" | "map" | "methodology" | "islands" | "data") =>
>
{t(lang, "nav.data")}
</a>
<a
href="/premsa"
class={navLink("press")}
aria-current={isPress ? "page" : undefined}
>
{t(lang, "nav.press")}
</a>
<a
href="/metodologia"
class={navLink("methodology")}
+29 -1
View File
@@ -10,7 +10,8 @@
"map": "Mapa",
"methodology": "Metodologia",
"islands": "Per illa",
"data": "Dades"
"data": "Dades",
"press": "Premsa"
},
"lang_toggle": {
"label": "Idioma",
@@ -203,5 +204,32 @@
"repro_step2": "Descarrega les dades crues (Inside Airbnb, INE, HUT, IBESTAT) a data/raw/",
"repro_step3": "Executa els scripts en ordre 01 → 06",
"repo_link_label": "Repositori a GitHub"
},
"press": {
"title": "Premsa",
"lead": "Material per a periodistes i mitjans que vulguin cobrir el tema. Cifres citables, bio del projecte i contacte.",
"section_quoteable_title": "Cifres citables",
"section_quoteable_lead": "Una frase per dada. Totes amb font pública. Pots reproduir-les lliurement amb atribució a Cases Tancades.",
"section_bio_title": "Sobre el projecte",
"section_bio_body": "Cases Tancades és una iniciativa ciutadana independent que creua dades oficials d'habitatge semi-buit amb lloguer turístic a les Illes Balears. El projecte no té afiliació política ni financament públic o privat. El codi i les dades es publiquen sota llicència oberta per facilitar la verificació i la difusió.",
"section_contact_title": "Contacte",
"section_contact_body": "Per a peticions de mitjans, entrevistes o verificació de dades:",
"contact_email_label": "Correu electrònic",
"contact_response_label": "Temps de resposta",
"contact_response_value": "24-48 hores en dies laborables",
"section_assets_title": "Recursos gràfics",
"section_assets_lead": "Imatges i gràfics per acompanyar la teva peça. Llicència oberta.",
"asset_og_title": "Open Graph (xarxes)",
"asset_og_desc": "1200×630 px, PNG. La imatge que apareix quan es comparteix l'URL a Twitter/X, WhatsApp, LinkedIn, etc.",
"asset_tiles_title": "Tiles del mapa",
"asset_tiles_desc": "Vector tiles z0z13. Capa 'cases' amb seccions censals. Càrrega directa a MapLibre.",
"asset_data_title": "Dades",
"asset_data_desc": "Tots els datasets a /dades, formats oberts (CSV, Parquet, GeoJSON).",
"section_how_to_title": "Com citar",
"cite_1": "Segons l'anàlisi de Cases Tancades, amb dades d'Inside Airbnb (juny 2026)...",
"cite_2": "D'acord amb el registre HUT del Consell d'Eivissa...",
"cite_3": "Segons dades de l'INE (2024)...",
"section_disclaimer_title": "Avís legal",
"disclaimer_body": "Totes les dades provenen de fonts públiques oficials o obertes. No fem cap acusació individual. Si detectes una errada, escriu-nos i la corregirem."
}
}
+29 -1
View File
@@ -10,7 +10,8 @@
"map": "Mapa",
"methodology": "Metodología",
"islands": "Por isla",
"data": "Datos"
"data": "Datos",
"press": "Prensa"
},
"lang_toggle": {
"label": "Idioma",
@@ -203,5 +204,32 @@
"repro_step2": "Descarga los datos crudos (Inside Airbnb, INE, HUT, IBESTAT) a data/raw/",
"repro_step3": "Ejecuta los scripts en orden 01 → 06",
"repo_link_label": "Repositorio en GitHub"
},
"press": {
"title": "Prensa",
"lead": "Material para periodistas y medios que quieran cubrir el tema. Cifras citables, bio del proyecto y contacto.",
"section_quoteable_title": "Cifras citables",
"section_quoteable_lead": "Una frase por dato. Todas con fuente pública. Puedes reproducirlas libremente con atribución a Cases Tancades.",
"section_bio_title": "Sobre el proyecto",
"section_bio_body": "Cases Tancades es una iniciativa ciudadana independiente que cruza datos oficiales de vivienda semi-vacía con alquiler turístico en las Islas Baleares. El proyecto no tiene afiliación política ni financiación pública o privada. El código y los datos se publican bajo licencia abierta para facilitar la verificación y la difusión.",
"section_contact_title": "Contacto",
"section_contact_body": "Para peticiones de medios, entrevistas o verificación de datos:",
"contact_email_label": "Correo electrónico",
"contact_response_label": "Tiempo de respuesta",
"contact_response_value": "24-48 horas en días laborables",
"section_assets_title": "Recursos gráficos",
"section_assets_lead": "Imágenes y gráficos para acompañar tu pieza. Licencia abierta.",
"asset_og_title": "Open Graph (redes)",
"asset_og_desc": "1200×630 px, PNG. La imagen que aparece cuando se comparte la URL en Twitter/X, WhatsApp, LinkedIn, etc.",
"asset_tiles_title": "Tiles del mapa",
"asset_tiles_desc": "Vector tiles z0z13. Capa 'cases' con secciones censales. Carga directa en MapLibre.",
"asset_data_title": "Datos",
"asset_data_desc": "Todos los datasets en /dades, formatos abiertos (CSV, Parquet, GeoJSON).",
"section_how_to_title": "Cómo citar",
"cite_1": "Según el análisis de Cases Tancades, con datos de Inside Airbnb (junio 2026)...",
"cite_2": "De acuerdo con el registro HUT del Consell d'Eivissa...",
"cite_3": "Según datos del INE (2024)...",
"section_disclaimer_title": "Aviso legal",
"disclaimer_body": "Todos los datos provienen de fuentes públicas oficiales o abiertas. No hacemos ninguna acusación individual. Si detectas un error, escríbenos y lo corregiremos."
}
}
+179
View File
@@ -0,0 +1,179 @@
---
export const prerender = false;
import Base from "../layouts/Base.astro";
import { getLangFromAstroCookies, t, type Lang } from "../i18n";
const lang: Lang = getLangFromAstroCookies(Astro.cookies);
// TODO: substituir per correu real quan es decideixi. Format actual: premsa@<domini>
const CONTACT_EMAIL = "premsa@casestancades.cat";
interface Quoteable {
number: string;
text: string;
source: string;
}
const quoteables: Quoteable[] = [
{
number: "18.175",
text: "Listings actius a Airbnb a Mallorca i Menorca",
source: "Inside Airbnb, juny 2026",
},
{
number: "18.184",
text: "Places turístiques legals (HUT) a Eivissa",
source: "Registre HUT Consell d'Eivissa, 14 juliol 2026",
},
{
number: "40%",
text: "De les places HUT d'Eivissa es concentren a Sant Josep de sa Talaia",
source: "Elaboració pròpia a partir del registre HUT",
},
{
number: "16,2%",
text: "D'habitatges buits a Balears",
source: "INE, 2024",
},
{
number: "$258M",
text: "Ingressos estimats d'Airbnb els darrers 365 dies, Mallorca + Menorca",
source: "Inside Airbnb, juny 2026",
},
{
number: "95,4%",
text: "Dels listings actius són pisos sencers (Entire home/apt)",
source: "Inside Airbnb, juny 2026",
},
];
const description = t(lang, "press.lead");
---
<Base
lang={lang}
active="press"
title={t(lang, "press.title")}
description={description}
>
<section class="bg-gradient-to-b from-orange-50 to-stone-50 border-b border-stone-200">
<div class="max-w-4xl mx-auto px-4 py-12 sm:py-16 text-center">
<h1 class="text-3xl sm:text-4xl font-bold text-stone-900 mb-4">
{t(lang, "press.title")}
</h1>
<p class="text-base sm:text-lg text-stone-700 max-w-2xl mx-auto">
{description}
</p>
</div>
</section>
<section class="max-w-5xl mx-auto px-4 py-12">
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-2">
{t(lang, "press.section_quoteable_title")}
</h2>
<p class="text-stone-600 mb-6">{t(lang, "press.section_quoteable_lead")}</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{quoteables.map((q) => (
<blockquote class="border-l-4 border-orange-700 bg-white p-4 rounded-r">
<p class="text-3xl font-bold text-orange-700 tabular-nums mb-1">{q.number}</p>
<p class="text-stone-800 mb-2">{q.text}</p>
<cite class="text-xs text-stone-500 not-italic">— {q.source}</cite>
</blockquote>
))}
</div>
</section>
<section class="max-w-5xl mx-auto px-4 py-12 border-t border-stone-200">
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-4">
{t(lang, "press.section_bio_title")}
</h2>
<p class="text-stone-700 leading-relaxed text-lg">
{t(lang, "press.section_bio_body")}
</p>
</section>
<section class="max-w-5xl mx-auto px-4 py-12 border-t border-stone-200">
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-2">
{t(lang, "press.section_contact_title")}
</h2>
<p class="text-stone-700 mb-4">{t(lang, "press.section_contact_body")}</p>
<dl class="grid grid-cols-1 sm:grid-cols-2 gap-4 max-w-2xl">
<div class="bg-white border border-stone-200 rounded p-4">
<dt class="text-xs uppercase tracking-wide text-stone-500 mb-1">
{t(lang, "press.contact_email_label")}
</dt>
<dd>
<a
href={`mailto:${CONTACT_EMAIL}`}
class="text-orange-700 hover:text-orange-800 font-medium underline break-all"
>
{CONTACT_EMAIL}
</a>
</dd>
</div>
<div class="bg-white border border-stone-200 rounded p-4">
<dt class="text-xs uppercase tracking-wide text-stone-500 mb-1">
{t(lang, "press.contact_response_label")}
</dt>
<dd class="text-stone-800 font-medium">{t(lang, "press.contact_response_value")}</dd>
</div>
</dl>
</section>
<section class="max-w-5xl mx-auto px-4 py-12 border-t border-stone-200">
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-2">
{t(lang, "press.section_assets_title")}
</h2>
<p class="text-stone-600 mb-6">{t(lang, "press.section_assets_lead")}</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<a
href="/og-image.png"
download
class="block border border-stone-200 rounded-lg p-5 bg-white hover:border-orange-700 transition-colors"
>
<h3 class="font-bold text-orange-700 mb-1">{t(lang, "press.asset_og_title")}</h3>
<p class="text-sm text-stone-600 mb-3">{t(lang, "press.asset_og_desc")}</p>
<code class="text-xs bg-stone-100 px-1.5 py-0.5 rounded">/og-image.png</code>
</a>
<a
href="/tiles/dataset.pmtiles"
download
class="block border border-stone-200 rounded-lg p-5 bg-white hover:border-orange-700 transition-colors"
>
<h3 class="font-bold text-orange-700 mb-1">{t(lang, "press.asset_tiles_title")}</h3>
<p class="text-sm text-stone-600 mb-3">{t(lang, "press.asset_tiles_desc")}</p>
<code class="text-xs bg-stone-100 px-1.5 py-0.5 rounded">/tiles/dataset.pmtiles</code>
</a>
<a
href="/dades"
class="block border border-stone-200 rounded-lg p-5 bg-white hover:border-orange-700 transition-colors"
>
<h3 class="font-bold text-orange-700 mb-1">{t(lang, "press.asset_data_title")}</h3>
<p class="text-sm text-stone-600 mb-3">{t(lang, "press.asset_data_desc")}</p>
<code class="text-xs bg-stone-100 px-1.5 py-0.5 rounded">/dades</code>
</a>
</div>
</section>
<section class="max-w-5xl mx-auto px-4 py-12 border-t border-stone-200">
<h2 class="text-2xl sm:text-3xl font-bold text-stone-900 mb-4">
{t(lang, "press.section_how_to_title")}
</h2>
<ul class="space-y-2 text-stone-700 list-disc pl-5">
<li>{t(lang, "press.cite_1")}</li>
<li>{t(lang, "press.cite_2")}</li>
<li>{t(lang, "press.cite_3")}</li>
</ul>
</section>
<section class="max-w-5xl mx-auto px-4 py-12 border-t border-stone-200">
<div class="bg-stone-100 border-l-4 border-stone-400 p-4 rounded-r">
<h2 class="text-lg font-bold text-stone-900 mb-2">
{t(lang, "press.section_disclaimer_title")}
</h2>
<p class="text-stone-700 leading-relaxed">
{t(lang, "press.disclaimer_body")}
</p>
</div>
</section>
</Base>