Skip to content

Commit

Permalink
Merge pull request #148 from Vizzuality/fix/project_45
Browse files Browse the repository at this point in the history
Fix/project 45
  • Loading branch information
mluena authored Dec 20, 2024
2 parents add086e + 68859d9 commit 2265155
Show file tree
Hide file tree
Showing 28 changed files with 664 additions and 491 deletions.
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"cmdk": "0.2.1",
"country-iso-3-to-2": "^1.1.1",
"d3-array": "3.2.4",
"deck.gl": "8.9.19",
"eslint": "8.42.0",
Expand All @@ -67,7 +68,6 @@
"react-map-gl": "7.0.25",
"react-markdown": "9.0.1",
"react-share": "5.1.0",
"react-world-flags": "1.6.0",
"recharts": "2.12.1",
"remark-gfm": "4.0.0",
"rooks": "7.14.1",
Expand Down
44 changes: 44 additions & 0 deletions client/src/components/flag/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Image from 'next/image';

const DEFAULT_CDN_URL = 'https://cdn.jsdelivr.net/gh/lipis/flag-icons/flags/4x3/';
const DEFAULT_CDN_SUFFIX = 'svg';

interface ImgProps extends React.ImgHTMLAttributes<HTMLImageElement> {
cdnSuffix?: string;
cdnUrl?: string;
countryCode: string;
width?: number;
height?: number;
svg?: true;
}

export type CountryFlagProps = ImgProps;

export const CountryFlag = ({
cdnSuffix = DEFAULT_CDN_SUFFIX,
cdnUrl = DEFAULT_CDN_URL,
countryCode,
height = 26.66,
width = 40,
svg = true,
className,
}: CountryFlagProps) => {
if (typeof countryCode !== 'string') {
return null;
}
if (svg) {
const flagUrl = `${cdnUrl}${countryCode.toLowerCase()}.${cdnSuffix}`;

return (
<Image
alt={'Flag of ' + countryCode}
src={flagUrl}
width={width}
height={height}
className={className}
/>
);
}
};

