Skip to content

Commit 855935f

Browse files
added state filter for tourism statistic
1 parent 4b4c1e3 commit 855935f

File tree

7 files changed

+344
-115
lines changed

7 files changed

+344
-115
lines changed

assets/controllers/statistics_controller.js

Lines changed: 85 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ export default class extends Controller {
2626
'snapshotArrivalsChart',
2727
'snapshotOvernightsChart',
2828
'snapshotByCountryBody',
29+
'showByState',
30+
'byCountryTableHeader',
31+
'byCountryColumnHeader',
32+
'arrivalsChartHeader',
33+
'overnightsChartHeader',
34+
'noStateDataHint',
2935
];
3036

3137
static values = {
@@ -40,6 +46,15 @@ export default class extends Controller {
4046
snapshotArrivalsLabel: String,
4147
snapshotOvernightsLabel: String,
4248
snapshotRoomLabel: String,
49+
byCountryTableLabel: String,
50+
byStateTableLabel: String,
51+
countryLabel: String,
52+
stateLabel: String,
53+
arrivalsByCountryLabel: String,
54+
overnightsByCountryLabel: String,
55+
arrivalsByStateLabel: String,
56+
overnightsByStateLabel: String,
57+
noStateDataLabel: String,
4358
};
4459

4560
connect() {
@@ -320,17 +335,52 @@ export default class extends Controller {
320335
const data = await response.json();
321336
this.currentSnapshotId = data.id || null;
322337
const countryNames = data.countryNames || {};
338+
this.lastTourismData = (data.metrics && data.metrics.tourism) ? data.metrics.tourism : {};
339+
this.lastCountryNames = countryNames;
323340

324341
this.updateSnapshotSummary(data.metrics || {});
325342
this.updateSnapshotWarnings(data.warnings || []);
326-
this.updateSnapshotByCountryTable(
327-
(data.metrics && data.metrics.tourism) ? data.metrics.tourism : {},
328-
countryNames
329-
);
330-
await this.drawSnapshotCharts(
331-
(data.metrics && data.metrics.tourism) ? data.metrics.tourism : {},
332-
countryNames
333-
);
343+
this.renderTourismView();
344+
}
345+
346+
get isStateView() {
347+
return this.hasShowByStateTarget && this.showByStateTarget.checked;
348+
}
349+
350+
toggleByState() {
351+
this.renderTourismView();
352+
}
353+
354+
renderTourismView() {
355+
const tourism = this.lastTourismData || {};
356+
const countryNames = this.lastCountryNames || {};
357+
this.updateHeaders();
358+
this.updateSnapshotByCountryTable(tourism, countryNames);
359+
this.drawSnapshotCharts(tourism, countryNames);
360+
}
361+
362+
updateHeaders() {
363+
const byState = this.isStateView;
364+
if (this.hasByCountryTableHeaderTarget) {
365+
this.byCountryTableHeaderTarget.textContent = byState
366+
? (this.byStateTableLabelValue || 'By state')
367+
: (this.byCountryTableLabelValue || 'By country');
368+
}
369+
if (this.hasByCountryColumnHeaderTarget) {
370+
this.byCountryColumnHeaderTarget.textContent = byState
371+
? (this.stateLabelValue || 'State')
372+
: (this.countryLabelValue || 'Country');
373+
}
374+
if (this.hasArrivalsChartHeaderTarget) {
375+
this.arrivalsChartHeaderTarget.textContent = byState
376+
? (this.arrivalsByStateLabelValue || 'Arrivals by state')
377+
: (this.arrivalsByCountryLabelValue || 'Arrivals by country');
378+
}
379+
if (this.hasOvernightsChartHeaderTarget) {
380+
this.overnightsChartHeaderTarget.textContent = byState
381+
? (this.overnightsByStateLabelValue || 'Overnights by state')
382+
: (this.overnightsByCountryLabelValue || 'Overnights by country');
383+
}
334384
}
335385

336386
snapshotParams(force = false) {
@@ -413,39 +463,53 @@ export default class extends Controller {
413463

414464
updateSnapshotByCountryTable(tourism, countryNames) {
415465
if (!this.hasSnapshotByCountryBodyTarget) return;
416-
const arrivals = tourism.arrivals_by_country || {};
417-
const overnights = tourism.overnights_by_country || {};
418-
const countries = Array.from(new Set([
466+
const byState = this.isStateView;
467+
const arrivals = byState ? (tourism.arrivals_by_state || {}) : (tourism.arrivals_by_country || {});
468+
const overnights = byState ? (tourism.overnights_by_state || {}) : (tourism.overnights_by_country || {});
469+
const keys = Array.from(new Set([
419470
...Object.keys(arrivals),
420471
...Object.keys(overnights),
421472
])).sort();
422473

423474
this.snapshotByCountryBodyTarget.innerHTML = '';
424-
countries.forEach((country) => {
425-
const label = this.mapCountryLabel(country, countryNames);
475+
keys.forEach((key) => {
476+
const label = byState ? this.formatStateLabel(key) : this.mapCountryLabel(key, countryNames);
426477
const tr = document.createElement('tr');
427-
const tdCountry = document.createElement('td');
478+
const tdKey = document.createElement('td');
428479
const tdArrivals = document.createElement('td');
429480
const tdOvernights = document.createElement('td');
430-
tdCountry.textContent = label;
431-
tdArrivals.textContent = (arrivals[country] ?? 0).toLocaleString();
432-
tdOvernights.textContent = (overnights[country] ?? 0).toLocaleString();
433-
tr.appendChild(tdCountry);
481+
tdKey.textContent = label;
482+
tdArrivals.textContent = (arrivals[key] ?? 0).toLocaleString();
483+
tdOvernights.textContent = (overnights[key] ?? 0).toLocaleString();
484+
tr.appendChild(tdKey);
434485
tr.appendChild(tdArrivals);
435486
tr.appendChild(tdOvernights);
436487
this.snapshotByCountryBodyTarget.appendChild(tr);
437488
});
489+
490+
if (this.hasNoStateDataHintTarget) {
491+
this.noStateDataHintTarget.classList.toggle('d-none', !byState || keys.length > 0);
492+
}
493+
}
494+
495+
formatStateLabel(stateKey) {
496+
const slashPos = stateKey.indexOf('/');
497+
if (slashPos === -1) return stateKey;
498+
const countryCode = stateKey.substring(0, slashPos);
499+
const stateName = stateKey.substring(slashPos + 1);
500+
return `${stateName} (${countryCode})`;
438501
}
439502

440503
async drawSnapshotCharts(tourism, countryNames) {
441504
if (!(await this.waitForChart())) return;
442-
const arrivals = tourism.arrivals_by_country || {};
443-
const overnights = tourism.overnights_by_country || {};
505+
const byState = this.isStateView;
506+
const arrivals = byState ? (tourism.arrivals_by_state || {}) : (tourism.arrivals_by_country || {});
507+
const overnights = byState ? (tourism.overnights_by_state || {}) : (tourism.overnights_by_country || {});
444508
const codes = Array.from(new Set([
445509
...Object.keys(arrivals),
446510
...Object.keys(overnights),
447511
])).sort();
448-
const labels = codes;
512+
const labels = codes.map((code) => byState ? this.formatStateLabel(code) : code);
449513
const arrivalsData = codes.map((code) => arrivals[code] ?? 0);
450514
const overnightsData = codes.map((code) => overnights[code] ?? 0);
451515

config/packages/framework.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ parameters:
66

77
framework:
88
secret: '%env(APP_SECRET)%'
9-
trusted_proxies: '%env(TRUSTED_PROXIES)%'
9+
trusted_proxies: '%env(trim:TRUSTED_PROXIES)%'
1010
trusted_headers: [ 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix' ]
1111
#default_locale: en
1212
#csrf_protection: true

src/Repository/PostalCodeDataRepository.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,19 @@ public function findPlacesByCode(string $country, string $zip)
3838
;
3939
}
4040

41-
/*
42-
public function findOneBySomeField($value): ?PostalCodeData
41+
public function findStateByCountryAndZip(string $countryCode, string $zip): ?string
4342
{
44-
return $this->createQueryBuilder('p')
45-
->andWhere('p.exampleField = :val')
46-
->setParameter('val', $value)
43+
$result = $this->createQueryBuilder('p')
44+
->select('p.stateName')
45+
->where('p.countryCode = :country')
46+
->andWhere('p.postalCode = :zip')
47+
->setParameter('country', $countryCode)
48+
->setParameter('zip', $zip)
49+
->setMaxResults(1)
4750
->getQuery()
4851
->getOneOrNullResult()
4952
;
53+
54+
return $result['stateName'] ?? null;
5055
}
51-
*/
5256
}

0 commit comments

Comments
 (0)