From 24abdb54b8def7496cb015079ba2715f53342c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20K=C3=B6ves?= <3187531+vkoves@users.noreply.github.com> Date: Thu, 24 Sep 2026 19:46:20 -0500 Subject: [PATCH 1/2] Add property types sort toggle --- src/pages/PropertyTypes.vue | 55 +++++++++++++++++++++++++++++++------ src/scss/global.scss | 38 +++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/src/pages/PropertyTypes.vue b/src/pages/PropertyTypes.vue index 4c677c68..4b417f85 100644 --- a/src/pages/PropertyTypes.vue +++ b/src/pages/PropertyTypes.vue @@ -37,6 +37,9 @@ interface IPropertyTypeSummary { imgUrl: string | null; } +/** The fields the property type list can be sorted by */ +type PropertyTypeSortField = 'buildingCount' | 'totalGHGEmissions'; + /** * Total emissions across every property type we have stats for, used as the * denominator for each type's share. This covers a few types that don't have @@ -69,17 +72,33 @@ export default class PropertyTypes extends Vue { /** Set by Gridsome to results of the static GraphQL query */ readonly $static!: { allBuilding: { edges: Array } }; + /** The sort options shown in the toggle, in display order */ + readonly SortOptions: Array<{ field: PropertyTypeSortField; label: string }> = + [ + { field: 'buildingCount', label: 'Most Buildings' }, + { field: 'totalGHGEmissions', label: 'Highest Emissions' }, + ]; + + /** All property types that have a generated page, unsorted */ + propertyTypes: Array = []; + /** - * All property types that have a generated page, sorted by building count - * descending, since the largest categories are the most useful to browse + * The field to sort by, descending. Defaults to building count since the + * largest categories are the most useful to browse */ - propertyTypes: Array = []; + sortField: PropertyTypeSortField = 'buildingCount'; + + get sortedPropertyTypes(): Array { + return [...this.propertyTypes].sort( + (a, b) => b[this.sortField] - a[this.sortField], + ); + } created(): void { const featuredBuildings = this.buildFeaturedBuildingMap(); - this.propertyTypes = PropertyTypesConstant.propertyTypes - .map((propertyType: string) => { + this.propertyTypes = PropertyTypesConstant.propertyTypes.map( + (propertyType: string) => { const stats = ( BuildingStatsByPropertyType as Record )[propertyType] as PropertyTypeStats | undefined; @@ -103,8 +122,8 @@ export default class PropertyTypes extends Vue { ? (getBuildingImage(featuredBuilding)?.imgUrl ?? null) : null, }; - }) - .sort((a, b) => b.buildingCount - a.buildingCount); + }, + ); } /** @@ -201,8 +220,24 @@ export default class PropertyTypes extends Vue { city as a whole is trending.

+
+ +
+
    -
  • +
  • Date: Thu, 24 Sep 2026 19:59:30 -0500 Subject: [PATCH 2/2] Add emissions share rank --- src/pages/PropertyTypes.vue | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/pages/PropertyTypes.vue b/src/pages/PropertyTypes.vue index 4b417f85..d09fd7b3 100644 --- a/src/pages/PropertyTypes.vue +++ b/src/pages/PropertyTypes.vue @@ -30,6 +30,8 @@ interface IPropertyTypeSummary { totalGHGEmissions: number; /** Share of all benchmarked emissions, as a percent (e.g. 12.4) */ percentOfTotalEmissions: number; + /** Rank by total emissions among all property types, 1 being the highest */ + emissionsRank: number; avgGHGIntensity: number; /** The largest building of this type that has a photo, if any */ featuredBuilding: IBuilding | null; @@ -37,6 +39,9 @@ interface IPropertyTypeSummary { imgUrl: string | null; } +/** Only show a property type's emissions rank if it's at least this high */ +const MaxEmissionsRankShown = 10; + /** The fields the property type list can be sorted by */ type PropertyTypeSortField = 'buildingCount' | 'totalGHGEmissions'; @@ -88,6 +93,8 @@ export default class PropertyTypes extends Vue { */ sortField: PropertyTypeSortField = 'buildingCount'; + readonly MaxEmissionsRankShown = MaxEmissionsRankShown; + get sortedPropertyTypes(): Array { return [...this.propertyTypes].sort( (a, b) => b[this.sortField] - a[this.sortField], @@ -116,6 +123,8 @@ export default class PropertyTypes extends Vue { percentOfTotalEmissions: CitywideTotalEmissions ? (totalGHGEmissions / CitywideTotalEmissions) * 100 : 0, + // Set below, once we have every type's emissions to compare + emissionsRank: 0, avgGHGIntensity: stats?.GHGIntensity?.mean ?? 0, featuredBuilding, imgUrl: featuredBuilding @@ -124,6 +133,12 @@ export default class PropertyTypes extends Vue { }; }, ); + + [...this.propertyTypes] + .sort((a, b) => b.totalGHGEmissions - a.totalGHGEmissions) + .forEach((type, index) => { + type.emissionsRank = index + 1; + }); } /** @@ -294,6 +309,14 @@ export default class PropertyTypes extends Vue { }} of total benchmarked + + + #{{ type.emissionsRank }} + highest + @@ -437,7 +460,8 @@ export default class PropertyTypes extends Vue { font-size: 1rem; } - .type-percent { + .type-percent, + .type-rank { display: block; font-size: 0.875rem; color: $text-mid-light;