Skip to content

Commit 786277c

Browse files
Merge pull request #52 from klimadashboard/feat/company-emissions-zod-typescript
feat(companies): typescript support to companies emissions
2 parents 3d11501 + 18b6597 commit 786277c

13 files changed

Lines changed: 166 additions & 311 deletions

src/lib/components/charts/custom/companiesEmissions/CheckIcon.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script>
1+
<script lang="ts">
22
export let additionalClasses = '';
33
</script>
44

src/lib/components/charts/custom/companiesEmissions/CompanyClimateGoals.svelte

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
<script>
2-
import companies from '$lib/stores/companies';
1+
<script lang="ts">
32
import CheckIcon from './CheckIcon.svelte';
43
import XIcon from './XIcon.svelte';
4+
import type { CompanyMetaData } from './types';
55
6-
export let companiesGoalData = [];
6+
export let companiesGoalData: CompanyMetaData[] = [];
77
8-
let isOMV = false;
8+
let isOMV: boolean = false;
99
$: isOMV = !!companiesGoalData.filter((company) => company.name === 'OMV AG').length;
1010
1111
const tableCellClasses = 'text-semibold text-sm text-center px-1 leading-tight py-1';
@@ -31,16 +31,15 @@
3131
</tr>
3232
{/if}
3333
{#each companiesGoalData as company (company.name)}
34-
{@const companyMetaData = companies.find((c) => c.name == company.name)}
3534
<tr class="border-b">
3635
<td class={tableCellClasses}>
3736
<img
3837
src="https://base.klimadashboard.org/assets/{company.logoId}"
39-
alt={companiesGoalData.name}
38+
alt={company.name}
4039
width="80"
4140
height="80"
4241
class="inline-block w-24 h-16 p-2 m-1 object-contain dark:bg-gray-100 rounded-xl"
43-
title={companiesGoalData.name}
42+
title={company.name}
4443
/>
4544
</td>
4645
<td class={tableCellClasses}>
@@ -56,7 +55,7 @@
5655
{/if}
5756
{/if}
5857
</td>
59-
<td class={tableCellClasses} title={company.member_sbt}>
58+
<td class={tableCellClasses}>
6059
{#if company.member_sbt}
6160
<CheckIcon additionalClasses="mx-auto" />
6261
{:else}
@@ -68,10 +67,10 @@
6867
{/each}
6968
</tbody>
7069
</table>
71-
{#if isOMV}
72-
<p class="text-sm pt-4">
73-
*Öl und Gaskonzerne wie die OMV können aktuell nicht an der Science Based Target Initative
74-
teilnehmen (SBTi Oil and Gas) und ihre Emmissionsziele validieren lassen.
75-
</p>
76-
{/if}
70+
{/if}
71+
{#if isOMV}
72+
<p class="text-sm pt-4">
73+
*Öl und Gaskonzerne wie die OMV können aktuell nicht an der Science Based Target Initative
74+
teilnehmen (SBTi Oil and Gas) und ihre Emmissionsziele validieren lassen.
75+
</p>
7776
{/if}

src/lib/components/charts/custom/companiesEmissions/CompanyEmissionsContainer.svelte

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
1-
<script>
2-
// @ts-nocheck
3-
import atxCompanies from '$lib/stores/companies';
4-
import getDirectusInstance from '$lib/utils/directus';
5-
import { readItems } from '@directus/sdk';
6-
import { PUBLIC_VERSION } from '$env/static/public';
1+
<script lang="ts">
72
import CompanyEmissionsLineChart from './CompanyEmissionsLineChart.svelte';
83
import CompanyClimateGoals from './CompanyClimateGoals.svelte';
9-
import { EMISSION_SCOPE_KEYS } from './constants';
10-
import { getCompanyEmissionData, getAllSectors, getCompanyMetaData } from './getData';
4+
import { getCompanyEmissionData, getAllSectors } from './getData';
115
import Switch from '$lib/components/Switch.svelte';
126
import { glossaryItem } from '$lib/stores/glossary';
137
import DataDownload from './DataDownload.svelte';
148
import { page } from '$app/state';
9+
import type { CompanyMetaData, CompanyMetaDataArray } from './types';
1510
16-
export let companiesMetaData = [];
11+
export let companiesMetaData: CompanyMetaDataArray = [];
1712
export let chart;
1813
19-
const scopes = EMISSION_SCOPE_KEYS;
20-
let selectedScopes = [1];
14+
const scopes = [1, 2, 3];
15+
let selectedScopes: number[] = [1];
2116
let selectedSector = '';
22-
let emissions;
2317
let isFocusView = true;
2418
let initialCompany = 'Erste Group Bank AG';
2519
let selectedCompaniesNames = [initialCompany];
@@ -38,6 +32,8 @@
3832
];
3933
let selectedScope2Category = 'location_based';
4034
35+
type CompanyWithSelected = CompanyMetaData & { selected: boolean };
36+
4137
$: companies = companiesMetaData.map((company) => {
4238
if (page.params.id && company.id === page.params.id) {
4339
return {
@@ -50,7 +46,7 @@
5046
selected: false
5147
};
5248
}
53-
});
49+
}) as CompanyWithSelected[];
5450
5551
function selectAll() {
5652
companies = companies.map((company) => {
@@ -72,7 +68,7 @@
7268
});
7369
}
7470
75-
function onClickCompany(company) {
71+
function onClickCompany(company: CompanyWithSelected) {
7672
if (!isFocusView) {
7773
companies = companies.map((c) => {
7874
if (c.name === company.name) {
@@ -91,7 +87,6 @@
9187
}
9288
9389
// Filter
94-
$: allSelected = companies.reduce((selected, company) => selected && company.selected, true);
9590
$: allDeselected = companies.reduce(
9691
(deselected, company) => deselected && !company.selected,
9792
true
@@ -101,7 +96,7 @@
10196
.filter((company) => company.selected)
10297
.map((company) => company.name);
10398
104-
function toggleScope(scope) {
99+
function toggleScope(scope: number) {
105100
if (selectedScopes.length === 1 && selectedScopes[0] === scope) return;
106101
const index = selectedScopes.indexOf(scope);
107102
if (index === -1) {
@@ -112,8 +107,9 @@
112107
}
113108
}
114109
115-
function handleGlossaryButtonClick(event) {
116-
const term = event.target.dataset.term;
110+
function handleGlossaryButtonClick(event: MouseEvent) {
111+
const target = event.target as HTMLElement;
112+
const term = target.dataset.term;
117113
if (term) {
118114
$glossaryItem = term;
119115
}
@@ -135,7 +131,7 @@
135131
{selectedSector === sector.name
136132
? 'text-black bg-gray-300 '
137133
: 'text-gray-700 dark:text-gray-700 bg-gray-100 dark:bg-gray-500 '}"
138-
aria-label={sector}
134+
aria-label={sector.name}
139135
title={sector.name}
140136
on:click={() => {
141137
if (selectedSector === sector.name) {
@@ -146,8 +142,8 @@
146142
}}
147143
>
148144
<img
149-
src="https://base.klimadashboard.org/assets/{sector.icon}"
150-
alt="Energy"
145+
src={`https://base.klimadashboard.org/assets/${sector.icon}`}
146+
alt={sector.name}
151147
height="60"
152148
class="h-4"
153149
/>
@@ -189,11 +185,11 @@
189185
class="{isFocusView
190186
? 'bg-agriculture'
191187
: 'bg-energy'} h-3 w-3 inline-block rounded-full mr-1"
192-
/>
188+
></span>
193189
{isFocusView ? 'Mehrfachauswahl: ein' : 'Mehrfachauswahl: aus'}
194190
</button>
195191
</div>
196-
<div class="ml-auto" />
192+
<div class="ml-auto"></div>
197193
</div>
198194
<!-- Companies -->
199195
<div class="flex flex-wrap gap-2 mb-4">
@@ -209,13 +205,13 @@
209205
>
210206
<img
211207
src="https://base.klimadashboard.org/assets/{company.sectorIconIds[0]}"
212-
alt="Energy"
208+
alt={company.sectors.join(', ')}
213209
height="60"
214210
class="h-4"
215211
/>
216212
<img
217213
src="https://base.klimadashboard.org/assets/{company.logoId}"
218-
alt={company.logo}
214+
alt={company.name}
219215
width="60"
220216
height="60"
221217
class="inline-block h-6 object-contain"
@@ -245,7 +241,7 @@
245241
{selectedScopes.includes(scope)
246242
? 'text-black bg-gray-100 border-2 border-green-600'
247243
: 'text-gray-600 bg-gray-100 border-2 border-gray-100'}"
248-
aria-label={scope}
244+
aria-label={`Scope ${scope}`}
249245
on:click={() => toggleScope(scope)}
250246
>
251247
<span class="font-semibold tracking-wide">Scope {scope}</span>

src/lib/components/charts/custom/companiesEmissions/CompanyEmissionsLineChart.svelte

Lines changed: 30 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,47 @@
1-
<script>
2-
// @ts-nocheck
1+
<script lang="ts">
32
import LineChart from '$lib/components/charts/chartLine.svelte';
4-
import { EMISSION_SCOPE_KEYS } from './constants';
53
import { transformDataSingleCompany, transformDataMultipleCompanies } from './transformData';
4+
import type { CompanyEmissionArray, CompanyMetaData } from './types';
65
7-
export let emissions;
8-
export let selectedCompanies;
9-
export let selectedScopes;
10-
export let selectedScope2Category = 'location_based';
6+
export let emissions: CompanyEmissionArray;
7+
export let selectedCompanies: CompanyMetaData[];
8+
export let selectedScopes: number[];
9+
export let selectedScope2Category: string = 'location_based';
1110
12-
let isScopeThreeSelected;
11+
let isScopeThreeSelected: boolean;
1312
$: isScopeThreeSelected = selectedScopes.includes(3);
1413
15-
let isSingleCompanySelected;
16-
let selectedCompanyNames;
14+
let isSingleCompanySelected: boolean;
15+
let selectedCompanyNames: string[];
1716
$: isSingleCompanySelected = selectedCompanies.length === 1;
1817
$: selectedCompanyNames = [...selectedCompanies].map((company) => company.name);
1918
20-
const rawColors = ['#7CBAB3', '#575C75', '#71665B', '#B28834', '#8CAED9', '#E0A906', '#CF6317'];
21-
const selectedScopesToColors = {
19+
const rawColors: string[] = [
20+
'#7CBAB3',
21+
'#575C75',
22+
'#71665B',
23+
'#B28834',
24+
'#8CAED9',
25+
'#E0A906',
26+
'#CF6317'
27+
];
28+
const selectedScopesToColors: Record<number, string> = {
2229
1: '#4e79a7',
2330
2: '#f28e2c',
2431
3: '#e15759'
2532
};
2633
27-
const selectedScopesToLabels = {
34+
const selectedScopesToLabels: Record<number, string> = {
2835
1: 'Scope 1',
2936
2: 'Scope 2',
3037
3: 'Scope 3'
3138
};
3239
const maxCompanies = 7;
3340
34-
// // Magazine Visuation Companies & Colors
35-
// const rawColors = [
36-
// '#19A6E2',
37-
// '#08779A',
38-
// '#910505',
39-
// '#000000',
40-
// '#036041',
41-
// '#31B159',
42-
// '#F2380F',
43-
// '#0F469A',
44-
// '#6787A6'
45-
// ];
46-
// selectedCompanyNames = [
47-
// 'Voestalpine AG',
48-
// 'OMV AG',
49-
// 'Wienerberger AG',
50-
// 'EVN AG',
51-
// 'Mayr-Melnhof Karton AG',
52-
// 'Lenzing AG',
53-
// 'STRABAG SE',
54-
// 'Verbund AG',
55-
// 'Austria Technologie & Systemtechnik AG'
56-
// ];
57-
58-
let dataset = [];
59-
let keys;
60-
let labels;
61-
let colors;
41+
let dataset: Array<Record<string, any>> = [];
42+
let keys: number[] | string[];
43+
let labels: string[];
44+
let colors: string[];
6245
$: {
6346
if (emissions && selectedCompanies && selectedScopes) {
6447
if (isSingleCompanySelected) {
@@ -115,13 +98,16 @@
11598
</p>
11699
{/if}
117100
{:else if selectedCompanies.length === 0}
118-
<div class="h-28"></div>
101+
<div class="h-20"></div>
119102
<p class="text-center">Keine Unternehmen ausgewählt.</p>
120103
<p class="text-center">⬆ Wähle oben bis zu sieben Unternehmen aus! ⬆</p>
104+
<div class="h-20"></div>
121105
{:else if selectedCompanies.length > maxCompanies}
122-
<div class="h-28"></div>
106+
<div class="h-20"></div>
123107
<p class="text-center">Zu viele Unternehmen ausgewählt. Wähle maximal 7 Unternehmen.</p>
108+
<div class="h-20"></div>
124109
{:else}
125-
<div class="h-28"></div>
110+
<div class="h-20"></div>
126111
<p class="text-center">Laden...</p>
112+
<div class="h-20"></div>
127113
{/if}

src/lib/components/charts/custom/companiesEmissions/DataDownload.svelte

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
<script>
1+
<script lang="ts">
22
import { page } from '$app/state';
3+
import type { CompanyEmission, CompanyEmissionArray } from './types';
34
4-
export let data;
5+
export let data: CompanyEmissionArray;
56
6-
function escapeCSVValue(value) {
7+
function escapeCSVValue(value: string | number | null | undefined) {
78
if (typeof value === 'string') {
89
// Escape double quotes by doubling them
910
const escaped = value.replace(/"/g, '""');
@@ -23,7 +24,7 @@
2324
return;
2425
}
2526
26-
const headers = Object.keys(data[0]);
27+
const headers = Object.keys(data[0]) as (keyof CompanyEmission)[];
2728
const rows = data.map((row) => headers.map((header) => escapeCSVValue(row[header])).join(','));
2829
const csvContent = [headers.join(','), ...rows].join('\n');
2930

src/lib/components/charts/custom/companiesEmissions/constants.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/lib/components/charts/custom/companiesEmissions/getData.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import getDirectusInstance from '$lib/utils/directus';
22
import { readItems } from '@directus/sdk';
33
import { flattenCompanies } from './utils';
4+
import type { Company, CompanyEmissionArray } from './types';
45

56
// NOTE: Use these filters to filter directly via the API call,
67
// instead of fetching all data and filtering client side:
@@ -17,11 +18,10 @@ export const getCompanyEmissionData = async () => {
1718
const data = await directus.request(
1819
readItems('companies_emissions', {
1920
fields: ['year', 'company', 'scope', 'value', 'category', 'source'],
20-
2121
limit: -1
2222
})
2323
);
24-
return data;
24+
return data as CompanyEmissionArray;
2525
};
2626

2727
export const getCompanyMetaData = async () => {
@@ -41,7 +41,11 @@ export const getCompanyMetaData = async () => {
4141
limit: -1
4242
})
4343
);
44-
return flattenCompanies(data);
44+
45+
// Flatten data for easier usage in the chart components
46+
const flattenedData = flattenCompanies(data as Company[]);
47+
48+
return flattenedData;
4549
};
4650

4751
export const getAllSectors = async () => {

src/lib/components/charts/custom/companiesEmissions/index.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<script>
1+
<script lang="ts">
22
import CompanyEmissionsContainer from './CompanyEmissionsContainer.svelte';
33
import { getCompanyMetaData } from './getData';
44

0 commit comments

Comments
 (0)