Skip to content

emilieallen/project-2

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

60 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GA London React Project-2-What's My Footprint

TABLE OF CONTENTS

The second project for General Assembley (GA) Software Engineering Immersive(SEI-Flex) program was to build a React application that consumes a public API.

We have selected Carbon Cloud API to get products Carbon dioxide equivalent (CO2e). Our application aims to allow users to:

  • Display products from various Markets based on the selected production Stage.
  • Search for products by name from the rendered list.
  • Show Most and Least emissive products from selected categories.
  • Add selected products to "Interested In" or "Would like to Avoid" baskets
  • Estimate the total impact of products in the baskets.

The app can be viewed here.

The app had to:

  • Consume a public API – this could be anything but it must make sense for your project.
  • The app should include a router - with several "pages".
  • Include wireframes - that you designed before building the app.
  • Have semantically clean HTML.
  • Be deployed online and accessible to the public.
  • JavaScript
  • React
  • React-router-dom
  • Bulma
  • VSCode
  • Git/GitHub
  • Insomnia/Postman
  • @nivo/bar
  • @nivo/pie
  • iso-3166-1

Loading Countries Loaded Countries

function iso3SortedList(arr){
    const countries = arr.map(item=>{
        const {country:countryName,alpha3:countryCode} = iso.whereAlpha3(item.key)
        return {countryName,countryCode}
    })
    return countries.sort((current,next)=>current.countryName.localeCompare(next.countryName))
}

const [dropdownList,setDropdownList] = useState(undefined);
    useEffect(()=>{
        async function getCountriesNames(){
            const response = await fetch('https://api.carboncloud.com/v0/search', {
                headers: {
                Accept: 'application/json',
                "X-API-KEY" : process.env.REACT_API_KEY,
                },
                })
            const data = await response.json()
            const buckets =data.aggregations.Markets.Markets.buckets
            setDropdownList(iso3SortedList(buckets))
        }
        getCountriesNames()
    }
    ,[])

API returns deeply nested ISO3 code of available countries from the initial search which will be used to generate future queries for products. To use it for dropdown we have used iso-3166-1 library to get full names of the countries. We have also made a sorting function iso3SortedList(arr) to clean up the code and make it more reusable.

Stages Dropdown

const stages = {
    DistributionCenter: "At Distribution Center",
    Factory:"At Factory",
    Farm:"At Farm",
    StoreShelf:"At Store",
    NoSpecific:"Unspecified"
}
...

<select onChange={(e)=>{setStageOption(e.target.value)}}>
    <option hidden>Select Stage &#127981;</option>
    {Object.entries(stages).map((stage,i)=>{
        return <option key={i} value={stage[0]}>{stage[1]}</option>
    })}
</select>

Stages object is imported from reusable forlder to generate currently available stages. This information is not accessible by API call hence had to be hardcoded.

Submit Search

<div className="column"><CountryDropdown setMarketCode={setMarketCode}/></div>
<div className="column"><StageDropdown setStageOption={setStageOption}/></div>

Renders Market and Stage dropdowns.

function displayError(){
    const text = "Please select"
    if(!marketCode&&!stageOption){return <p>{text} Market and Stage</p>} 
    else if(!marketCode){return <p>{text} Market</p>}
    else if(!stageOption){return <p>{text} Stage </p>}
    else return ""
}

displayError function returns a paragraph or empty string. Apart from displaying missing information for submission it also used as validator within handleSubmitForm.

function handleSubmitForm(e){
    e.preventDefault()
    if(displayError()){return}
    navigate(`/search/market=${marketCode}&stage=${stageOption}`, {state:{market:marketCode,stage:stageOption}});
    }
    ...


{displayError()}
<button onClick={(e)=>{handleSubmitForm(e)}} className=" button is-primary is-small">Check CO2</button>

handleSubmitForm checks if displayError returns truthy value indicating that there are parameters missing to return early. if falsy value is returned - form will be "submitted" and navigation to path with will triggered.

<Route path={`/search/market=:market&stage=:stage`} element={
<BasketContext.Provider value={[interestedInArr,setInterestedInArr,wantToAvoidArr,setWantToAvoidArr]}>
    <SearchResults/>
</BasketContext.Provider>
} />

useContext is used to pass currently selected items to the <SearchResults/> element and its children from <App/>.

market = useLocation().state.market
stage = useLocation().state.stage

set market and stage from form submission.

if(!market){ market = useParams().market}
if(!stage){ stage = useParams().stage}

if no data has been provided via form, take :market and stage parameters from url. !This works only in development and crashes in production. It will be discussed in bugs section.

const stages = ["DistributionCenter","Factory","StoreShelf","NoSpecific"]
    if(stage==="Farm"){return <FarmResults market={market} stage={stage} />
    } else if(stages.includes(stage)){ return <DisCenterFactoryStoreUnspecifiedResults market={market} stage={stage} />
    }

Renders Farm or Other stages depending on selected stage. Both components will make requests to https://api.carboncloud.com/v0/search?q=&market=${market}&gate=${stage}. However returned data will differ and will be listed in next two snippets.

 const arr = hits.map(item=>{
    return {
        id:item._id,
        productName:item._source.productName,
        market:item._source.locationCode,
        totalFootprint:item._source.totalClimateFootprint,
        
        totalCH4Footprint:item._source.totalCh4ClimateFootprint,
        totalN2oFootprint:item._source.totalN2oClimateFootprint,
        totalCo2Footprint:item._source.totalCo2ClimateFootprint,

        co2Breakdown:{
            drying:item._source.co2Drying,
            irrigation: item._source.co2Irrigation,
            farmMachinery: item._source.co2Machinery,
            pesticideProduction: item._source.co2PesticideProduction,
            Deforestation: item._source.co2LandUseChange,
            OrganicSoils: item._source.co2OrganicSoils,
            FertilizerProduction: item._source.co2FertilizerProduction,
        },
        productInfo:`https://apps.carboncloud.com/climatehub/agricultural-reports/benchmarks/${item._id}`
    }})

Data collected from requests to Farm Stage

const arr = data.hits.hits.map(item=>{
    return {
        id:item._id,
        productName:item._source.productName,
        market:item._source.market,
        totalFootprint:item._source.totalFootprint,
        footprintBreakdown:item._source.footprintBreakdown,
        imageUrl:item._source.imageUrl,
        productInfo:item._source.reportUrl
    }
})

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 97.5%
  • HTML 1.8%
  • SCSS 0.7%