);
};
diff --git a/client/src/components/__snapshots__/areaDetail.test.tsx.snap b/client/src/components/__snapshots__/areaDetail.test.tsx.snap
new file mode 100644
index 00000000..7f925cfb
--- /dev/null
+++ b/client/src/components/__snapshots__/areaDetail.test.tsx.snap
@@ -0,0 +1,159 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`rendering of the AreaDetail checks if various text fields are visible 1`] = `
+
+
+ ,
+
+`;
diff --git a/client/src/components/__snapshots__/mapInfoPanel.test.tsx.snap b/client/src/components/__snapshots__/mapInfoPanel.test.tsx.snap
new file mode 100644
index 00000000..299e4350
--- /dev/null
+++ b/client/src/components/__snapshots__/mapInfoPanel.test.tsx.snap
@@ -0,0 +1,31 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`simulate a click on map hould match the snapshot of the MapInfoPanel component 1`] = ``;
+
+exports[`simulate app starting up, no click on map should match the snapshot of the MapIntroduction component 1`] = `
+
+
+
+
+ ,
+
+`;
diff --git a/client/src/components/areaDetail.module.scss b/client/src/components/areaDetail.module.scss
index fef7a424..96f7d902 100644
--- a/client/src/components/areaDetail.module.scss
+++ b/client/src/components/areaDetail.module.scss
@@ -1,23 +1,156 @@
-.areaDetailTable {
- max-width: 31.6vw;
+@import "./areaDetailUtils.scss";
+
+$sidePanelLabelFontColor: #171716;
+$featureSelectBorderColor: #00bde3;
+
+@mixin sidePanelLabelStyle {
+ font-size: small;
+ color: $sidePanelLabelFontColor;
+ font-weight: 600;
}
-.titleContainer {
- display: flex;
- flex-direction: column;
- padding: 22px 22px;
-}
-
-.titleIndicatorName {
- font-weight: bold;
+@mixin categorizationCircleStyle {
+ height: 0.6rem;
+ width: 0.6rem;
+ border-radius: 100%;
+ align-self: center;
+ margin-top: 0.8rem;
+ margin-right: 0.5rem;
+ opacity: 0.6;
}
.areaDetailContainer {
- max-height: 50vh;
- overflow: scroll;
+ display: flex;
+ flex-direction: column;
}
-.areaDetailTableContainer {
- overflow: auto;
- padding: 22px;
+// top row styles
+.topRow {
+ display: flex;
+}
+
+.cumulativeIndexScore,
+.categorization {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ height: 7.7rem;
+ border-bottom: $sidePanelBorder;
+ flex: 1 0 50%;
+ padding-top: 2rem;
+}
+
+.topRowTitle,
+.censusLabel {
+ @include sidePanelLabelStyle;
+}
+
+.topRowSubTitle {
+ font-size: small;
+ color: $sidePanelLabelFontColor;
+}
+
+.score {
+ font-size: xx-large;
+ font-weight: bolder;
+}
+
+.scoreSuperscript {
+ font-size: large;
+ padding-bottom: 1rem;
+}
+
+.categorization {
+ border-left: $sidePanelBorder;
+}
+
+.priority {
+ display: flex;
+}
+
+.prioritized {
+ @include categorizationCircleStyle;
+ background: #1a4480;
+ border: 1px solid $featureSelectBorderColor;
+}
+
+.threshold {
+ @include categorizationCircleStyle;
+ background: #d7dde7;
+ border: 1px solid $featureSelectBorderColor;
+}
+
+.nonPrioritized {
+ @include categorizationCircleStyle;
+ border: 1px solid $featureSelectBorderColor;
+}
+
+.prioritization {
+ font-size: large;
+ font-weight: bold;
+ padding-top: 0.8rem;
+}
+
+.censusRow {
+ display: flex;
+ flex-direction: column;
+ border-bottom: $sidePanelBorder;
+ list-style: none;
+ margin: 0;
+}
+
+//census row styles
+.censusRow {
+ padding: 1rem;
+}
+
+.censusText,
+.indicatorDescription {
+ font-size: small;
+}
+
+//Divider styles
+.divider {
+ @include sidePanelLabelStyle;
+ display: flex;
+ justify-content: space-between;
+ border-bottom: $sidePanelBorder;
+ padding: 0.3rem 0.5rem 0.3rem 1rem;
+ background-color: #edeef0;
+}
+
+//Indicator box styles
+.indicatorBox {
+ display: flex;
+ padding: 1.5rem 1rem;
+ border-bottom: $sidePanelBorder;
+
+ @media screen and (max-width: $mobileBreakpoint) {
+ justify-content: space-between;
+ padding-top: 0.5rem;
+ padding-bottom: 0.5rem;
+ }
+}
+
+.indicatorBox:last-child {
+ border-bottom: none;
+}
+
+.indicatorTitle {
+ font-size: large;
+ font-weight: bolder;
+}
+
+.indicatorValue {
+ flex: 1 0 37%;
+ align-self: center;
+ padding-left: 2.4rem;
+ font-size: large;
+
+ @media screen and (max-width: $mobileBreakpoint) {
+ flex: 1 0 40%;
+ align-self: inherit;
+ padding-left: 3rem;
+ padding-top: 1rem;
+ }
}
diff --git a/client/src/components/areaDetail.module.scss.d.ts b/client/src/components/areaDetail.module.scss.d.ts
index 06e2b22f..060bcaac 100644
--- a/client/src/components/areaDetail.module.scss.d.ts
+++ b/client/src/components/areaDetail.module.scss.d.ts
@@ -1,10 +1,27 @@
declare namespace MapModuleScssNamespace {
export interface IMapModuleScss {
areaDetailContainer: string;
- areaDetailTable:string;
- areaDetailTableContainer:string;
- titleContainer:string;
- titleIndicatorName:string;
+ topRow:string;
+ cumulativeIndexScore:string;
+ scoreSuperscript: string;
+ topRowTitle:string;
+ topRowSubTitle:string;
+ categorization:string;
+ prioritized:string;
+ threshold:string;
+ nonPrioritized:string;
+ priority:string;
+ prioritization:string;
+ censusRow:string;
+ censusText: string;
+ censusLabel:string;
+ divider:string;
+ indicatorBox:string;
+ indicatorInfo:string;
+ indicatorTitle:string;
+ indicatorDescription:string;
+ indicatorValue:string;
+ score:string;
}
}
diff --git a/client/src/components/areaDetail.test.tsx b/client/src/components/areaDetail.test.tsx
new file mode 100644
index 00000000..f2f2f8d5
--- /dev/null
+++ b/client/src/components/areaDetail.test.tsx
@@ -0,0 +1,47 @@
+import * as React from 'react';
+import {render} from '@testing-library/react';
+import AreaDetail, {getCategorization, readablePercent} from './areaDetail';
+import {LocalizedComponent} from '../test/testHelpers';
+import * as constants from '../data/constants';
+
+describe('rendering of the AreaDetail', () => {
+ const properties = {
+ [constants.POVERTY_PROPERTY_PERCENTILE]: 99,
+ [constants.EDUCATION_PROPERTY_PERCENTILE]: 98,
+ [constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE]: 97,
+ [constants.UNEMPLOYMENT_PROPERTY_PERCENTILE]: 96,
+ [constants.HOUSING_BURDEN_PROPERTY_PERCENTILE]: 95,
+ [constants.SCORE_PROPERTY_HIGH]: 95,
+ [constants.GEOID_PROPERTY]: 98729374234,
+ [constants.TOTAL_POPULATION]: 3435435,
+ };
+
+ const {asFragment} = render(
+
+
+ ,
+ )
+ ;
+
+ it('checks if various text fields are visible', () => {
+ expect(asFragment()).toMatchSnapshot();
+ });
+});
+
+describe('tests the readablePercent function', () => {
+ expect(readablePercent(.9877665443)).toEqual('98.8');
+});
+
+describe('tests the getCategorization function', () => {
+ it(`should equal Prioritized for value >= ${constants.SCORE_BOUNDARY_LOW}`, () => {
+ expect(getCategorization(.756)).toEqual(['Prioritized', undefined]);
+ });
+
+ it(`should equal Threshold for .60 <= value < ${constants.SCORE_BOUNDARY_THRESHOLD}`, () => {
+ expect(getCategorization(.65)).toEqual(['Threshold', undefined]);
+ });
+
+ it(`should equal Non-prioritized for value < ${constants.SCORE_BOUNDARY_PRIORITIZED}`, () => {
+ expect(getCategorization(.53)).toEqual(['Non-prioritized', undefined]);
+ });
+});
diff --git a/client/src/components/areaDetail.tsx b/client/src/components/areaDetail.tsx
index cd79f03a..eb57fcb7 100644
--- a/client/src/components/areaDetail.tsx
+++ b/client/src/components/areaDetail.tsx
@@ -1,92 +1,210 @@
+// External Libs:
import * as React from 'react';
-import * as constants from '../data/constants';
+import {useIntl} from 'gatsby-plugin-intl';
+import {defineMessages} from 'react-intl';
+
+// Components:
+
+// Styles and constants
import * as styles from './areaDetail.module.scss';
+import * as constants from '../data/constants';
+
+export const readablePercent = (percent: number) => {
+ return `${(percent * 100).toFixed(1)}`;
+};
+
+export const getCategorization = (percentile: number) => {
+ let categorization;
+ let categoryCircleStyle;
+
+ if (percentile >= constants.SCORE_BOUNDARY_PRIORITIZED ) {
+ categorization = 'Prioritized';
+ categoryCircleStyle = styles.prioritized;
+ } else if (constants.SCORE_BOUNDARY_THRESHOLD <= percentile && percentile < constants.SCORE_BOUNDARY_PRIORITIZED) {
+ categorization = 'Threshold';
+ categoryCircleStyle = styles.threshold;
+ } else {
+ categorization = 'Non-prioritized';
+ categoryCircleStyle = styles.nonPrioritized;
+ }
+ return [categorization, categoryCircleStyle];
+};
interface IAreaDetailProps {
properties: constants.J40Properties,
}
-
const AreaDetail = ({properties}:IAreaDetailProps) => {
- const readablePercent = (percent: number) => {
- return `${(percent * 100).toFixed(2)}`;
+ const intl = useIntl();
+ const messages = defineMessages({
+ cumulativeIndexScore: {
+ id: 'areaDetail.priorityInfo.cumulativeIndexScore',
+ defaultMessage: 'Cumulative Index Score',
+ description: 'the cumulative score of the feature selected',
+ },
+ percentile: {
+ id: 'areaDetail.priorityInfo.percentile',
+ defaultMessage: 'percentile',
+ description: 'the percentil of the feature selected',
+ },
+ categorization: {
+ id: 'areaDetail.priorityInfo.categorization',
+ defaultMessage: 'Categorization',
+ description: 'the categorization of prioritized, threshold or non-prioritized',
+ },
+ censusBlockGroup: {
+ id: 'areaDetail.geographicInfo.censusBlockGroup',
+ defaultMessage: 'Census block group:',
+ description: 'the census block group id number of the feature selected',
+ },
+ county: {
+ id: 'areaDetail.geographicInfo.county',
+ defaultMessage: 'County:',
+ description: 'the county of the feature selected',
+ },
+ state: {
+ id: 'areaDetail.geographicInfo.state',
+ defaultMessage: 'State: ',
+ description: 'the state of the feature selected',
+ },
+ population: {
+ id: 'areaDetail.geographicInfo.population',
+ defaultMessage: 'Population:',
+ description: 'the population of the feature selected',
+ },
+ indicatorColumnHeader: {
+ id: 'areaDetail.indicators.indicatorColumnHeader',
+ defaultMessage: 'INDICATORS',
+ description: 'the population of the feature selected',
+ },
+ percentileColumnHeader: {
+ id: 'areaDetail.indicators.percentileColumnHeader',
+ defaultMessage: 'PERCENTILE (0-100)',
+ description: 'the population of the feature selected',
+ },
+ poverty: {
+ id: 'areaDetail.indicator.poverty',
+ defaultMessage: 'Poverty',
+ description: 'Household income is less than or equal to twice the federal "poverty level"',
+ },
+ education: {
+ id: 'areaDetail.indicator.education',
+ defaultMessage: 'Education',
+ description: 'Percent of people age 25 or older that didn’t get a high school diploma',
+ },
+ linguisticIsolation: {
+ id: 'areaDetail.indicator.linguisticIsolation',
+ defaultMessage: 'Linguistic isolation',
+ description: 'Households in which all members speak a non-English language and ' +
+ 'speak English less than "very well"',
+ },
+ unemployment: {
+ id: 'areaDetail.indicator.unemployment',
+ defaultMessage: 'Unemployment rate',
+ description: 'Number of unemployed people as a percentage of the labor force',
+ },
+ houseBurden: {
+ id: 'areaDetail.indicator.houseBurden',
+ defaultMessage: 'Housing Burden',
+ description: 'Households that are low income and spend more than 30% of their income to housing costs',
+ },
+ });
+
+ const score = properties[constants.SCORE_PROPERTY_HIGH] as number;
+ const blockGroup = properties[constants.GEOID_PROPERTY];
+ const population = properties[constants.TOTAL_POPULATION];
+
+ interface indicatorInfo {
+ label: string,
+ description: string,
+ value: number,
+ }
+
+ // Todo: Ticket #367 will be replacing descriptions with YAML file
+ const povertyInfo:indicatorInfo = {
+ label: intl.formatMessage(messages.poverty),
+ description: 'Household income is less than or equal to twice the federal "poverty level"',
+ value: properties[constants.POVERTY_PROPERTY_PERCENTILE],
+ };
+ const eduInfo:indicatorInfo = {
+ label: intl.formatMessage(messages.education),
+ description: 'Percent of people age 25 or older that didn’t get a high school diploma',
+ value: properties[constants.EDUCATION_PROPERTY_PERCENTILE],
+ };
+ const linIsoInfo:indicatorInfo = {
+ label: intl.formatMessage(messages.linguisticIsolation),
+ description: 'Households in which all members speak a non-English language and speak English less than "very well"',
+ value: properties[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE],
+ };
+ const umemployInfo:indicatorInfo = {
+ label: intl.formatMessage(messages.unemployment),
+ description: 'Number of unemployed people as a percentage of the labor force',
+ value: properties[constants.UNEMPLOYMENT_PROPERTY_PERCENTILE],
+ };
+ const houseBurden:indicatorInfo = {
+ label: intl.formatMessage(messages.houseBurden),
+ description: 'Households that are low income and spend more than 30% of their income to housing costs',
+ value: properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE],
};
- const getCategorization = (percentile: number) => {
- let categorization;
- if (percentile >= 0.75 ) {
- categorization = 'Prioritized';
- } else if (0.60 <= percentile && percentile < 0.75) {
- categorization = 'Threshold';
- } else {
- categorization = 'Non-prioritized';
- }
- return categorization;
- };
-
- const getTitleContent = () => {
- const blockGroup = properties[constants.GEOID_PROPERTY];
- const score = properties[constants.SCORE_PROPERTY_HIGH] as number;
- return (
-
-
- Census Block Group:
- {blockGroup}
-
-
- Just Progress Categorization:
- {getCategorization(score)}
-
-
- Cumulative Index Score:
- {readablePercent(score)}
-
-
- );
- };
-
- const getBodyContent = () => {
- const rows = [];
- const sortedKeys = Object.entries(properties).sort();
- for (let [key, value] of sortedKeys) {
- // We should only format floats
- if (typeof value === 'number' && value % 1 !== 0) {
- value = readablePercent(value);
- }
-
- // Filter out all caps
- if (!key.match(/^[A-Z0-9]+$/)) {
- rows.push(
+ ))}
+
+
);
};
diff --git a/client/src/components/areaDetailUtils.scss b/client/src/components/areaDetailUtils.scss
new file mode 100644
index 00000000..7f8d4207
--- /dev/null
+++ b/client/src/components/areaDetailUtils.scss
@@ -0,0 +1,10 @@
+/*
+ This file is meant to hold styles that are shared with other SASS modules.
+ You can import this file into other SASS file to re-use styles.
+
+ Todo Design System: replace colors with tokens. Once these styles become more general the name can be less specific
+*/
+
+$sidePanelBorderColor: #f2f2f2;
+$sidePanelBorder: 2px solid $sidePanelBorderColor;
+$mobileBreakpoint: 400px;
diff --git a/client/src/components/mapInfoPanel.test.tsx b/client/src/components/mapInfoPanel.test.tsx
new file mode 100644
index 00000000..846a5922
--- /dev/null
+++ b/client/src/components/mapInfoPanel.test.tsx
@@ -0,0 +1,51 @@
+import * as React from 'react';
+import {render} from '@testing-library/react';
+import MapInfoPanel from './mapInfoPanel';
+import {LocalizedComponent} from '../test/testHelpers';
+
+describe('simulate app starting up, no click on map', () => {
+ const {asFragment} = render(
+
+
+ ,
+ );
+
+ it('should match the snapshot of the MapIntroduction component', () => {
+ expect(asFragment()).toMatchSnapshot();
+ });
+});
+
+describe('simulate a click on map', () => {
+ const featureProperties = {
+ 'GEOID10': '350459430003',
+ 'Total population': 960,
+ 'GEOID10 (percentile)': 0.5784380914343289,
+ 'Housing burden (percent) (percentile)': 0.10073235017829946,
+ 'Total population (percentile)': 0.2985685303608629,
+ 'Linguistic isolation (percent) (percentile)': 0.9623469180109516,
+ 'Percent of households in linguistic isolation (percentile)': 0.9230800651740774,
+ 'Poverty (Less than 200% of federal poverty line) (percentile)': 0.947202643271775,
+ 'Percent individuals age 25 or over with less than high school degree (percentile)': 0.7804232684164424,
+ 'Unemployed civilians (percent) (percentile)': 0.9873599918675144,
+ 'Score D (percentile)': 0.9321799276549586,
+ };
+ const selectedFeatureId = 345;
+
+ const {asFragment} = render(
+
+
+ ,
+ );
+
+ it('hould match the snapshot of the MapInfoPanel component', () => {
+ expect(asFragment()).toMatchSnapshot();
+ });
+});
diff --git a/client/src/components/mapInfoPanel.tsx b/client/src/components/mapInfoPanel.tsx
new file mode 100644
index 00000000..19e9874b
--- /dev/null
+++ b/client/src/components/mapInfoPanel.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import MapIntroduction from './mapIntroduction';
+import AreaDetail from './areaDetail';
+
+interface IMapInfoPanelProps {
+ className: string,
+ featureProperties: { [key:string]: string | number } | undefined,
+ selectedFeatureId: string | number | undefined
+ }
+
+const MapInfoPanel = ({className, featureProperties, selectedFeatureId}:IMapInfoPanelProps) => {
+ return (
+
+ );
+};
+
+export default MapInfoPanel;
diff --git a/client/src/components/mapIntroduction.module.scss b/client/src/components/mapIntroduction.module.scss
new file mode 100644
index 00000000..3421d211
--- /dev/null
+++ b/client/src/components/mapIntroduction.module.scss
@@ -0,0 +1,34 @@
+.mapIntroContainer {
+ padding: 20px 20px;
+}
+
+.mapIntroHeader {
+ font-size: xx-large;
+ line-height: 1.9rem;
+ padding-top: 0.8rem;
+ padding-left: 0.3rem;
+}
+.mapIntroText {
+ display: flex;
+ margin-top: 2.4rem;
+}
+
+.mapIntroLightbulb {
+ flex: 1 0 10%;
+ align-self: flex-start;
+}
+
+.didYouKnowBox {
+ padding-left: 0.4rem;
+ padding-top: 0.2rem;
+ font-size: large;
+}
+
+.didYouKnow {
+ font-weight: 600;
+}
+.didYouKnowText {
+ width: 95%;
+ padding-top: 0.3rem;
+ line-height: 1.5rem;
+}
diff --git a/client/src/components/mapIntroduction.module.scss.d.ts b/client/src/components/mapIntroduction.module.scss.d.ts
new file mode 100644
index 00000000..afa9b474
--- /dev/null
+++ b/client/src/components/mapIntroduction.module.scss.d.ts
@@ -0,0 +1,18 @@
+declare namespace MapIntroductionModuleScssNamespace {
+ export interface IMapIntroductionModuleScss {
+ mapIntroContainer: string;
+ mapIntroHeader: string;
+ mapIntroText: string;
+ mapIntroLightbulb: string;
+ didYouKnowBox: string
+ didYouKnow: string
+ didYouKnowText: string
+ }
+ }
+
+declare const MapIntroductionModuleScssModule: MapIntroductionModuleScssNamespace.IMapIntroductionModuleScss & {
+ /** WARNING: Only available when `css-loader` is used without `style-loader` or `mini-css-extract-plugin` */
+ locals: MapIntroductionModuleScssNamespace.IMapIntroductionModuleScss;
+ };
+
+export = MapIntroductionModuleScssModule;
diff --git a/client/src/components/mapIntroduction.test.tsx b/client/src/components/mapIntroduction.test.tsx
new file mode 100644
index 00000000..bbbfc50e
--- /dev/null
+++ b/client/src/components/mapIntroduction.test.tsx
@@ -0,0 +1,16 @@
+import * as React from 'react';
+import {render, screen} from '@testing-library/react';
+import MapIntroduction from './mapIntroduction';
+import {LocalizedComponent} from '../../src/test/testHelpers';
+
+describe('rendering of the component', () => {
+ render(
+
+
+ ,
+ );
+
+ it('renders the title', () => {
+ expect(screen.getByRole('banner')).toHaveTextContent('Zoom and select a census block group to view data');
+ });
+});
diff --git a/client/src/components/mapIntroduction.tsx b/client/src/components/mapIntroduction.tsx
new file mode 100644
index 00000000..2ab932a5
--- /dev/null
+++ b/client/src/components/mapIntroduction.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import {useIntl} from 'gatsby-plugin-intl';
+import {defineMessages} from 'react-intl';
+
+// @ts-ignore
+import lightbulbIcon from '/node_modules/uswds/dist/img/usa-icons/lightbulb_outline.svg';
+import * as styles from './mapIntroduction.module.scss';
+
+const MapIntroduction = () => {
+ const intl = useIntl();
+ const messages = defineMessages({
+ mapIntroHeader: {
+ id: 'mapIntro.mapIntroHeader',
+ defaultMessage: 'Zoom and select a census block group to view data',
+ description: 'introductory text of ways to use the map',
+ },
+ didYouKnow: {
+ id: 'mapIntro.didYouKnow',
+ defaultMessage: ' Did you know?',
+ description: 'text prompting a cite paragraph',
+ },
+ censusBlockGroupDefinition: {
+ id: 'mapIntro.censusBlockGroupDefinition',
+ defaultMessage: 'A census block group is generally between 600 and 3,000 people. ' +
+ 'It is the smallest geographical unit for which the U.S. Census ' +
+ 'Bureau publishes sample data.',
+ description: 'cites the definition and helpful information about census groups',
+ },
+ });
+
+ return (
+
+ );
+};
+
+export default MapIntroduction;
diff --git a/client/src/components/mapWrapper.tsx b/client/src/components/mapWrapper.tsx
index 1768cb1b..de0a1d60 100644
--- a/client/src/components/mapWrapper.tsx
+++ b/client/src/components/mapWrapper.tsx
@@ -1,13 +1,14 @@
import * as React from 'react';
import J40Map from './J40Map';
+import MapLegend from '../components/mapLegend';
const MapWrapper = () => {
return (
-
- {
-
- }
-
+
+
Explore the Tool
+
+
+
);
};
diff --git a/client/src/data/constants.tsx b/client/src/data/constants.tsx
index a1d779c3..98b9a444 100644
--- a/client/src/data/constants.tsx
+++ b/client/src/data/constants.tsx
@@ -1,4 +1,5 @@
import {LngLatBoundsLike} from 'maplibre-gl';
+import {isMobile as isMobileReactDeviceDetect} from 'react-device-detect';
// URLS
export const FEATURE_TILE_BASE_URL = 'https://d2zjid6n5ja2pt.cloudfront.net';
@@ -22,13 +23,20 @@ export const HIGH_SCORE_LAYER_NAME = 'score-high-layer';
export const LOW_SCORE_SOURCE_NAME = 'score-low';
export const LOW_SCORE_LAYER_NAME = 'score-low-layer';
export const SELECTED_PROPERTY = 'selected';
+export const POVERTY_PROPERTY_PERCENTILE = 'Poverty (Less than 200% of federal poverty line) (percentile)';
+export const HOUSING_BURDEN_PROPERTY_PERCENTILE = 'Housing burden (percent) (percentile)';
+export const LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE = 'Linguistic isolation (percent) (percentile)';
+export const UNEMPLOYMENT_PROPERTY_PERCENTILE = 'Unemployed civilians (percent) (percentile)';
+export const TOTAL_POPULATION = 'Total population';
+
+export const EDUCATION_PROPERTY_PERCENTILE = 'Percent individuals age 25 or over ' +
+'with less than high school degree (percentile)';
// The name of the layer within the tiles that contains the score
export const SCORE_SOURCE_LAYER = 'blocks';
export type J40Properties = { [key: string]: any };
-
// Zoom
export const GLOBAL_MIN_ZOOM = 3;
export const GLOBAL_MAX_ZOOM = 22;
@@ -100,4 +108,4 @@ export const SCORE_BOUNDARY_LOW = 0.0;
export const SCORE_BOUNDARY_THRESHOLD = 0.6;
export const SCORE_BOUNDARY_PRIORITIZED = 0.75;
-export const isMobile = typeof window !== 'undefined' && (window.innerWidth < 400);
+export const isMobile = isMobileReactDeviceDetect;
diff --git a/client/src/intl/en.json b/client/src/intl/en.json
index 8f16da71..5e2f336a 100644
--- a/client/src/intl/en.json
+++ b/client/src/intl/en.json
@@ -1,4 +1,60 @@
{
+ "areaDetail.geographicInfo.censusBlockGroup": {
+ "defaultMessage": "Census block group:",
+ "description": "the census block group id number of the feature selected"
+ },
+ "areaDetail.geographicInfo.county": {
+ "defaultMessage": "County:",
+ "description": "the county of the feature selected"
+ },
+ "areaDetail.geographicInfo.population": {
+ "defaultMessage": "Population:",
+ "description": "the population of the feature selected"
+ },
+ "areaDetail.geographicInfo.state": {
+ "defaultMessage": "State:",
+ "description": "the state of the feature selected"
+ },
+ "areaDetail.indicator.education": {
+ "defaultMessage": "Education",
+ "description": "Percent of people age 25 or older that didn’t get a high school diploma"
+ },
+ "areaDetail.indicator.houseBurden": {
+ "defaultMessage": "Housing Burden",
+ "description": "Households that are low income and spend more than 30% of their income to housing costs"
+ },
+ "areaDetail.indicator.linguisticIsolation": {
+ "defaultMessage": "Linguistic Isolation",
+ "description": "Households in which all members speak a non-English language and speak English less than \"very well\""
+ },
+ "areaDetail.indicator.poverty": {
+ "defaultMessage": "Poverty",
+ "description": "Household income is less than or equal to twice the federal \"poverty level\""
+ },
+ "areaDetail.indicator.unemployment": {
+ "defaultMessage": "Unemployment",
+ "description": "Number of unemployed people as a percentage of the labor force"
+ },
+ "areaDetail.indicators.indicatorColumnHeader": {
+ "defaultMessage": "INDICATORS",
+ "description": "the population of the feature selected"
+ },
+ "areaDetail.indicators.percentileColumnHeader": {
+ "defaultMessage": "PERCENTILE (0-100)",
+ "description": "the population of the feature selected"
+ },
+ "areaDetail.priorityInfo.categorization": {
+ "defaultMessage": "Categorization",
+ "description": "the categorization of prioritized, threshold or non-prioritized"
+ },
+ "areaDetail.priorityInfo.cumulativeIndexScore": {
+ "defaultMessage": "Cumulative Index Score",
+ "description": "the cumulative score of the feature selected"
+ },
+ "areaDetail.priorityInfo.percentile": {
+ "defaultMessage": "percentile",
+ "description": "the percentil of the feature selected"
+ },
"areasOfInterest.climate": {
"defaultMessage": "Climate change",
"description": "item in areasOfInterest list"
diff --git a/client/src/pages/cejst.tsx b/client/src/pages/cejst.tsx
index 5f2136f5..234c3765 100644
--- a/client/src/pages/cejst.tsx
+++ b/client/src/pages/cejst.tsx
@@ -2,7 +2,6 @@ import React from 'react';
import Layout from '../components/layout';
import MapWrapper from '../components/mapWrapper';
import HowYouCanHelp from '../components/HowYouCanHelp';
-import MapLegend from '../components/mapLegend';
import DownloadPacket from '../components/downloadPacket';
import * as styles from './cejst.module.scss';
@@ -52,10 +51,7 @@ const CEJSTPage = ({location}: IMapPageProps) => {