Skip to content

Commit

Permalink
Merge tag 'v0.36.0-rc.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
evanp committed Dec 16, 2024
2 parents 7579946 + 7b83ac8 commit 1e509d9
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 38 deletions.
4 changes: 2 additions & 2 deletions app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "city-catalyst",
"version": "0.35.0",
"version": "0.36.0-rc.0",
"private": true,
"type": "module",
"scripts": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ interface EmissionBySectorTableProps {

type ExtendedSectorEmission = SectorEmission & {
percentageChange: number | null;
totalInventoryPercentage: number;
totalInventoryPercentage: number | null;
};

const EmissionBySectorTableSection: React.FC<EmissionBySectorTableProps> = ({
Expand Down
50 changes: 28 additions & 22 deletions app/src/app/[lng]/[inventory]/InventoryResultTab/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useTranslation } from "@/i18n/client";
import { InventoryResponse, SectorEmission } from "@/util/types";
import { CityYearData, InventoryResponse, SectorEmission } from "@/util/types";
import {
Box,
Card,
Expand All @@ -28,14 +28,13 @@ import { capitalizeFirstLetter, toKebabCase } from "@/util/helpers";
import React, { ChangeEvent, useMemo, useState } from "react";
import {
api,
useGetCitiesAndYearsQuery,
useGetCityYearsQuery,
useGetYearOverYearResultsQuery,
} from "@/services/api";
import ByScopeView from "@/app/[lng]/[inventory]/InventoryResultTab/ByScopeView";
import { SectorHeader } from "@/app/[lng]/[inventory]/InventoryResultTab/SectorHeader";
import { ByActivityView } from "@/app/[lng]/[inventory]/InventoryResultTab/ByActivityView";
import { getSectorsForInventory, SECTORS } from "@/util/constants";
import { Selector } from "@/components/selector";
import { EmptyStateCardContent } from "@/app/[lng]/[inventory]/InventoryResultTab/EmptyStateCardContent";
import { Trans } from "react-i18next/TransWithoutContext";
import ButtonGroupToggle from "@/components/button-group-toggle";
Expand Down Expand Up @@ -265,51 +264,57 @@ export function EmissionPerSectors({
skip: !inventory?.cityId,
});

const { data: citiesAndYears, isLoading } = useGetCitiesAndYearsQuery();
const { data: cityYears, isLoading } = useGetCityYearsQuery(
inventory?.cityId,
);

const loadingState = isLoading || isLoadingYearlgyGhg;

const targetYears = useMemo<
| Record<string, { year: number; inventoryId: string; lastUpdate: Date }>
| undefined
Record<string, { year: number; inventoryId: string; lastUpdate: Date }>
>(() => {
return citiesAndYears
?.find(({ city }) => inventory.cityId === city.cityId)
?.years.reduce(
(acc, curr) => {
return (
cityYears?.years.reduce(
(acc: Record<string, CityYearData>, curr: CityYearData) => {
acc[curr.inventoryId] = curr;
return acc;
},
{} as Record<string, any>,
);
}, [citiesAndYears, inventory]);
) ?? {}
);
}, [cityYears]);

const transformedYearOverYearData = useMemo(() => {
if (yearlyGhgResult && targetYears) {
const yearlyMap: Record<string, SectorEmission[]> = {};
const totalInventoryEmissions: Record<string, bigint> = {};
const response = Object.keys(yearlyGhgResult).map((inventoryId) => {
const yearData = targetYears[inventoryId];
const year = targetYears[inventoryId].year;
const totalEmissions = yearlyGhgResult[inventoryId].totalEmissions;
yearlyMap[yearData.year] = totalEmissions.totalEmissionsBySector;
totalInventoryEmissions[yearData.year] = BigInt(
totalEmissions.sumOfEmissions,
);
yearlyMap[year] = totalEmissions.totalEmissionsBySector;
totalInventoryEmissions[year] = BigInt(totalEmissions.sumOfEmissions);

return {
bySector: [...totalEmissions.totalEmissionsBySector],
...yearData,
year,
inventoryId,
};
});

// taking the response object let's working on getting the percentage increase for each year
return response
.map((data) => {
const yearWithPercentageIncrease = data.bySector.map((sectorData) => {
const totalInventoryPercentage = Number(
(BigInt(sectorData.co2eq) * 100n) /
totalInventoryEmissions[data.year],
);
const inventoryEmissions = totalInventoryEmissions[data.year];
if (!inventoryEmissions) {
console.error(
"Total inventory emissions missing for year " + data.year,
);
}

const totalInventoryPercentage = inventoryEmissions
? Number((BigInt(sectorData.co2eq) * 100n) / inventoryEmissions)
: null;

let percentageChange: number | null = null;
if (data.year - 1 in yearlyMap) {
Expand Down Expand Up @@ -339,6 +344,7 @@ export function EmissionPerSectors({
bySector: yearWithPercentageIncrease,
};
})
.filter((data) => !!data)
.sort((a, b) => b.year - a.year);
}
return [];
Expand Down
6 changes: 2 additions & 4 deletions app/src/app/api/v0/city/[city]/population/[year]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ export const GET = apiHandler(async (_req: Request, { session, params }) => {
const city = await UserService.findUserCity(params.city, session, true);
const year = z.coerce.number().parse(params.year);

const cityPopulationData = PopulationService.getPopulationDataForCityYear(
city.cityId,
year,
);
const cityPopulationData =
await PopulationService.getPopulationDataForCityYear(city.cityId, year);

return NextResponse.json({
data: cityPopulationData,
Expand Down
47 changes: 47 additions & 0 deletions app/src/app/api/v0/city/[city]/years/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// fetch the years of the inventories attached to a city

import { apiHandler } from "@/util/api";
import { NextRequest, NextResponse } from "next/server";
import createHttpError from "http-errors";
import { db } from "@/models";

export const GET = apiHandler(async (_req: NextRequest, { params }) => {
// TODO implement access control (check if inventory is public)
/* if (!context.session && !inventory.isPublic) {
throw new createHttpError.Unauthorized("Unauthorized");
} */

const city = await db.models.City.findByPk(params.city, {
include: [
{
model: db.models.Inventory,
as: "inventories",
attributes: ["year", "inventoryId", "lastUpdated"],
},
],
});

if (!city) {
throw new createHttpError.NotFound("City not found");
}

return NextResponse.json({
data: {
city: {
name: city.name,
locode: city.locode,
area: city.area,
country: city.country,
countryLocode: city.countryLocode,
region: city.region,
regionLocode: city.regionLocode,
cityId: city.cityId,
},
years: city.inventories.map((inventory) => ({
year: inventory.year,
inventoryId: inventory.inventoryId,
lastUpdate: inventory.lastUpdated,
})),
},
});
});
7 changes: 4 additions & 3 deletions app/src/components/InventorySelect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { api, useGetCitiesAndYearsQuery } from "@/services/api";
import type { CitiesAndYearsResponse } from "@/util/types";
import type { CityAndYearsResponse } from "@/util/types";
import {
Center,
Icon,
Expand Down Expand Up @@ -30,7 +30,7 @@ export const InventorySelect = ({
const { data: citiesAndYears, isLoading } = useGetCitiesAndYearsQuery();

const [setUserInfo] = api.useSetUserInfoMutation();
const onSelect = async ({ city, years }: CitiesAndYearsResponse) => {
const onSelect = async ({ city, years }: CityAndYearsResponse) => {
// get the latest inventory for the city
let targetInventory = years[0];
await setUserInfo({
Expand All @@ -53,7 +53,8 @@ export const InventorySelect = ({
)}
{citiesAndYears?.map(({ city, years }) => {
const isCurrent = years.some(
(y) => y.inventoryId === currentInventoryId,
(y: { inventoryId: string }) =>
y.inventoryId === currentInventoryId,
);
return (
<MenuItem
Expand Down
13 changes: 10 additions & 3 deletions app/src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from "@/models/init-models";
import type { BoundingBox } from "@/util/geojson";
import {
CitiesAndYearsResponse,
CityAndYearsResponse,
ConnectDataSourceQuery,
ConnectDataSourceResponse,
EmissionsFactorResponse,
Expand Down Expand Up @@ -51,15 +51,21 @@ export const api = createApi({
],
baseQuery: fetchBaseQuery({ baseUrl: "/api/v0/", credentials: "include" }),
endpoints: (builder) => ({
getCitiesAndYears: builder.query<CitiesAndYearsResponse[], void>({
getCitiesAndYears: builder.query<CityAndYearsResponse[], void>({
query: () => "user/cities",
transformResponse: (response: { data: CitiesAndYearsResponse[] }) =>
transformResponse: (response: { data: CityAndYearsResponse[] }) =>
response.data.map(({ city, years }) => ({
city,
years: years.sort((a, b) => b.year - a.year),
})),
providesTags: ["CitiesAndInventories"],
}),
getCityYears: builder.query<CityAndYearsResponse, string>({
query: (cityId) => `city/${cityId}/years`,
transformResponse: (response: { data: CityAndYearsResponse }) =>
response.data,
providesTags: ["CitiesAndInventories"],
}),
getCity: builder.query<CityAttributes, string>({
query: (cityId) => `city/${cityId}`,
transformResponse: (response: { data: CityAttributes }) => response.data,
Expand Down Expand Up @@ -710,6 +716,7 @@ export const GLOBAL_API_URL =
// hooks are automatically generated
export const {
useGetCityQuery,
useGetCityYearsQuery,
useGetCitiesAndYearsQuery,
useGetYearOverYearResultsQuery,
useAddCityMutation,
Expand Down
10 changes: 8 additions & 2 deletions app/src/util/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ import {
} from "@/backend/DataSourceService";
import { ActivityValue } from "@/models/ActivityValue";

export interface CitiesAndYearsResponse {
export interface CityAndYearsResponse {
city: CityAttributes;
years: { year: number; inventoryId: string; lastUpdate: Date }[];
years: CityYearData[];
}

export interface CityYearData {
year: number;
inventoryId: string;
lastUpdate: Date;
}

interface RequiredInventoryAttributes extends Required<InventoryAttributes> {}
Expand Down

0 comments on commit 1e509d9

Please sign in to comment.