Skip to content

Commit

Permalink
Add alert map details
Browse files Browse the repository at this point in the history
  • Loading branch information
barshathakuri committed Apr 2, 2024
1 parent e9d781b commit b21ef43
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 145 deletions.
2 changes: 1 addition & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import App from './App';
const webappRootId = 'webapp-root';

const webappRootElement = document.getElementById(webappRootId);
const APP_GRAPHQL_ENDPOINT= "http://localhost:8000/graphql/";
const APP_GRAPHQL_ENDPOINT = 'http://localhost:8000/graphql/';

const client = new ApolloClient({
uri: APP_GRAPHQL_ENDPOINT,
Expand Down
8 changes: 6 additions & 2 deletions src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ export const DURATION_MAP_ZOOM = 1000;
export const DEFAULT_MAP_PADDING = 50;

// Colors

export const COLOR_LIGHT_GREY = '#e0e0e0';
export const COLOR_RED = '#f5333f';
export const COLOR_PRIMARY_RED = '#f5333f';
export const COLOR_WHITE = '#ffffff';
export const COLOR_TEXT = '#313131';
export const COLOR_PRIMARY_RED = '#f5333f';
export const COLOR_TEXT_ON_DARK = COLOR_WHITE;
export const COLOR_DARK_GREY = '#a5a5a5';
export const COLOR_BLACK = '#000000';
6 changes: 6 additions & 0 deletions src/views/AlertMap/AlertDetail/i18n.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"namespace": "alertDetails",
"strings": {
"alertViewDetails": "View Details"
}
}
50 changes: 50 additions & 0 deletions src/views/AlertMap/AlertDetail/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ChevronRightLineIcon } from '@ifrc-go/icons';
import {
Button,
Container,
} from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';

import { AlertsInfoQuery } from '#generated/types';

Check failure on line 8 in src/views/AlertMap/AlertDetail/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Cannot find module '#generated/types' or its corresponding type declarations.

Check failure on line 8 in src/views/AlertMap/AlertDetail/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

Unable to resolve path to module '#generated/types'

import i18n from './i18n.json';
import styles from './styles.module.css';

type Alert = NonNullable<NonNullable<NonNullable<AlertsInfoQuery['public']>['alerts']>['items']>[number];

export interface Props {
data: Alert;
onExpandClick: (alertId: string | undefined) => void;
}

function AlertDetail(props: Props) {
const {
data,
onExpandClick,
} = props;

const strings = useTranslation(i18n);

return (
<Container
className={styles.alertInfo}
heading={data?.country.name ?? '--'}
headerClassName={styles.alertListItem}
headingLevel={5}
key={data.countryId}
headerDescription={data.infos.map((alert) => alert.event)}

Check failure on line 35 in src/views/AlertMap/AlertDetail/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Parameter 'alert' implicitly has an 'any' type.
actions={(
<Button
name={data.countryId}
onClick={onExpandClick}
variant="tertiary"
title={strings.alertViewDetails}
>
<ChevronRightLineIcon className={styles.icon} />
</Button>
)}
/>
);
}

export default AlertDetail;
32 changes: 32 additions & 0 deletions src/views/AlertMap/AlertDetail/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.alert-info {
.alert-list-item {
gap: 0;

.icon {
align-self: flex-end;
font-size: var(--go-ui-height-icon-multiplier);
}:hover {
.icon {
animation: wiggle var(--go-ui-duration-transition-slow) ease-in-out;
}
}
}

@keyframes wiggle {
0% {
transform: translateX(0);
}

25% {
transform: translateX(-0.1rem);
}

50% {
transform: translateX(0.1rem);
}

100% {
transform: translateX(0);
}
}
}
5 changes: 4 additions & 1 deletion src/views/AlertMap/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
"namespace": "ongoingAlertMap",
"strings": {
"mapHeading": "All Ongoing Alerts",
"mapViewAllSources": "View All Sources"
"mapViewAllSources": "View All Sources",
"ongoingAlertCountries": "Ongoing Alert Countries",
"backToAlertsLabel": "Back to Alerts",
"alertViewDetails": "View Details"
}
}
148 changes: 94 additions & 54 deletions src/views/AlertMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,49 @@ import {
useState,
} from 'react';
import { Link } from 'react-router-dom';
import type { LngLatBoundsLike, FillLayer } from 'mapbox-gl';
import {
gql,
useQuery,
} from '@apollo/client';
import { Container } from '@ifrc-go/ui';
import { ChevronLeftLineIcon } from '@ifrc-go/icons';
import {
BlockLoading,
Button,
Container,
List,
} from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';
import {
_cs,
isDefined,
isNotDefined,
listToGroupList,
unique,
} from '@togglecorp/fujs';
import {
MapBounds,
MapContainer,
MapLayer,
} from '@togglecorp/re-map';
import type {
FillLayer,
LngLatBoundsLike,
} from 'mapbox-gl';

import MapPopup from '#components/MapPopup';
import BaseMap from '#components/domain/BaseMap';
import MapPopup from '#components/MapPopup';
import {
AlertsInfoQuery,
AlertsInfoQueryVariables,
CountryInfoQuery,
CountryInfoQueryVariables,
} from '#generated/types';

Check failure on line 40 in src/views/AlertMap/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Cannot find module '#generated/types' or its corresponding type declarations.

Check failure on line 40 in src/views/AlertMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

Unable to resolve path to module '#generated/types'
import {

Check failure on line 41 in src/views/AlertMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

`#utils/constants` import should occur before import of `#generated/types`
COLOR_LIGHT_GREY,
COLOR_PRIMARY_RED,
DEFAULT_MAP_PADDING,
DURATION_MAP_ZOOM,
} from '#utils/constants';

