stats: place × theme matrix (/stats/<place>/<theme>), sticky place/theme selector, generic metric engine with comparisons, 301s from the old section URLs
All checks were successful
Deploy production / deploy (push) Successful in 1m19s
All checks were successful
Deploy production / deploy (push) Successful in 1m19s
This commit is contained in:
731
src/lib/stats/views/CountryView.svelte
Normal file
731
src/lib/stats/views/CountryView.svelte
Normal file
@@ -0,0 +1,731 @@
|
||||
<script lang="ts">
|
||||
import type { CountryViewData } from '#lib/server/stats-views.js';
|
||||
import type { StatsCommon } from '#lib/stats/matrix.js';
|
||||
import { resolve } from '$app/paths';
|
||||
import StatChart from '#lib/stats/StatChart.svelte';
|
||||
import Kpi from '#lib/stats/Kpi.svelte';
|
||||
import {
|
||||
barRankOption,
|
||||
change,
|
||||
latest,
|
||||
lineOption,
|
||||
type Line,
|
||||
type StatPoint
|
||||
} from '#lib/stats/chart.js';
|
||||
import { CW_INDUSTRIES, CW_NIGHT_MARKETS, EU_TRADE } from '#lib/stats/curacao.js';
|
||||
import { compact, num, period } from '#lib/stats/format.js';
|
||||
import { COUNTRY } from '#lib/stats/regions.js';
|
||||
import { COUNTRY_COLOR, FLAG } from '#lib/stats/countries.js';
|
||||
import ArrowLeft from 'lucide-svelte/icons/arrow-left';
|
||||
import PlaceHeritage from '#lib/stats/PlaceHeritage.svelte';
|
||||
|
||||
let { data }: { data: CountryViewData & StatsCommon } = $props();
|
||||
const c = $derived(data.code);
|
||||
const s = $derived(data.series);
|
||||
const a = $derived(data.attributions);
|
||||
const name = $derived(COUNTRY[c] ?? c);
|
||||
const color = $derived(COUNTRY_COLOR[c] ?? '#3b82f6');
|
||||
const has = (id: string) => (s[`${id}:${c}`]?.points.length ?? 0) > 0;
|
||||
const pts = (id: string, code = c): StatPoint[] => s[`${id}:${code}`]?.points ?? [];
|
||||
const forecastFrom = (id: string) => s[`${id}:${c}`]?.forecastFrom;
|
||||
|
||||
/** IMF series split into outcome (solid) and WEO projection (dashed). */
|
||||
function imfLines(id: string, label: string, col: string): Line[] {
|
||||
const all = pts(id);
|
||||
const from = forecastFrom(id);
|
||||
if (!from) return [{ name: label, points: all, color: col }];
|
||||
const cut = `${from}-01-01`;
|
||||
const past = all.filter(([d]) => d < cut);
|
||||
const future = all.filter(([d]) => d >= cut);
|
||||
return [
|
||||
{ name: label, points: past, color: col },
|
||||
{
|
||||
name: `${label} (IMF forecast)`,
|
||||
points: past.length ? [past[past.length - 1], ...future] : future,
|
||||
color: col,
|
||||
dashed: true
|
||||
}
|
||||
];
|
||||
}
|
||||
/** IMF if it covers the country, else the World Bank fallback. */
|
||||
const pick = (imf: string, wb: string) => (has(imf) ? imf : wb);
|
||||
const lastOf = (id: string) => {
|
||||
const from = forecastFrom(id);
|
||||
const p = pts(id).filter(([d]) => !from || d < `${from}-01-01`);
|
||||
return latest(p);
|
||||
};
|
||||
|
||||
const kPop = $derived(lastOf('wb:SP.POP.TOTL'));
|
||||
const kGdp = $derived(lastOf('wb:NY.GDP.PCAP.PP.KD'));
|
||||
const kGrowth = $derived(lastOf(pick('imf:NGDP_RPCH', 'wb:NY.GDP.MKTP.KD.ZG')));
|
||||
const kInfl = $derived(lastOf(pick('imf:PCPIPCH', 'wb:FP.CPI.TOTL.ZG')));
|
||||
const kUnemp = $derived(lastOf(pick('imf:LUR', 'wb:SL.UEM.TOTL.ZS')));
|
||||
const kLife = $derived(lastOf('wb:SP.DYN.LE00.IN'));
|
||||
const kTour = $derived(lastOf('wb:ST.INT.ARVL'));
|
||||
const kDebt = $derived(lastOf(pick('imf:GGXWDG_NGDP', 'wb:GC.DOD.TOTL.GD.ZS')));
|
||||
const popDelta = $derived(change(pts('wb:SP.POP.TOTL'), 10)?.pct ?? null);
|
||||
const imfCovered = $derived(has('imf:NGDP_RPCH'));
|
||||
|
||||
// §8 Curaçao detail series: stored without the `:CUW` suffix.
|
||||
const cw = (id: string): StatPoint[] => s[id]?.points ?? [];
|
||||
const isCw = $derived(c === 'CUW' && cw('cw:cpi:index').length > 0);
|
||||
const cwGdpYear = $derived(latest(cw('cw:gdp:gdp'))?.[0]);
|
||||
const cwIndustries = $derived(
|
||||
Object.entries(CW_INDUSTRIES)
|
||||
.map(([k, label]) => ({
|
||||
label,
|
||||
value: cw(`cw:gdp:${k}`).find(([d]) => d === cwGdpYear)?.[1] ?? NaN
|
||||
}))
|
||||
.filter((r) => Number.isFinite(r.value))
|
||||
);
|
||||
const cwCpi = $derived(latest(cw('cw:cpi:yoy')));
|
||||
const cwPop = $derived(latest(cw('cw:pop:jan1')));
|
||||
const cwUnemp = $derived(latest(cw('cw:lfs:unemployment_rate_pct:total')));
|
||||
const cwGrowth = $derived(latest(cw('cw:gdp:real_growth_pct')));
|
||||
</script>
|
||||
|
||||
<section class="stats-intro">
|
||||
<a class="back" href={resolve('/stats/core/overview' as '/stats')}
|
||||
><ArrowLeft size={14} /> countries</a
|
||||
>
|
||||
<span class="stats-eyebrow">stats / countries / {c}</span>
|
||||
<h1><span class="flag">{FLAG[c]}</span> {name}</h1>
|
||||
<p>
|
||||
{#if c === 'CUW'}
|
||||
Curaçao has been a country within the Kingdom of the Netherlands since 2010, with about
|
||||
158,000 inhabitants. The IMF's World Economic Outlook doesn't cover it, so the headline
|
||||
numbers come from the World Bank; the detail further down comes from CBS Curaçao (the island's
|
||||
statistics office), Eurostat, ILOSTAT, Our World in Data and the UN. Amounts in guilders (ANG,
|
||||
pegged at 1.79 to the US dollar). The central bank's balance-of-payments tables can't be
|
||||
fetched automatically, so they aren't here yet.
|
||||
{:else}
|
||||
{name} at a glance, from the World Bank's development indicators and the IMF World Economic Outlook{imfCovered
|
||||
? ' (dashed lines are IMF forecasts)'
|
||||
: ''}.
|
||||
{/if}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="kpis">
|
||||
<Kpi
|
||||
label="Population"
|
||||
value={compact(kPop?.[1])}
|
||||
sub={` 10 yr · ${period(kPop?.[0], 'A')}`}
|
||||
delta={popDelta}
|
||||
deltaUnit="%"
|
||||
{color}
|
||||
/>
|
||||
<Kpi
|
||||
label="GDP per capita, PPP"
|
||||
value={`$${compact(kGdp?.[1])}`}
|
||||
sub={`constant 2021 int. $ · ${period(kGdp?.[0], 'A')}`}
|
||||
color="#10b981"
|
||||
/>
|
||||
<Kpi
|
||||
label="Real growth"
|
||||
value={num(kGrowth?.[1], 1)}
|
||||
unit="%"
|
||||
sub={period(kGrowth?.[0], 'A')}
|
||||
color="#3b82f6"
|
||||
/>
|
||||
<Kpi
|
||||
label="Inflation"
|
||||
value={num(kInfl?.[1], 1)}
|
||||
unit="%"
|
||||
sub={period(kInfl?.[0], 'A')}
|
||||
color="#e11d48"
|
||||
/>
|
||||
{#if kUnemp}
|
||||
<Kpi
|
||||
label="Unemployment"
|
||||
value={num(kUnemp[1], 1)}
|
||||
unit="%"
|
||||
sub={period(kUnemp[0], 'A')}
|
||||
color="#a855f7"
|
||||
/>
|
||||
{/if}
|
||||
{#if kDebt}
|
||||
<Kpi
|
||||
label="Government debt"
|
||||
value={num(kDebt[1], 0)}
|
||||
unit="% GDP"
|
||||
sub={period(kDebt[0], 'A')}
|
||||
color="#f97316"
|
||||
/>
|
||||
{/if}
|
||||
<Kpi
|
||||
label="Life expectancy"
|
||||
value={num(kLife?.[1], 1)}
|
||||
unit="yr"
|
||||
sub={period(kLife?.[0], 'A')}
|
||||
color="#06b6d4"
|
||||
/>
|
||||
{#if kTour}
|
||||
<Kpi
|
||||
label="Tourist arrivals"
|
||||
value={compact(kTour[1])}
|
||||
sub={period(kTour[0], 'A')}
|
||||
color="#eab308"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">People</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Population"
|
||||
subtitle="inhabitants · net migration on the right"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Population', points: pts('wb:SP.POP.TOTL'), color, kind: 'area' },
|
||||
{
|
||||
name: 'Net migration',
|
||||
points: pts('wb:SM.POP.NETM'),
|
||||
color: '#64748b',
|
||||
kind: 'bar',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ decimals: 0, min: 'dataMin', rightUnit: 'people' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Life expectancy"
|
||||
subtitle="years at birth, next to the Netherlands and the world"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name, points: pts('wb:SP.DYN.LE00.IN'), color },
|
||||
...(c !== 'NLD'
|
||||
? [
|
||||
{
|
||||
name: 'Netherlands',
|
||||
points: pts('wb:SP.DYN.LE00.IN', 'NLD'),
|
||||
color: '#f97316',
|
||||
dashed: true
|
||||
}
|
||||
]
|
||||
: []),
|
||||
...(c !== 'WLD'
|
||||
? [
|
||||
{
|
||||
name: 'World',
|
||||
points: pts('wb:SP.DYN.LE00.IN', 'WLD'),
|
||||
color: '#94a3b8',
|
||||
dashed: true
|
||||
}
|
||||
]
|
||||
: [])
|
||||
],
|
||||
{ unit: 'years', decimals: 1, min: 'dataMin' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Fertility and ageing"
|
||||
subtitle="births per woman · share aged 65+ on the right"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Fertility rate', points: pts('wb:SP.DYN.TFRT.IN'), color: '#ec4899' },
|
||||
{
|
||||
name: 'Aged 65+ (%)',
|
||||
points: pts('wb:SP.POP.65UP.TO.ZS'),
|
||||
color: '#64748b',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ unit: 'births', rightUnit: '%', decimals: 2 }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">Economy</h2>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="GDP per capita"
|
||||
subtitle="PPP, constant 2021 international $ · vs the Netherlands and the world"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name, points: pts('wb:NY.GDP.PCAP.PP.KD'), color },
|
||||
...(c !== 'NLD'
|
||||
? [
|
||||
{
|
||||
name: 'Netherlands',
|
||||
points: pts('wb:NY.GDP.PCAP.PP.KD', 'NLD'),
|
||||
color: '#f97316',
|
||||
dashed: true
|
||||
}
|
||||
]
|
||||
: []),
|
||||
...(c !== 'WLD'
|
||||
? [
|
||||
{
|
||||
name: 'World',
|
||||
points: pts('wb:NY.GDP.PCAP.PP.KD', 'WLD'),
|
||||
color: '#94a3b8',
|
||||
dashed: true
|
||||
}
|
||||
]
|
||||
: [])
|
||||
],
|
||||
{ unit: '$', decimals: 0 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Real GDP growth"
|
||||
subtitle={has('imf:NGDP_RPCH') ? '% a year · IMF WEO incl. forecasts' : '% a year · World Bank'}
|
||||
sources={has('imf:NGDP_RPCH') ? ['imf'] : ['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
has('imf:NGDP_RPCH')
|
||||
? imfLines('imf:NGDP_RPCH', 'Growth', '#3b82f6')
|
||||
: [
|
||||
{ name: 'Growth', points: pts('wb:NY.GDP.MKTP.KD.ZG'), color: '#3b82f6', kind: 'bar' }
|
||||
],
|
||||
{ unit: '%', decimals: 1, legend: has('imf:NGDP_RPCH') }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Inflation"
|
||||
subtitle="% consumer prices, a year"
|
||||
sources={has('imf:PCPIPCH') ? ['imf', 'worldbank'] : ['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
...(has('imf:PCPIPCH')
|
||||
? imfLines('imf:PCPIPCH', name, '#e11d48')
|
||||
: [{ name, points: pts('wb:FP.CPI.TOTL.ZG'), color: '#e11d48' }]),
|
||||
...(c !== 'NLD'
|
||||
? [
|
||||
{
|
||||
name: 'Netherlands',
|
||||
points: pts('wb:FP.CPI.TOTL.ZG', 'NLD'),
|
||||
color: '#f97316',
|
||||
dashed: true
|
||||
}
|
||||
]
|
||||
: [])
|
||||
],
|
||||
{ unit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
{#if has('imf:LUR') || has('wb:SL.UEM.TOTL.ZS')}
|
||||
<StatChart
|
||||
title="Unemployment"
|
||||
subtitle="% of the labour force"
|
||||
sources={has('imf:LUR') ? ['imf'] : ['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
has('imf:LUR')
|
||||
? imfLines('imf:LUR', 'Unemployment', '#a855f7')
|
||||
: [{ name: 'Unemployment', points: pts('wb:SL.UEM.TOTL.ZS'), color: '#a855f7' }],
|
||||
{ unit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
{#if has('wb:NE.EXP.GNFS.ZS') || has('wb:NE.TRD.GNFS.ZS')}
|
||||
<StatChart
|
||||
title="Trade"
|
||||
subtitle="exports and imports of goods and services, % of GDP"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Exports', points: pts('wb:NE.EXP.GNFS.ZS'), color: '#10b981' },
|
||||
{ name: 'Imports', points: pts('wb:NE.IMP.GNFS.ZS'), color: '#e11d48' },
|
||||
{
|
||||
name: 'Services value added',
|
||||
points: pts('wb:NV.SRV.TOTL.ZS'),
|
||||
color: '#64748b',
|
||||
dashed: true
|
||||
}
|
||||
],
|
||||
{ unit: '% GDP', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
{#if has('wb:ST.INT.ARVL') || has('wb:ST.INT.RCPT.CD')}
|
||||
<StatChart
|
||||
title="Tourism"
|
||||
subtitle="international arrivals · receipts (US$) on the right"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Arrivals', points: pts('wb:ST.INT.ARVL'), color: '#eab308', kind: 'bar' },
|
||||
{ name: 'Receipts', points: pts('wb:ST.INT.RCPT.CD'), color: '#06b6d4', right: true }
|
||||
],
|
||||
{ decimals: 0, rightUnit: 'US$' }
|
||||
)}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<h2 class="stats-section-title">Government and energy</h2>
|
||||
<div class="stats-grid">
|
||||
{#if !isCw || has('imf:GGXWDG_NGDP') || has('wb:GC.DOD.TOTL.GD.ZS')}
|
||||
<StatChart
|
||||
title="Government finances"
|
||||
subtitle={has('imf:GGXWDG_NGDP')
|
||||
? '% of GDP · IMF (general government)'
|
||||
: '% of GDP · World Bank (central government)'}
|
||||
sources={has('imf:GGXWDG_NGDP') ? ['imf'] : ['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
has('imf:GGXWDG_NGDP')
|
||||
? [
|
||||
...imfLines('imf:GGXWDG_NGDP', 'Debt', '#e11d48'),
|
||||
...imfLines('imf:GGR_G01_GDP_PT', 'Revenue', '#10b981'),
|
||||
...imfLines('imf:G_X_G01_GDP_PT', 'Spending', '#3b82f6')
|
||||
]
|
||||
: [
|
||||
{ name: 'Debt', points: pts('wb:GC.DOD.TOTL.GD.ZS'), color: '#e11d48' },
|
||||
{ name: 'Revenue', points: pts('wb:GC.REV.XGRT.GD.ZS'), color: '#10b981' },
|
||||
{ name: 'Expense', points: pts('wb:GC.XPN.TOTL.GD.ZS'), color: '#3b82f6' }
|
||||
],
|
||||
{ unit: '% GDP', decimals: 1 }
|
||||
)}
|
||||
note={!has('imf:GGXWDG_NGDP') && !has('wb:GC.DOD.TOTL.GD.ZS')
|
||||
? 'No government finance data for this country yet.'
|
||||
: ''}
|
||||
/>
|
||||
{/if}
|
||||
<StatChart
|
||||
title="Energy"
|
||||
subtitle="net energy imports (% of use) · renewable share of electricity"
|
||||
sources={['worldbank']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Net energy imports', points: pts('wb:EG.IMP.CONS.ZS'), color: '#64748b' },
|
||||
{ name: 'Renewable electricity', points: pts('wb:EG.ELC.RNEW.ZS'), color: '#10b981' }
|
||||
],
|
||||
{ unit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#if isCw}
|
||||
<h2 class="stats-section-title">Curaçao in detail</h2>
|
||||
<div class="kpis">
|
||||
<Kpi
|
||||
label="Population, 1 Jan"
|
||||
value={compact(cwPop?.[1])}
|
||||
sub={`CBS Curaçao · ${period(cwPop?.[0], 'A')}`}
|
||||
{color}
|
||||
/>
|
||||
<Kpi
|
||||
label="Inflation"
|
||||
value={num(cwCpi?.[1], 1)}
|
||||
unit="%"
|
||||
sub={`year on year · ${period(cwCpi?.[0], 'M')}`}
|
||||
color="#e11d48"
|
||||
/>
|
||||
<Kpi
|
||||
label="Real growth"
|
||||
value={num(cwGrowth?.[1], 1)}
|
||||
unit="%"
|
||||
sub={period(cwGrowth?.[0], 'A')}
|
||||
color="#3b82f6"
|
||||
/>
|
||||
<Kpi
|
||||
label="Unemployment"
|
||||
value={num(cwUnemp?.[1], 1)}
|
||||
unit="%"
|
||||
sub={`labour force survey · ${period(cwUnemp?.[0], 'A')}`}
|
||||
color="#a855f7"
|
||||
/>
|
||||
</div>
|
||||
<div class="stats-grid">
|
||||
<StatChart
|
||||
title="Consumer prices since 1970"
|
||||
subtitle="CPI (2023 = 100) · inflation year on year (%) on the right"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'CPI', points: cw('cw:cpi:index'), color: '#64748b', kind: 'area' },
|
||||
{ name: 'Inflation', points: cw('cw:cpi:yoy'), color: '#e11d48', right: true }
|
||||
],
|
||||
{ unit: 'index', rightUnit: '%', decimals: 1, zoom: true }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="GDP"
|
||||
subtitle="nominal, million guilders · real growth (%) on the right"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'GDP', points: cw('cw:gdp:gdp'), color, kind: 'bar' },
|
||||
{
|
||||
name: 'Real growth',
|
||||
points: cw('cw:gdp:real_growth_pct'),
|
||||
color: '#3b82f6',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ unit: 'mln ANG', rightUnit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="GDP by industry"
|
||||
subtitle={`gross value added, million guilders · ${period(cwGdpYear, 'A')}`}
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
height="420px"
|
||||
option={(t) => barRankOption(t, cwIndustries, { decimals: 0, unit: 'mln ANG', color })}
|
||||
/>
|
||||
<StatChart
|
||||
title="Population since 1900"
|
||||
subtitle="1 January (31 December before 1992) and census counts · UN estimate dashed"
|
||||
sources={['cbscw', 'owid']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Population', points: cw('cw:pop:jan1'), color, kind: 'area' },
|
||||
{ name: 'Census', points: cw('cw:pop:census'), color: '#0f172a', kind: 'bar' },
|
||||
{
|
||||
name: 'UN WPP (via OWID)',
|
||||
points: cw('owid:cw:population'),
|
||||
color: '#94a3b8',
|
||||
dashed: true
|
||||
}
|
||||
],
|
||||
{ decimals: 0, unit: 'people' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Unemployment"
|
||||
subtitle="% of the labour force · CBS labour force survey (no survey in 2021 and 2023), ILO dashed"
|
||||
sources={['cbscw', 'ilostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Total', points: cw('cw:lfs:unemployment_rate_pct:total'), color: '#a855f7' },
|
||||
{ name: 'Men', points: cw('cw:lfs:unemployment_rate_pct:m'), color: '#3b82f6' },
|
||||
{ name: 'Women', points: cw('cw:lfs:unemployment_rate_pct:f'), color: '#ec4899' },
|
||||
{
|
||||
name: 'Aged 15–24',
|
||||
points: cw('cw:lfs:unemployment_rate_pct:15-24'),
|
||||
color: '#f97316'
|
||||
},
|
||||
{
|
||||
name: 'ILO estimate (15+)',
|
||||
points: cw('ilostat:une_deap_sex_age_rt:total:15plus'),
|
||||
color: '#94a3b8',
|
||||
dashed: true
|
||||
}
|
||||
],
|
||||
{ unit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Tourism"
|
||||
subtitle="cruise passengers and daytrippers · stay-over nights on the right"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Cruise passengers',
|
||||
points: cw('cw:tour:cruise_pax'),
|
||||
color: '#06b6d4',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Daytrippers',
|
||||
points: cw('cw:tour:daytrippers'),
|
||||
color: '#eab308',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Stay-over nights',
|
||||
points: cw('cw:tour:nights'),
|
||||
color: '#e11d48',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ decimals: 0, rightUnit: 'nights' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Stay-over nights by market"
|
||||
subtitle="tourist nights by region of residence"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
Object.entries(CW_NIGHT_MARKETS).map(([k, label], i) => ({
|
||||
name: label,
|
||||
points: cw(`cw:tour:nights:${k}`),
|
||||
color: ['#3b82f6', '#e11d48', '#10b981', '#eab308', '#94a3b8'][i],
|
||||
kind: 'bar' as const,
|
||||
stack: 'nights'
|
||||
})),
|
||||
{ decimals: 0, unit: 'nights' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Government revenue and expenditure"
|
||||
subtitle="million guilders · balance as bars (recent years provisional)"
|
||||
sources={['cbscw']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{ name: 'Revenue', points: cw('cw:gov:r.total'), color: '#10b981' },
|
||||
{ name: 'Expenditure', points: cw('cw:gov:e.total'), color: '#3b82f6' },
|
||||
{ name: 'Balance', points: cw('cw:gov:balance'), color: '#e11d48', kind: 'bar' }
|
||||
],
|
||||
{ unit: 'mln ANG', decimals: 0 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Trade with the EU"
|
||||
subtitle="EU27 goods exports to and imports from Curaçao, million €"
|
||||
sources={['eurostat']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'EU exports to Curaçao',
|
||||
points: cw(EU_TRADE('MIO_EXP_VAL')),
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{
|
||||
name: 'EU imports from Curaçao',
|
||||
points: cw(EU_TRADE('MIO_IMP_VAL')),
|
||||
color: '#f97316'
|
||||
},
|
||||
{
|
||||
name: 'EU balance',
|
||||
points: cw(EU_TRADE('MIO_BAL_VAL')),
|
||||
color: '#94a3b8',
|
||||
kind: 'bar'
|
||||
}
|
||||
],
|
||||
{ unit: 'mln €', decimals: 0 }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Goods trade (as reported by Curaçao)"
|
||||
subtitle="US$ · only 2017–2020 are reported to the UN"
|
||||
sources={['comtrade']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'Imports',
|
||||
points: cw('comtrade:cw:imports:world'),
|
||||
color: '#e11d48',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Exports',
|
||||
points: cw('comtrade:cw:exports:world'),
|
||||
color: '#10b981',
|
||||
kind: 'bar'
|
||||
},
|
||||
{
|
||||
name: 'Imports from the US',
|
||||
points: cw('comtrade:cw:imports:usa'),
|
||||
color: '#3b82f6'
|
||||
},
|
||||
{ name: 'Imports from NL', points: cw('comtrade:cw:imports:nld'), color: '#f97316' }
|
||||
],
|
||||
{ decimals: 0, unit: 'US$' }
|
||||
)}
|
||||
/>
|
||||
<StatChart
|
||||
title="Climate and energy"
|
||||
subtitle="CO₂ per person (t) · renewable share of final energy (%) on the right"
|
||||
sources={['owid', 'unsdg']}
|
||||
attributions={a}
|
||||
option={(t) =>
|
||||
lineOption(
|
||||
t,
|
||||
[
|
||||
{
|
||||
name: 'CO₂ per person',
|
||||
points: cw('owid:cw:co-emissions-per-capita'),
|
||||
color: '#64748b'
|
||||
},
|
||||
{
|
||||
name: 'Renewable share',
|
||||
points: cw('unsdg:eg_fec_rnew'),
|
||||
color: '#10b981',
|
||||
right: true
|
||||
}
|
||||
],
|
||||
{ unit: 't', rightUnit: '%', decimals: 1 }
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if data.heritage}
|
||||
<PlaceHeritage h={data.heritage} attributions={a} />
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.back {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
color: var(--site-muted);
|
||||
font-size: 0.8rem;
|
||||
text-decoration: none;
|
||||
width: fit-content;
|
||||
}
|
||||
.back:hover {
|
||||
color: var(--site-text);
|
||||
}
|
||||
.flag {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user