feat(web): afegir pagina /premsa amb kit per a periodistes
This commit is contained in:
@@ -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
@@ -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 z0–z13. 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
@@ -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 z0–z13. 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."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user