import AlertDetail from './AlertDetail';

import i18n from './i18n.json';
import styles from './styles.module.css';

Expand All @@ -44,6 +55,7 @@ query AlertsInfo {
public {
alerts {
items {
id
addresses
country {
centroid
Expand Down Expand Up @@ -116,70 +128,40 @@ query AlertsInfo {
}
`;

const COUNTRY_INFO = gql`
query CountryInfo {
public {
countries {
items {
iso3
id
centroid
continent {
id
name
}
continentId
name
region {
id
name
centroid
}
regionId
}
limit
offset
}
}
}
`;
type AlertType = NonNullable<NonNullable<NonNullable<AlertsInfoQuery['public']>['alerts']>['items']>[number];

type Props = {
className?: string;
alertId: string;
bbox: LngLatBoundsLike | undefined;
onActiveCountryChange: (countryId: | undefined) => void;
}

const sourceOptions: mapboxgl.GeoJSONSourceRaw = {
type: 'geojson',
};
const keySelector = (alert: AlertType) => alert?.id;

interface ClickedPoint {
feature: GeoJSON.Feature<GeoJSON.Point, AlertsInfoQueryVariables>;
lngLat: mapboxgl.LngLatLike;
}

function OngoingAlertMap(props: Props) {
function OngoingAlertMap<
KEY extends string | number
>(props: Props) {
const {
className,
bbox,
alertId,
onActiveCountryChange,
} = props;

const strings = useTranslation(i18n);
const [activeCountryId, setActiveCountryId] = useState<KEY | undefined>(undefined);

const {
data: alertsResponse,
loading: alertLoading,
} = useQuery<AlertsInfoQuery, AlertsInfoQueryVariables>(
ALERTS_INFO,
);

const {
data: countryResponse,
} = useQuery<CountryInfoQuery, CountryInfoQueryVariables>(
COUNTRY_INFO,
);

const [
clickedPointProperties,
setClickedPointProperties,
Expand All @@ -192,6 +174,24 @@ function OngoingAlertMap(props: Props) {
[setClickedPointProperties],
);

const setActiveAlertIdSafe = useCallback(
(countryId: string | number | undefined) => {
const countryIdSafe = countryId as undefined;

setActiveCountryId(countryIdSafe);
onActiveCountryChange(countryIdSafe);
},
[onActiveCountryChange],
);

const eventListRendererParams = useCallback(
(_: string | number, alert: AlertType) => ({
data: alert,
onExpandClick: setActiveAlertIdSafe,
}),
[setActiveAlertIdSafe],
);

const handleCountryClick = useCallback((
feature: mapboxgl.MapboxGeoJSONFeature,
lngLat: mapboxgl.LngLatLike,
Expand All @@ -212,7 +212,11 @@ function OngoingAlertMap(props: Props) {
},
};
}
const uniqueCountries = unique(alertsResponse.public.alerts.items, (item) => item.country.iso3);
const uniqueCountries = unique(
alertsResponse.public.alerts.items,
(item) => item.country.iso3,

Check failure on line 217 in src/views/AlertMap/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

'item' is of type 'unknown'.
);

return {
type: 'fill',
paint: {
Expand All @@ -223,27 +227,26 @@ function OngoingAlertMap(props: Props) {
...uniqueCountries.flatMap(

Check failure on line 227 in src/views/AlertMap/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

'uniqueCountries' is possibly 'undefined'.
(alert) => [

Check failure on line 228 in src/views/AlertMap/index.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Parameter 'alert' implicitly has an 'any' type.
alert.country.iso3.toUpperCase(),
'#ff0000',
COLOR_PRIMARY_RED,
],
),
'#e0e0e0',
COLOR_LIGHT_GREY,
],
},
layout: {
visibility: 'visible',
},
};
}, [alertsResponse?.public.alerts.items]);

console.info('country', alertsResponse);
}, [alertsResponse]);

return (
<Container
className={_cs(styles.alertMap, className)}
heading={strings.mapHeading}
withHeaderBorder
childrenContainerClassName={styles.content}
childrenContainerClassName={styles.mainContent}
actions={(
// TODO: Add sources link
<Link
className={styles.sources}
to="/"
Expand All @@ -269,10 +272,11 @@ function OngoingAlertMap(props: Props) {
<MapPopup
onCloseButtonClick={handlePointClose}
coordinates={clickedPointProperties.lngLat}
childrenContainerClassName={styles.popupContent}
heading="Map"
contentViewType="vertical"
childrenContainerClassName={styles.popupContent}
>
<>Hello</>
Map
</MapPopup>
)}
<MapBounds
Expand All @@ -281,6 +285,42 @@ function OngoingAlertMap(props: Props) {
padding={DEFAULT_MAP_PADDING}
/>
</BaseMap>
<Container
className={styles.countryList}
childrenContainerClassName={styles.content}
withInternalPadding
heading={strings.ongoingAlertCountries}
headingLevel={4}
withHeaderBorder
contentViewType="vertical"
actions={isDefined(activeCountryId) && (
<Button
name={undefined}
onClick={setActiveAlertIdSafe}
variant="tertiary"
icons={(
<ChevronLeftLineIcon className={styles.icon} />
)}
>
{strings.backToAlertsLabel}
</Button>
)}
>
{alertLoading && <BlockLoading />}
{isDefined(alertsResponse) && (
<List
className={styles.countryList}
filtered={false}
pending={alertLoading}
errored={false}
data={alertsResponse?.public?.alerts.items}
keySelector={keySelector}
renderer={AlertDetail}
rendererParams={eventListRendererParams}
emptyMessage="No data found"
/>
)}
</Container>
</Container>
);
}
Expand Down
Loading

0 comments on commit b21ef43

Please sign in to comment.