export default CountryFlag;
2 changes: 2 additions & 0 deletions client/src/containers/countries/detail/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export const COLUMNS = [
'forest_area_pct',
'intervention_area_total',
'jobs',
'total_trainings',
'trainees',
'jobs_total',
'net_flux_co2e_year',
'production_ntfp_total',
Expand Down
43 changes: 25 additions & 18 deletions client/src/containers/countries/detail/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import { useEffect } from 'react';

import Markdown from 'react-markdown';
import Flag from 'react-world-flags';

import Image from 'next/image';
import Link from 'next/link';
import { notFound, useParams } from 'next/navigation';

import getCountryIso2 from 'country-iso-3-to-2';
import { useSetAtom } from 'jotai';
import { X } from 'lucide-react';
import { ArrowLeft, Download, ExternalLink, Info } from 'lucide-react';
Expand Down Expand Up @@ -37,6 +37,7 @@ import { usefulLinksCountry } from '@/containers/countries/detail/constants';
import { COLUMNS, CSV_COLUMNS_ORDER } from '@/containers/countries/detail/constants';
import Share from '@/containers/share';

import CountryFlag from '@/components/flag';
import { Button } from '@/components/ui/button';
import { Dialog, DialogClose, DialogContent, DialogTrigger } from '@/components/ui/dialog';
import ContentLoader from '@/components/ui/loader';
Expand Down Expand Up @@ -195,11 +196,13 @@ export default function CountryDetailPanel() {
<ScrollArea className="h-full px-5">
<div className="mt-16 flex items-center space-x-3 pt-7">
{data?.data?.attributes?.iso && (
<Flag
code={data?.data?.attributes.iso}
height="40"
width="48"
<CountryFlag
alt={data.data?.attributes.iso}
countryCode={getCountryIso2(data.data?.attributes.iso || '') || ''}
key={`${data.data?.attributes.iso}`}
className="rounded"
width={48}
height={32}
/>
)}
<h2 className="text-xl" data-cy="country-detail-name">
Expand All @@ -220,11 +223,13 @@ export default function CountryDetailPanel() {
<div className="flex flex-col space-y-8 px-4">
<div className="mt-4 flex space-x-2">
{data?.data?.attributes?.iso && (
<Flag
code={data?.data?.attributes.iso}
height="32"
width="40"
<CountryFlag
alt={data.data?.attributes.iso}
countryCode={getCountryIso2(data.data?.attributes.iso || '') || ''}
key={`${data.data?.attributes.iso}`}
className="rounded"
width={48}
height={32}
/>
)}
<p>{data?.data?.attributes?.name}</p>
Expand Down Expand Up @@ -435,7 +440,7 @@ export default function CountryDetailPanel() {
</div>
<div className="w-full rounded-xl bg-white p-4 shadow-sm">
<div className="flex items-center justify-between pb-2">
<h3 className="text-base text-green-800">Total jobs</h3>
<h3 className="text-base text-green-800">Total trainings</h3>
<Tooltip delayDuration={200}>
<TooltipTrigger className="flex items-center justify-center rounded-full p-2 hover:bg-yellow-50 data-[state=open]:bg-yellow-50">
<Info className="text-green-800" size={20} />
Expand All @@ -444,24 +449,26 @@ export default function CountryDetailPanel() {
<TooltipContent className="max-w-[200px] p-2">
<p className="text-sm text-yellow-900">
<Markdown remarkPlugins={[remarkGfm]} className="prose text-xs">
The total number of short- and long-term jobs generated by the
project interventions in the AFoCO Member Countries.
The total number of training activities conducted and participants
in the AFoCO Member Countries.
</Markdown>
</p>
</TooltipContent>
</Tooltip>
</div>

<p className="py-4 text-3xl font-extrabold">
{formatCompactNumber(indicators.jobs_total['value'])}
{formatCompactNumber(indicators.trainings_total['value'])}
</p>
{indicators.jobs && (
{indicators.trainees && (
<div className="h-44">
<BarsChart
data={Object.entries(indicators.jobs['value']).map(([year, uv]) => ({
year,
uv,
}))}
data={Object.entries(indicators.trainees['value']).map(
([year, uv]) => ({
year,
uv,
})
)}
barDataKey="uv"
barRadius={[20, 20, 20, 20]}
fillBar="#70B6CC"
Expand Down
16 changes: 13 additions & 3 deletions client/src/containers/countries/item.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
'use client';

import Flag from 'react-world-flags';

import Link from 'next/link';

import getCountryIso2 from 'country-iso-3-to-2';

import { useGetCountryIndicatorFields } from '@/types/generated/country-indicator-field';
import { CountryListResponseDataItem } from '@/types/generated/strapi.schemas';

import { useSyncQueryParams } from '@/hooks/datasets';

import CountryFlag from '@/components/flag';

export default function CountryItem({ data }: { data: CountryListResponseDataItem }) {
const queryParams = useSyncQueryParams({ bbox: true });

Expand All @@ -35,7 +37,15 @@ export default function CountryItem({ data }: { data: CountryListResponseDataIte
>
<div className="flex items-center space-x-4">
{data.attributes?.iso && (
<Flag code={data.attributes.iso} height="32" width="40" className="rounded" />
<CountryFlag
alt={data.attributes.iso}
countryCode={getCountryIso2(data.attributes.iso || '') || ''}
key={`${data.attributes.iso}`}
className="rounded"
style={{
fontSize: '3em',
}}
/>
)}

<h3>{data.attributes?.name}</h3>
Expand Down
4 changes: 2 additions & 2 deletions client/src/containers/countries/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
// import { useState } from 'react';

// import { Search, X } from 'lucide-react';
import { ExternalLink } from 'lucide-react';

import { useGetCountries } from '@/types/generated/country';

import CountryItem from '@/containers/countries/item';
import { usefulLinksCountriesList } from '@/containers/countries/detail/constants';
import CountryItem from '@/containers/countries/item';

// import { Input } from '@/components/ui/input';
import ContentLoader from '@/components/ui/loader';
import { ScrollArea } from '@/components/ui/scroll-area';
import { ExternalLink } from 'lucide-react';

export default function CountriesList() {
// const [searchValue, setSearchValue] = useState<string | null>(null);
Expand Down
64 changes: 48 additions & 16 deletions client/src/containers/datasets/layers/projects/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,21 @@ export function useLayers({

// Reactivity to Hover Events in the Sidebar:
// Similarly, When a user hovers over the a project in the sidebar, both point and geometry representations within the layer are programmed to change in color and/or size.

const sanitizedProjects = filteredProjects.filter((project) => project !== null);

const filter =
sanitizedProjects.length > 0
? ['in', ['get', 'project_code'], ['literal', sanitizedProjects]]
: ['!=', ['get', 'project_code'], null];

return [
{
id: 'projects_points_shadow',
type: 'circle',
filter: ['in', ['get', 'project_code'], ['literal', filteredProjects]],
filter,
source: 'projects',
'source-layer': 'areas_centroids_c',
'source-layer': 'areas_centroids_c_v202410',
paint: {
'circle-radius': 16,
'circle-color': '#ccc',
Expand All @@ -163,18 +171,18 @@ export function useLayers({
{
id: 'projects_circle',
type: 'circle',
filter: ['in', ['get', 'project_code'], ['literal', filteredProjects]],
filter,
source: 'projects',
'source-layer': 'areas_centroids_c',
'source-layer': 'areas_centroids_c_v202410',
paint: {
'circle-stroke-color': '#ffffff',
'circle-stroke-width': [
'case',
['boolean', ['feature-state', 'hover'], false],
3,
['==', ['get', 'project_code'], hoveredProject],
['==', ['get', 'project_code'], hoveredProject?.[0] || null],
7,
['!=', ['get', 'project_code'], hoveredProject],
['!=', ['get', 'project_code'], hoveredProject?.[0] || null],
3,
7,
],
Expand All @@ -193,19 +201,35 @@ export function useLayers({
'case',
['boolean', ['feature-state', 'hover'], false],
1,
['all', ['to-boolean', hoveredProject], ['!=', ['get', 'project_code'], hoveredProject]],
[
'all',
['to-boolean', hoveredProject?.[0] || null],
['!=', ['get', 'project_code'], hoveredProject?.[0] || null],
],
0.2,
['all', ['to-boolean', hoveredProject], ['==', ['get', 'project_code'], hoveredProject]],
[
'all',
['to-boolean', hoveredProject?.[0] || null],
['==', ['get', 'project_code'], hoveredProject?.[0] || null],
],
1,
opacity,
],
'circle-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1,
['all', ['to-boolean', hoveredProject], ['!=', ['get', 'project_code'], hoveredProject]],
[
'all',
['to-boolean', hoveredProject?.[0] || null],
['!=', ['get', 'project_code'], hoveredProject?.[0] || null],
],
0.2,
['all', ['to-boolean', hoveredProject], ['==', ['get', 'project_code'], hoveredProject]],
[
'all',
['to-boolean', hoveredProject?.[0] || null],
['==', ['get', 'project_code'], hoveredProject?.[0] || null],
],
1,
opacity,
],
Expand All @@ -218,18 +242,26 @@ export function useLayers({
{
id: 'projects_fill',
type: 'fill',
filter: ['in', ['get', 'project_code'], ['literal', filteredProjects]],
filter,
source: 'projects',
'source-layer': 'areas_centroids_l',
'source-layer': 'areas_centroids_l_v202410',
paint: {
'fill-color': '#176252',
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
0.7,
['all', ['to-boolean', hoveredProject], ['!=', ['get', 'project_code'], hoveredProject]],
[
'all',
['to-boolean', hoveredProject?.[0] || null],
['!=', ['get', 'project_code'], hoveredProject?.[0] || null],
],
0.2,
['all', ['to-boolean', hoveredProject], ['==', ['get', 'project_code'], hoveredProject]],
[
'all',
['to-boolean', hoveredProject?.[0] || null],
['==', ['get', 'project_code'], hoveredProject?.[0] || null],
],
0.7,
opacity * 0.7,
],
Expand All @@ -242,9 +274,9 @@ export function useLayers({
{
id: 'projects_line',
type: 'line',
filter: ['in', ['get', 'project_code'], ['literal', filteredProjects]],
filter,
source: 'projects',
'source-layer': 'areas_centroids_l',
'source-layer': 'areas_centroids_l_v202410',
paint: {
'line-color': '#B45F06',
'line-opacity': opacity,
Expand Down
2 changes: 1 addition & 1 deletion client/src/containers/datasets/layers/projects/layer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useLayers } from './hooks';
const SOURCE: SourceProps = {
promoteId: 'project_code',
type: 'vector',
url: 'mapbox://afoco.25x9bxct',
url: 'mapbox://afoco.06cjgob1',
id: 'projects',
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const TreeCoverLossSettings: React.FC<TreeCoverLossSettings> = ({
description,
startYear: startYearValue,
endYear: endYearValue,
paramsConfig,
onChangeSettings,
}) => {
// const startYear = useMemo(
Expand Down
2 changes: 1 addition & 1 deletion client/src/containers/filters/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function Filters({ nrResults = 0 }: { nrResults: number }) {
Clear all
</button>
<DialogClose>
<Button variant="primary" size="base" onClick={close}>
<Button variant="primary" size="base">
<p>
Show <span className="font-bold"> {nrResults} </span> results
</p>
Expand Down
Loading

0 comments on commit 2265155

Please sign in to comment.