diff --git a/src/components/app.tsx b/src/components/app.tsx index 7564101..542371c 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -2,7 +2,7 @@ import React, {useEffect, useState} from "react"; import { Dropdown } from "./dropdown"; import classnames from "classnames"; import { Information } from "./information"; -import { attributeOptions, categories, defaultSelectedOptions, yearsOptions } from "./constants"; +import { attributeOptions, categories, defaultSelectedOptions } from "./constants"; import { IStateOptions } from "./types"; import { createTableFromSelections } from "../scripts/api"; import { connect } from "../scripts/connect"; @@ -14,7 +14,6 @@ function App() { const [showInfo, setShowInfo] = useState(false); const [selectedOptions, setSelectedOptions] = useState(defaultSelectedOptions); const [getDataDisabled, setGetDataDisabled] = useState(true); - const {farmerDemographics, farmDemographics, crops, economicsAndWages} = selectedOptions; useEffect(() => { const init = async () => { diff --git a/src/components/attribute-options.tsx b/src/components/attribute-options.tsx index 6e373a5..939aeee 100644 --- a/src/components/attribute-options.tsx +++ b/src/components/attribute-options.tsx @@ -34,8 +34,12 @@ export const AttributeOptions: React.FC = (props) => { attributeOptions.map((attr) => { return ( <> - {attr.label &&
{attr.label}
} - {attr.instructions &&
{attr.instructions}
} + {attr.label &&
{attr.label}
} + {attr.instructions && +
+ {attr.instructions} +
+ }
= (props) => {
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ipsum velit, pellentesque eget turpis non, vestibulum egestas tellus. Fusce sed dolor hendrerit, rutrum ligula et, imperdiet est. Nam tincidunt leo a ultricies elementum. Quisque ornare eget massa ac congue. Curabitur et nisi orci. Nulla mollis lacus eu velit mollis, in vehicula lectus ultricies. Nulla facilisi. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ipsum velit, pellentesque eget turpis.
diff --git a/src/components/options.scss b/src/components/options.scss index 70b558b..bb1821e 100644 --- a/src/components/options.scss +++ b/src/components/options.scss @@ -68,7 +68,7 @@ } } -.category { +.statisticcat_desc { font-weight: 600; } diff --git a/src/components/place-options.tsx b/src/components/place-options.tsx index f165fbd..7e5bb04 100644 --- a/src/components/place-options.tsx +++ b/src/components/place-options.tsx @@ -18,7 +18,10 @@ export const PlaceOptions: React.FC = (props) => { return ( <>
{placeOpt.instructions}:
-
+
{ return arr.reduce((acc: any[], val: any) => Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []); -} +}; diff --git a/src/components/years-options.tsx b/src/components/years-options.tsx index 8bfd780..bd0ab11 100644 --- a/src/components/years-options.tsx +++ b/src/components/years-options.tsx @@ -15,7 +15,6 @@ interface IProps { export const YearsOptions: React.FC = (props) => { const {handleSetSelectedOptions, selectedOptions} = props; const [availableYearOptions, setAvailableYearOptions] = useState([]); - const {farmerDemographics, farmDemographics, crops, economicsAndWages} = selectedOptions; useEffect(() => { const attrKeys = attributeOptions.filter((attr) => attr.key !== "cropUnits").map((attr) => attr.key); @@ -37,9 +36,20 @@ export const YearsOptions: React.FC = (props) => { } return years; }, new Set()); + const newSet: string[] = Array.from(newAvailableYears); + setAvailableYearOptions(newSet); - setAvailableYearOptions(Array.from(newAvailableYears)); - }, [farmerDemographics, farmDemographics, crops, economicsAndWages]) + // if selected years includes years not in available options, remove them from selection + const selectionsNotAvailable = selectedOptions.years.filter(year => !newSet.includes(year)); + if (selectionsNotAvailable.length) { + const newSelectedYears = [...selectedOptions.years]; + selectionsNotAvailable.forEach((year) => { + newSelectedYears.splice(newSelectedYears.indexOf(year), 1); + }); + handleSetSelectedOptions("years", newSelectedYears); + } + + }, [selectedOptions, handleSetSelectedOptions]); const handleSelectYear = (yearKey: string, years: string|string[]) => { handleSetSelectedOptions(yearKey, years); diff --git a/src/scripts/api.ts b/src/scripts/api.ts index ba10ec7..b44fbfa 100644 --- a/src/scripts/api.ts +++ b/src/scripts/api.ts @@ -1,5 +1,5 @@ import fetchJsonp from "fetch-jsonp"; -import { ICropDataItem, queryData } from "./query-headers"; +import { ICropCategory, ICropDataItem, queryData } from "./query-headers"; import { IStateOptions } from "../components/types"; import { connect } from "./connect"; import { cropOptions } from "../components/constants"; @@ -24,30 +24,41 @@ interface IGetAttrDataParams { export const createRequest = ({attribute, geographicLevel, location, year, cropCategory}: IRequestParams) => { const queryParams = queryData.find((d) => d.plugInAttribute === attribute); - const {sector, group, commodity, category, domains, dataItem} = queryParams!; - - let item; - let cat; - if (cropCategory) { - const cropDataItem = queryParams?.dataItem as ICropDataItem; - const cropCat = queryParams?.category as ICropDataItem; - item = cropDataItem[cropCategory]; - cat = cropCat[cropCategory]; - } else { - item = dataItem; - cat = category; - } - const baseReq = `${baseURL}§_desc=${sector}&group_desc=${group}&commodity_desc=${commodity}&statisticcat_desc=${cat}&domain_desc=${domains}&agg_level_desc=${geographicLevel}&state_name=${location}&year=${year}`; - let req = baseReq; - if (Array.isArray(dataItem)) { - dataItem.forEach(dItem => { - req = req + `&short_desc=${dItem}`; - }); - } else { - req = req + `&short_desc=${item}`; + if (!queryParams) { + throw new Error("Invalid attribute"); } + const { + sect_desc, + group_desc, + commodity_desc, + statisticcat_desc, + domain_desc, + short_desc, + } = queryParams; + + const item = cropCategory ? + (queryParams?.short_desc as ICropDataItem)[cropCategory] : + short_desc as string[]; + const cat = cropCategory ? + (queryParams?.statisticcat_desc as ICropCategory)[cropCategory] : + statisticcat_desc; + + const baseReq = `${baseURL}` + + `§_desc=${encodeURIComponent(sect_desc)}` + + `&group_desc=${encodeURIComponent(group_desc)}` + + `&commodity_desc=${encodeURIComponent(commodity_desc)}` + + `&statisticcat_desc=${encodeURIComponent(cat as string)}` + + `&domain_desc=${encodeURIComponent(domain_desc)}` + + `&agg_level_desc=${geographicLevel}` + + `&state_name=${location}` + + `&year=${year}`; + + let req = baseReq; + item.forEach(subItem => { + req = req + `&short_desc=${encodeURIComponent(subItem)}`; + }); return req; }; @@ -62,11 +73,14 @@ export const createTableFromSelections = async (selectedOptions: IStateOptions) const selections = subOptions[key as keyof typeof subOptions]; for (const attribute of selections) { const queryParams = queryData.find((d) => d.plugInAttribute === attribute); - const {dataItem} = queryParams!; - if (Array.isArray(dataItem)) { - allAttrs.push(...dataItem); + if (!queryParams) { + throw new Error("Invalid attribute"); + } + const {short_desc} = queryParams; + if (Array.isArray(short_desc)) { + allAttrs.push(...short_desc); } else { - allAttrs.push(dataItem); + allAttrs.push(short_desc); } } } @@ -74,7 +88,7 @@ export const createTableFromSelections = async (selectedOptions: IStateOptions) const items = await getItems(selectedOptions); await connect.createItems(items); await connect.makeCaseTableAppear(); -} +}; const getItems = async (selectedOptions: IStateOptions) => { const {states, years} = selectedOptions; @@ -108,7 +122,7 @@ const getDataForSingleYearAndState = async (selectedOptions: IStateOptions, stat let item: any = { "State": state, "Year": year, - } + }; for (const key in subOptions) { const value = subOptions[key as keyof typeof subOptions]; @@ -136,12 +150,12 @@ const getAttrData = async (params: IGetAttrDataParams) => { const {data} = res; data.forEach((dataItem: any) => { values[dataItem.short_desc] = dataItem.Value; - }) + }); } else { console.log("error"); } return values; -} +}; export const fetchData = async (req: string) => { try { @@ -152,4 +166,4 @@ export const fetchData = async (req: string) => { console.log("parsing failed", error); throw error; } -}; \ No newline at end of file +}; diff --git a/src/scripts/query-headers.ts b/src/scripts/query-headers.ts index 2151acf..32110af 100644 --- a/src/scripts/query-headers.ts +++ b/src/scripts/query-headers.ts @@ -1,19 +1,24 @@ const areaHarvested = "Area Harvested"; const yieldInBU = "Yield"; -export interface ICropDataItem { + +export interface ICropCategory { [areaHarvested]: string, [yieldInBU]: string } +export interface ICropDataItem { + [areaHarvested]: string[], + [yieldInBU]: string[] +} -interface IQueryHeaders { +export interface IQueryHeaders { plugInAttribute: string, numberOfAttributeColumnsInCodap: number|string, - sector: string, - group: string, - commodity: string, - category: string|ICropDataItem, - dataItem: string|string[]|ICropDataItem, - domains: string, + sect_desc: string, + group_desc: string, + commodity_desc: string, + statisticcat_desc: string|ICropCategory, + short_desc: string[]|ICropDataItem, + domain_desc: string, geographicLevels?: string, years: { county: string[] @@ -22,24 +27,24 @@ interface IQueryHeaders { } const sharedDemographicHeaders = { -sector: "Demographics", -group: "Producers", -commodity: "Producers", -category: "Producers", -domains: "Total", +sect_desc: "Demographics", +group_desc: "Producers", +commodity_desc: "Producers", +statisticcat_desc: "Producers", +domain_desc: "Total", }; const sharedEconomicHeaders = { -sector: "Economics", -group: "Farms & Land & Assets", -commodity: "Farm Operations", -category: "Operations" +sect_desc: "Economics", +group_desc: "Farms & Land & Assets", +commodity_desc: "Farm Operations", +statisticcat_desc: "Operations" }; const sharedLaborHeaders = { -sector: "Economics", -group: "Expenses", -commodity: "Labor", +sect_desc: "Economics", +group_desc: "Expenses", +commodity_desc: "Labor", }; const allYears = []; @@ -52,7 +57,7 @@ export const queryData: Array = [ plugInAttribute: "Total Farmers", numberOfAttributeColumnsInCodap: 1, ...sharedDemographicHeaders, - dataItem: "PRODUCERS, (ALL) - NUMBER OF PRODUCERS", + short_desc: ["PRODUCERS, (ALL) - NUMBER OF PRODUCERS"], years: { county: ["2017"], state: ["2017"] @@ -62,7 +67,7 @@ export const queryData: Array = [ plugInAttribute: "Age", numberOfAttributeColumnsInCodap: 7, ...sharedDemographicHeaders, - dataItem: [ + short_desc: [ "PRODUCERS, AGE LT 25 - NUMBER OF PRODUCERS", "PRODUCERS, AGE 25 TO 34 - NUMBER OF PRODUCERS", "PRODUCERS, AGE 35 TO 44 - NUMBER OF PRODUCERS", @@ -81,7 +86,7 @@ export const queryData: Array = [ plugInAttribute: "Gender", numberOfAttributeColumnsInCodap: 2, ...sharedDemographicHeaders, - dataItem: [ + short_desc: [ "PRODUCERS, (ALL), FEMALE - NUMBER OF PRODUCERS", "PRODUCERS, (ALL), MALE - NUMBER OF PRODUCERS" ], @@ -94,7 +99,7 @@ export const queryData: Array = [ plugInAttribute: "Race", numberOfAttributeColumnsInCodap: 7, ...sharedDemographicHeaders, - dataItem: [ + short_desc: [ "PRODUCERS, AMERICAN INDIAN OR ALASKAN NATIVE - NUMBER OF PRODUCERS", "PRODUCERS, ASIAN - NUMBER OF PRODUCERS", "PRODUCERS, BLACK OR AFRICAN AMERICAN - NUMBER OF PRODUCERS", @@ -112,8 +117,8 @@ export const queryData: Array = [ plugInAttribute: "Total Farms", numberOfAttributeColumnsInCodap: 1, ...sharedEconomicHeaders, - dataItem: "Farm Operations - Number of Operations", - domains: "Total", + short_desc: ["FARM OPERATIONS - NUMBER OF OPERATIONS"], + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears, @@ -123,30 +128,30 @@ export const queryData: Array = [ { plugInAttribute: "Organization Type", numberOfAttributeColumnsInCodap: 5, - sector: "Demographics", - group: "Farms & Land & Assets", - commodity: "Farm Operations", - category: "Operations", - dataItem: [ + sect_desc: "Demographics", + group_desc: "Farms & Land & Assets", + commodity_desc: "Farm Operations", + statisticcat_desc: "Operations", + short_desc: [ "FARM OPERATIONS, ORGANIZATION, TAX PURPOSES, CORPORATION (EXCL FAMILY HELD) - NUMBER OF OPERATIONS", "FARM OPERATIONS, ORGANIZATION, TAX PURPOSES, CORPORATION, FAMILY HELD - NUMBER OF OPERATIONS", "FARM OPERATIONS, ORGANIZATION, TAX PURPOSES, FAMILY & INDIVIDUAL - NUMBER OF OPERATIONS", "FARM OPERATIONS, ORGANIZATION, TAX PURPOSES, INSTITUTIONAL & RESEARCH & RESERVATION & OTHER - NUMBER OF OPERATIONS", "FARM OPERATIONS, ORGANIZATION, TAX PURPOSES, PARTNERSHIP - NUMBER OF OPERATIONS" ], - domains: "Total", - geographicLevels: "State, County", + domain_desc: "Total", + geographicLevels: "County", years: { county: ["1997", "2002", "2007", "2012", "2017"], - state: allYears + state: [] } }, { plugInAttribute: "Economic Class", numberOfAttributeColumnsInCodap: "3 - 6", ...sharedEconomicHeaders, - dataItem: "Farm Operations - Number of Operations", - domains: "Economic Class", + short_desc: ["FARM OPERATIONS - NUMBER OF OPERATIONS"], + domain_desc: "Economic Class", geographicLevels: "State ", years: { county: allYears.filter(y => Number(y) >= 1987), @@ -156,12 +161,12 @@ export const queryData: Array = [ { plugInAttribute: "Acres Operated", numberOfAttributeColumnsInCodap: 14, - sector: "Economics", - group: "Farms & Land & Assets", - commodity: "Farm Operations", - category: "Area Operated", - dataItem: "Farm Operations - Acres Operated", - domains: "Area Operated", + sect_desc: "Economics", + group_desc: "Farms & Land & Assets", + commodity_desc: "Farm Operations", + statisticcat_desc: "Area Operated", + short_desc: ["FARM OPERATIONS - ACRES OPERATED"], + domain_desc: "Area Operated", geographicLevels: "State, County", years: { county: ["1997", "2002", "2007", "2012", "2017"], @@ -172,8 +177,8 @@ export const queryData: Array = [ plugInAttribute: "Organic", numberOfAttributeColumnsInCodap: 1, ...sharedEconomicHeaders, - dataItem: "Farm Operations, Organic - Number of Operations", - domains: "Organic Status", + short_desc: ["FARM OPERATIONS, ORGANIC - NUMBER OF OPERATIONS"], + domain_desc: "Organic Status", years: { county: ["2008", "2011", "2012", "2014", "2015", "2016", "2017", "2019", "2021"], state: ["2008", "2011", "2012", "2014", "2015", "2016", "2017", "2019", "2021"] @@ -183,13 +188,13 @@ export const queryData: Array = [ plugInAttribute: "Labor Status", numberOfAttributeColumnsInCodap: 3, ...sharedLaborHeaders, - category: "Workers", - dataItem: [ + statisticcat_desc: "Workers", + short_desc: [ "LABOR, MIGRANT - NUMBER OF WORKERS", "LABOR, UNPAID - NUMBER OF WORKERS", "LABOR, HIRED - NUMBER OF WORKERS" ], - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: ["2012", "2017"], @@ -200,9 +205,9 @@ export const queryData: Array = [ plugInAttribute: "Wages", numberOfAttributeColumnsInCodap: 1, ...sharedLaborHeaders, - category: "Wage Rate", - dataItem: "LABOR, HIRED - WAGE RATE, MEASURED IN $/HOUR", - domains: "Total", + statisticcat_desc: "Wage Rate", + short_desc: ["LABOR, HIRED - WAGE RATE, MEASURED IN $/HOUR"], + domain_desc: "Total", geographicLevels: "Region: Multi-state", years: { county: allYears.filter(y => Number(y) >= 1989), @@ -213,9 +218,9 @@ export const queryData: Array = [ plugInAttribute: "Time Worked", numberOfAttributeColumnsInCodap: 1, ...sharedLaborHeaders, - category: "Wage Rate", - dataItem: "Labor, Hired - Time Worked, Measured in Hours/Week", - domains: "Total", + statisticcat_desc: "Wage Rate", + short_desc: ["LABOR, HIRED - TIME WORKED, MEASURED IN HOURS/WEEK"], + domain_desc: "Total", geographicLevels: "Region: Multi-state", years: { county: allYears.filter(y => Number(y) >= 1989), @@ -225,18 +230,18 @@ export const queryData: Array = [ { plugInAttribute: "Corn", numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Field Crops", - commodity: "Corn", - category: { + sect_desc: "Crops", + group_desc: "Field Crops", + commodity_desc: "Corn", + statisticcat_desc: { [areaHarvested]: "Area Harvested", [yieldInBU]: "Yield" }, - dataItem: { - [areaHarvested]: "Corn, Grain - Acres Harvested", - [yieldInBU]: "Corn, Grain - Yield, measured in BU / acre" + short_desc: { + [areaHarvested]: ["CORN, GRAIN - ACRES HARVESTED"], + [yieldInBU]: ["CORN, GRAIN - YIELD, MEASURED IN BU / ACRE"] }, - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears, @@ -246,18 +251,18 @@ export const queryData: Array = [ { plugInAttribute: "Cotton", numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Field Crops", - commodity: "Cotton", - category: { + sect_desc: "Crops", + group_desc: "Field Crops", + commodity_desc: "Cotton", + statisticcat_desc: { [areaHarvested]: "Area Harvested", [yieldInBU]: "Yield" }, - dataItem: { - [areaHarvested]: "Cotton - Acres Harvested", - [yieldInBU]: "Cotton - Yield, measured in LB / acre" + short_desc: { + [areaHarvested]: ["COTTON - ACRES HARVESTED"], + [yieldInBU]: ["COTTON - YIELD, MEASURED IN LB / ACRE"] }, - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears, @@ -267,39 +272,18 @@ export const queryData: Array = [ { plugInAttribute: "Grapes", numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Fruit & Tree Nuts", - commodity: "Grapes", - category: { - [areaHarvested]: "Area Harvested", - [yieldInBU]: "Yield" - }, - dataItem: { - [areaHarvested]: "Grapes, Organic - Acres Harvested", - [yieldInBU]: "Grapes - Yield, measured in tons / acre" - }, - domains: "Total", - geographicLevels: "State, County", - years: { - county: allYears, - state: allYears - } -}, -{ - plugInAttribute: "Grasses", - numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Field Crops", - commodity: "Grasses", - category: { + sect_desc: "Crops", + group_desc: "Fruit & Tree Nuts", + commodity_desc: "Grapes", + statisticcat_desc: { [areaHarvested]: "Area Harvested", [yieldInBU]: "Yield" }, - dataItem: { - [areaHarvested]: "", - [yieldInBU]: "" + short_desc: { + [areaHarvested]: ["GRAPES, ORGANIC - ACRES HARVESTED"], + [yieldInBU]: ["GRAPES - YIELD, MEASURED IN TONS / ACRE"] }, - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears, @@ -309,18 +293,18 @@ export const queryData: Array = [ { plugInAttribute: "Oats", numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Field Crops", - commodity: "Oats", - category: { + sect_desc: "Crops", + group_desc: "Field Crops", + commodity_desc: "Oats", + statisticcat_desc: { [areaHarvested]: "Area Harvested", [yieldInBU]: "Yield" }, - dataItem: { - [areaHarvested]: "Oats - Acres Harvested", - [yieldInBU]: "Oats - Yield, measured in BU / acre" + short_desc: { + [areaHarvested]: ["Oats - Acres Harvested"], + [yieldInBU]: ["Oats - Yield, measured in BU / acre"] }, - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears, @@ -330,18 +314,18 @@ export const queryData: Array = [ { plugInAttribute: "Soybeans", numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Field Crops", - commodity: "Soybeans", - category: { + sect_desc: "Crops", + group_desc: "Field Crops", + commodity_desc: "Soybeans", + statisticcat_desc: { [areaHarvested]: "Area Harvested", [yieldInBU]: "Yield" }, - dataItem: { - [areaHarvested]: "Soybeans - Acres Harvested", - [yieldInBU]: "Soybeans - Yield, measured in BU / acre" + short_desc: { + [areaHarvested]: ["Soybeans - Acres Harvested"], + [yieldInBU]: ["Soybeans - Yield, measured in BU / acre"] }, - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears, @@ -351,18 +335,18 @@ export const queryData: Array = [ { plugInAttribute: "Wheat", numberOfAttributeColumnsInCodap: 1, - sector: "Crops", - group: "Field Crops", - commodity: "Wheat", - category: { + sect_desc: "Crops", + group_desc: "Field Crops", + commodity_desc: "Wheat", + statisticcat_desc: { [areaHarvested]: "Area Harvested", [yieldInBU]: "Yield" }, - dataItem: { - [areaHarvested]: "Wheat - Acres Harvested", - [yieldInBU]: "Wheat - Yield, measured in BU / acre" + short_desc: { + [areaHarvested]: ["Wheat - Acres Harvested"], + [yieldInBU]: ["Wheat - Yield, measured in BU / acre"] }, - domains: "Total", + domain_desc: "Total", geographicLevels: "State, County", years: { county: allYears,