Skip to content

Commit

Permalink
Add summary table
Browse files Browse the repository at this point in the history
  • Loading branch information
balagurova committed Jul 9, 2024
1 parent 6ced6c2 commit 255c3e8
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { PROGRAMMES } from './Components/Constants';
import { ProgrammeProvider, useProgramme } from './Components/ProgrammeContext';
import CheckboxGroup from './Components/CheckboxGroup';
import { ChoroplethMapDataType } from './Types';
import Table from './Components/Table';
import Summary from './Components/Summary';

function AppContent() {
const [data, setData] = useState<any[]>([]);
Expand Down Expand Up @@ -74,18 +76,33 @@ function AppContent() {
}));
};

const calculateTotals = (rawData: any[], programmes: typeof PROGRAMMES) => {
const totals: { [key: string]: { label: string; total: number } } = {};
programmes.forEach(programme => {
totals[programme.value] = {
label: programme.short,
total: rawData.reduce((sum, item) => {
return sum + (item[programme.value] === '1' ? 1 : 0);
}, 0),
};
});
return totals;
};

const transformedData = transformData(
data,
currentProgramme.value,
selectedRadio,
);

const programmeTotals = calculateTotals(data, PROGRAMMES);

return (
<div className='undp-container flex-div gap-06 flex-wrap flex-hor-align-center padding-04'>
<Header onSegmentChange={handleSegmentChange} />
<div className='flex-div flex-row' style={{ width: '100%' }}>
<div
className='flex-div flex-column gap-03 grow'
className='flex-div flex-column flex-space-between gap-03 grow'
style={{
width: 'calc(20% - 54px)',
}}
Expand All @@ -106,6 +123,7 @@ function AppContent() {
value={selectedCheckboxes}
/>
)}
<Summary totals={programmeTotals} />
</div>
<div
className='flex-div flex-column grow'
Expand All @@ -122,6 +140,7 @@ function AppContent() {
/>
</div>
</div>
<Table data={transformedData} />
</div>
);
}
Expand Down
6 changes: 6 additions & 0 deletions src/Components/Constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Leaf, School, BriefcaseBusiness, Flag, Shell } from 'lucide-react';

// constants.ts
export interface Programme {
[x: string]: any;
label: string;
value: string;
color: string;
Expand All @@ -17,12 +18,14 @@ export interface Subcategory {
export const PROGRAMMES: Programme[] = [
{
label: 'All Sustainable Financial Programmes',
short: 'All Programmes',
value: 'all_programmes',
color: '#006EB5',
icon: Leaf,
},
{
label: 'Public finance for the SDGs',
short: 'Public finance for the SDGs',
value: 'public',
color: '#5DD4F0',
icon: School,
Expand All @@ -33,6 +36,7 @@ export const PROGRAMMES: Programme[] = [
},
{
label: 'Unlocking private capital and aligning for the SDGs',
short: 'Unlocking private capital',
value: 'private',
color: '#02A38A',
icon: BriefcaseBusiness,
Expand All @@ -43,12 +47,14 @@ export const PROGRAMMES: Programme[] = [
},
{
label: 'Integrated National Financing Frameworks',
short: 'Integrated National Frameworks',
value: 'frameworks',
color: '#E78625',
icon: Flag,
},
{
label: 'Biofin',
short: 'Biofin',
value: 'biofin',
color: '#E0529E',
icon: Shell,
Expand Down
57 changes: 57 additions & 0 deletions src/Components/Summary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import styled from 'styled-components';

const TableContainer = styled.div`
.programme-totals-table-row {
display: flex;
justify-content: space-between;
border-bottom: 0.06rem solid var(--gray-400);
}
.first-data-point {
border-bottom: 0.06rem solid var(--gray-400);
}
`;

interface ProgrammeTotalsTableProps {
totals: {
[key: string]: {
label: string;
total: number;
};
};
}

function Summary(props: ProgrammeTotalsTableProps): JSX.Element {
const { totals } = props;
const totalEntries = Object.values(totals);
return (
<div className='programme-totals-table'>
<TableContainer>
<div className='first-data-point'>
<p className='label padding-bottom-02 margin-bottom-00'>
{totalEntries[0].label}
</p>
<h3
className='undp-typograhy total margin-00 padding-bottom-04'
style={{ fontWeight: '600' }}
>
{totalEntries[0].total}
</h3>
</div>
<div className='programme-totals-table'>
{totalEntries.slice(1).map(({ label, total }) => (
<div
key={label}
className='programme-totals-table-row padding-bottom-03 padding-top-03'
>
<div className='label margin-bottom-00'>{label}</div>
<div className='total bold label margin-bottom-00'>{total}</div>
</div>
))}
</div>
</TableContainer>
</div>
);
}

export default Summary;
88 changes: 88 additions & 0 deletions src/Components/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Check, Search } from 'lucide-react';
import React, { useState } from 'react';
import { Input } from 'antd';
import { ChoroplethMapDataType } from '../Types';
import { PROGRAMMES } from './Constants';

interface Props {
data: ChoroplethMapDataType[];
}

function Table(props: Props) {
const { data } = props;
const [searchTerm, setSearchTerm] = useState('');

const filteredData = data.filter((rowData: ChoroplethMapDataType) =>
rowData.data.country.toLowerCase().includes(searchTerm.toLowerCase()),
);

return (
<div className='margin-top-03'>
<Input
placeholder='Search by country'
className='undp-input'
prefix={<Search size={18} strokeWidth={2.5} color='var(--black)' />}
onChange={e => setSearchTerm(e.target.value)}
style={{ width: '100%' }}
/>
<div
className='undp-container margin-top-04 undp-scrollbar'
style={{
width: '100%',
height: '500px',
}}
>
<div
className='undp-table-head-small'
style={{
position: 'sticky',
top: '0',
zIndex: '1',
}}
>
<div
style={{ width: '25%' }}
className='undp-table-head-cell undp-sticky-head-column'
>
<div className='padding-left-05 padding-right-05'>Country Name</div>
</div>
{PROGRAMMES.map(field => (
<div
key={field.label}
style={{ width: '15%' }}
className='undp-table-head-cell undp-sticky-head-column'
>
<div className='padding-left-05 padding-right-05 flex-div flex-hor-align-center'>
{field.label}
</div>
</div>
))}
</div>
{filteredData.map((rowData, index) => (
<div key={index} className='undp-table-row'>
<div style={{ width: '25%' }} className='undp-table-row-cell-small'>
<div className='padding-left-05 padding-right-05'>
{rowData.data.country}
</div>
</div>
{PROGRAMMES.map(field => (
<div
key={field.value}
style={{ width: '15%' }}
className='undp-table-row-cell-small'
>
<div className='padding-left-05 padding-right-05 padding-top-02 flex-div flex-vert-align-center flex-hor-align-center'>
{rowData.data[field.value] === '1' ? (
<Check size={18} strokeWidth={3} color='var(--blue-600)' />
) : null}
</div>
</div>
))}
</div>
))}
</div>
</div>
);
}

export default Table;

0 comments on commit 255c3e8

Please sign in to comment.