{"version":3,"sources":["constants.ts","i18n.ts","assets/right-pointing-chevrons.svg","context/AppConfigContext.ts","context/FilterStatesContext.ts","hooks/useLanguage.ts","assets/logo-text.svg","components/modal/Modal.tsx","components/about/About.tsx","components/reports/Reports.tsx","util.ts","components/filter/Filter.tsx","hooks/useFilter.ts","components/filters/Filters.tsx","assets/logo.svg","components/footer/Footer.tsx","components/loadingoverlay/LoadingOverlay.tsx","context/OrganisationsContext.ts","components/focuses/Focuses.tsx","components/map/util.ts","components/map/OrganisationMarker.tsx","components/map/Map.tsx","components/mobilecontrols/MobileControls.tsx","assets/left-pointing-chevrons.svg","components/navbar/Navbar.tsx","components/navbar/IntroText.tsx","csv.ts","assets/women-led.svg","assets/youth-led.svg","assets/registered.svg","components/orglistitem/OrgListItem.tsx","components/orglist/OrgList.tsx","assets/email.svg","assets/link.svg","components/orgview/OrgView.tsx","components/app/App.tsx","services/API.ts","providers/AppConfigProvider.tsx","providers/FilterStatesProvider.tsx","providers/OrganisationsProvider.tsx","index.tsx"],"names":["API_URL","process","TRUE_CONSTANT","resources","en","translation","fr","i18n","use","LanguageDetector","initReactI18next","init","fallbackLng","interpolation","escapeValue","supportedLngs","_extends","Object","assign","target","i","arguments","length","source","key","prototype","hasOwnProperty","call","apply","this","_objectWithoutProperties","excluded","sourceKeys","keys","indexOf","_objectWithoutPropertiesLoose","getOwnPropertySymbols","sourceSymbolKeys","propertyIsEnumerable","d","_ref3","SvgRightPointingChevrons","_ref","svgRef","title","titleId","props","width","height","viewBox","fill","xmlns","ref","id","ForwardRef","AppConfigContext","createContext","FilterStatesContext","useTranslation","language","split","Modal","onClickOutside","children","overlayRef","useRef","useEffect","clickListener","e","current","contains","document","body","addEventListener","keyboardListener","removeEventListener","className","About","t","history","useHistory","push","href","rel","src","LogoWithText","alt","Reports","titleCase","str","map","s","substring","toLocaleUpperCase","toLocaleLowerCase","join","getTranslation","content","values","Filter","config","useState","show","setShow","fieldName","useContext","filterStates","setFilterState","filterState","find","item","nextValues","useFilter","setValues","useLanguage","label","labels","options","onCheckOption","value","checked","includes","filter","v","type","on","style","zoom","onChange","onClick","icon","faChevronUp","faChevronDown","o","htmlFor","count","Filters","filters","f","Footer","Logo","role","to","tabIndex","LoadingOverlay","OrganisationsContext","Focuses","focuses","focus","extractLatLng","org","coordinatesField","cleanCoordinates","data","trim","Number","n","OrganisationMarker","organisation","onHide","latLng","organisationFieldNames","coordinates","slug","reduce","acc","cur","concat","extractFocuses","slice","latitude","longitude","anchor","marginBottom","onMouseLeave","name","OUTLINE_COLOR","COLOR_SCALE","Map","autofocus","sidebarOpen","orgListOpen","hoveredOrganisation","setHoveredOrganisation","viewMode","organisations","focusedOrganisation","setMap","mapRef","setLocationFilter","viewport","setViewport","orgGeoJSON","useMemo","orgs","organisationCoordinatesField","organisationSizeField","size","features","geometry","properties","parseInt","updateLocationFilter","useCallback","bounds","getBounds","getNorthWest","north","lat","west","lng","getSouthEast","south","east","getMap","resize","easeTo","center","maxDuration","setTimeout","geoJSON","calcBounds","fitBounds","padding","onHoverPoint","feature","flexGrow","mapStyle","accessToken","onLoad","onViewportChange","showCompass","showZoom","position","cluster","paint","property","stops","maxzoom","cursor","m","queryRenderedFeatures","point","layers","clusterId","cluster_id","getSource","getClusterExpansionZoom","err","layout","minzoom","lngLat","onEnter","maxWidth","unit","MobileControls","onToggleFilters","onToggleMap","filtersHidden","mapHidden","disabled","SvgLeftPointingChevrons","Navbar","setSidebarOpen","IntroText","escapeQuotes","replace","stringify","dicts","columns","rows","dict","row","c","createProfileElement","elementConfig","currency","console","log","noData","FCFA_TO_USD_RATE","contentType","items","uniqueItems","x","womenLedIcon","youthLedIcon","registeredIcon","toFixed","toLocaleString","sum","createProfileTable","createProfileHtml","OrgListItem","highlight","appConfig","linkClasses","classNames","organisationSummary","OrgList","setOrgListOpen","loading","locationFilter","limit","setLimit","copied","setCopied","sort","orgA","orgB","cleanName","replaceAll","cleanOrgAName","cleanOrgBName","localeCompare","visibleOrganisations","download","encodeURIComponent","faDownload","textField","createElement","innerText","window","location","appendChild","navigator","platform","setSelectionRange","select","execCommand","remove","faLink","getMarkdownText","text","rawMarkup","marked","parse","smartLists","breaks","__html","OrgView","useParams","organisationDisplay","setFocusedOrganisation","email","extractEmailAddress","webAddress","rawWebAddress","webAddresses","Array","from","getUrls","address","extractWebAddress","EmailIcon","LinkIcon","heading","dangerouslySetInnerHTML","col","j","App","setCurrency","ready","innerWidth","isMobile","setMobile","setFiltersHidden","setMapHidden","clearAllFilters","resizeListener","isNowMobile","setViewMode","closedLeftPanel","openLeftPanel","orgListColumnClasses","openOrgList","closedOrgList","panelContainerClasses","mapColumnClasses","pointButtonClasses","heatmapButtonClasses","changeLanguage","path","client","axios","create","API","refreshAppData","appData","get","onDownloadProgress","progressEvent","progressStatus","querySelector","textContent","Math","round","loaded","response","display_config","summary","profile","name_fieldname","country","country_fieldname","coords_fieldname","jeunes","jeunes_fieldname","femmes","femmes_fieldname","borderBase","border_base_fieldname","registered","registered_fieldname","size_fieldname","budget","budget_fieldname","parseOrganisationData","extractFilterOptions","error","message","loadAppData","filterConfigs","result","filterConfig","orgValue","matchingOption","Boolean","dataInLanguage","versions","version","latestData","cleanData","clean","deriveOrganisationFocus","data_id","toLowerCase","cleanValue","isEUR","isUSD","USD_TO_FCFA","USD_TO_FCFA_RATE","EUR_TO_FCFA","EUR_TO_FCFA_RATE","scalar","intVal","toPrecision","prepareOptions","rawValue","allValues","uniqueValues","obj","option","last","a","b","String","AppConfigProvider","setReady","setConfig","loadConfig","loadedConfig","load","reload","Provider","FilterStatesProvider","search","params","endsWith","decodeURIComponent","loadFilters","setFilters","nextFilters","query","url","pathname","pushState","saveFilters","OrganisationsProvider","setLoading","setOrganisations","loadOrganisations","ReactDOM","render","StrictMode","getElementById"],"mappings":"6OAAaA,EAAUC,qEAWVC,EAAgB,MCFvBC,EAAY,CAChBC,GAAI,CACFC,Y,OAEFC,GAAI,CACFD,Y,QAIJE,IACGC,IAAIC,KACJD,IAAIE,KACJC,KAAK,CACJR,YACAS,YDnB4B,KCoB5BC,cAAe,CACbC,aAAa,GAEfC,cAAe,CAAC,KAAM,QAGXR,QAAf,E,+CC9BA,SAASS,IAA2Q,OAA9PA,EAAWC,OAAOC,QAAU,SAAUC,GAAU,IAAK,IAAIC,EAAI,EAAGA,EAAIC,UAAUC,OAAQF,IAAK,CAAE,IAAIG,EAASF,UAAUD,GAAI,IAAK,IAAII,KAAOD,EAAcN,OAAOQ,UAAUC,eAAeC,KAAKJ,EAAQC,KAAQL,EAAOK,GAAOD,EAAOC,IAAY,OAAOL,IAA2BS,MAAMC,KAAMR,WAEhT,SAASS,EAAyBP,EAAQQ,GAAY,GAAc,MAAVR,EAAgB,MAAO,GAAI,IAAkEC,EAAKJ,EAAnED,EAEzF,SAAuCI,EAAQQ,GAAY,GAAc,MAAVR,EAAgB,MAAO,GAAI,IAA2DC,EAAKJ,EAA5DD,EAAS,GAAQa,EAAaf,OAAOgB,KAAKV,GAAqB,IAAKH,EAAI,EAAGA,EAAIY,EAAWV,OAAQF,IAAOI,EAAMQ,EAAWZ,GAAQW,EAASG,QAAQV,IAAQ,IAAaL,EAAOK,GAAOD,EAAOC,IAAQ,OAAOL,EAFxMgB,CAA8BZ,EAAQQ,GAAuB,GAAId,OAAOmB,sBAAuB,CAAE,IAAIC,EAAmBpB,OAAOmB,sBAAsBb,GAAS,IAAKH,EAAI,EAAGA,EAAIiB,EAAiBf,OAAQF,IAAOI,EAAMa,EAAiBjB,GAAQW,EAASG,QAAQV,IAAQ,GAAkBP,OAAOQ,UAAUa,qBAAqBX,KAAKJ,EAAQC,KAAgBL,EAAOK,GAAOD,EAAOC,IAAU,OAAOL,EAMne,IAAI,EAAqB,gBAAoB,OAAQ,CACnDoB,EAAG,4FAGDC,EAAqB,gBAAoB,OAAQ,CACnDD,EAAG,+FAGL,SAASE,EAAyBC,EAAMC,GACtC,IAAIC,EAAQF,EAAKE,MACbC,EAAUH,EAAKG,QACfC,EAAQhB,EAAyBY,EAAM,CAAC,QAAS,YAErD,OAAoB,gBAAoB,MAAO1B,EAAS,CACtD+B,MAAO,GACPC,OAAQ,GACRC,QAAS,YACTC,KAAM,UACNC,MAAO,6BACPC,IAAKT,EACL,kBAAmBE,GAClBC,GAAQF,EAAqB,gBAAoB,QAAS,CAC3DS,GAAIR,GACHD,GAAS,KAAM,EAAOJ,GAG3B,IAAIc,EAA0B,aAAiBb,GCpBhCc,GDqBA,ICzBUC,wBACvB,KCOaC,EAJaD,wBAC1B,ICba,aAEb,OADiBE,cAATnD,KACIoD,SAASC,MAAM,KAAK,ICJnB,MAA0B,sCC4C1BC,G,MAzCyC,SAAC,GAGlD,IAFLC,EAEI,EAFJA,eACAC,EACI,EADJA,SAEMC,EAAaC,iBAAuB,MAuB1C,OArBAC,qBAAU,WACR,IAAMC,EAAgB,SAACC,GAAmB,IAAD,GACvC,OAAIJ,QAAJ,IAAIA,GAAJ,UAAIA,EAAYK,eAAhB,aAAI,EAAqBC,SAASF,EAAEjD,UAClC2C,KAGJS,SAASC,KAAKC,iBAAiB,QAASN,GAExC,IAAMO,EAAmB,SAACN,GACV,WAAVA,EAAE5C,KACJsC,KAKJ,OAFAS,SAASE,iBAAiB,UAAWC,GAE9B,WACLH,SAASC,KAAKG,oBAAoB,QAASR,GAC3CI,SAASI,oBAAoB,UAAWD,MAEzC,CAACZ,IAGF,sBAAKc,UAAU,+EAAf,UACE,qBACEvB,GAAG,gBACHuB,UAAU,6EACVxB,IAAKY,IAEP,qBAAKY,UAAU,8FAAf,SACE,qBAAKA,UAAU,oCAAf,SAAoDb,WCN7Cc,EAzBS,WAAO,IACrBC,EAAMpB,cAANoB,EACFC,EAAUC,cAEhB,OACE,cAAC,EAAD,CAAOlB,eAAgB,kBAAMiB,EAAQE,KAAK,MAA1C,SACE,sBAAKL,UAAU,OAAf,UACE,oBAAIA,UAAU,gBAAd,SAA+BE,EAAE,WACjC,oBAAIF,UAAU,SACd,mBAAGA,UAAU,OAAb,SAAqBE,EAAE,oBACvB,mBAAGF,UAAU,OAAb,SAAqBE,EAAE,oBACvB,mBAAGF,UAAU,OAAb,SAAqBE,EAAE,sBACvB,mBAAGF,UAAU,OAAb,SAAqBE,EAAE,qBACvB,mBACEI,KAAK,wCACL/D,OAAO,SACPgE,IAAI,aAHN,SAKE,qBAAKC,IAAKC,EAAcC,IAAKR,EAAE,0CCc1BS,EAjCW,WAAO,IACvBT,EAAMpB,cAANoB,EACFC,EAAUC,cAEhB,OACE,cAAC,EAAD,CAAOlB,eAAgB,kBAAMiB,EAAQE,KAAK,MAA1C,SACE,sBAAKL,UAAU,OAAf,UACE,oBAAIA,UAAU,gBAAd,SAA+BE,EAAE,aACjC,oBAAIF,UAAU,SACd,oBAAIA,UAAU,eAAd,0BACA,qBAAIA,UAAU,OAAd,UACE,6BAAI,mBAAGA,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,yCAA/D,2BACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,iCAA/D,mBACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,kCAA/D,oBACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,mCAA/D,wBAEN,oBAAIF,UAAU,eAAd,kBACA,qBAAIA,UAAU,OAAd,UACE,6BAAI,mBAAGA,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,yBAA/D,mBACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,2BAA/D,qBACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,2BAA/D,qBACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,gCAA/D,6BAEN,oBAAIF,UAAU,eAAd,mBACA,qBAAIA,UAAU,OAAd,UACE,6BAAI,mBAAGA,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,4BAA/D,qBACJ,6BAAI,mBAAGF,UAAU,2BAA2BzD,OAAO,QAAQ+D,KAAMJ,EAAE,gCAA/D,kC,yCC1BDU,EAAY,SAACC,GAAD,OACvBA,EACG7B,MAAM,OACN8B,KACC,SAACC,GAAD,gBACKA,EAAEC,UAAU,EAAG,GAAGC,qBADvB,OAC6CF,EACxCC,UAAU,GACVE,wBAENC,KAAK,MAEGC,EAAiB,SAC5BC,EACAtC,GAEA,MAAuB,kBAAZsC,EACFA,EAEFA,EAAQtC,IAAa1C,OAAOiF,OAAOD,GAAS,ICqDtCE,EApEoC,SAAC,GAAgB,IAAdC,EAAa,EAAbA,OAAa,EACzCC,oBAAS,GADgC,mBAC1DC,EAD0D,KACpDC,EADoD,OCNpD,SACbC,GACgD,IAAD,EACNC,qBAAWhD,GAA5CiD,EADuC,EACvCA,aAAcC,EADyB,EACzBA,eAEhBC,EAAcF,EAAaG,MAAK,SAACC,GAAD,OAAUA,EAAKN,YAAcA,KAQnE,MAAO,EANmB,OAAXI,QAAW,IAAXA,OAAA,EAAAA,EAAaV,SAAU,GAEpB,SAACa,GACjBJ,EAAeH,EAAWO,KDFAC,CAAUZ,EAAOI,WAFoB,mBAE1DN,EAF0D,KAElDe,EAFkD,KAI3DtD,EAAWuD,IACXC,EAAQnB,EAAeI,EAAOgB,OAAQzD,GAE5C,IAAKyC,EAAOiB,QAEV,OAAO,KAGT,IAAMC,EAAgB,SAACC,EAAeC,GAChCA,IAAYtB,EAAOuB,SAASF,GAC9BN,EAAU,GAAD,mBAAKf,GAAL,CAAaqB,MACZC,GAAWtB,EAAOuB,SAASF,IACrCN,EAAUf,EAAOwB,QAAO,SAACC,GAAD,OAAOA,IAAMJ,OAIzC,GAAoB,YAAhBnB,EAAOwB,KAAoB,CAC7B,IAAMC,EAAK3B,EAAO,KAAOhG,EACzB,OACE,sBAAK0E,UAAU,iDAAf,UACE,oBAAIA,UAAU,8BAAd,SAA6CuC,IAC7C,uBACES,KAAK,WACLE,MAAO,CAAEC,KAAM,KACfC,SAAU,kBAAMV,EAAcpH,GAAgB2H,SAMtD,OACE,sBAAKjD,UAAU,6CAAf,UACE,wBACEA,UAAS,0BAAqB0B,EAAO,OAAS,IAC9CsB,KAAK,SACLK,QAAS,kBAAM1B,GAASD,IAH1B,SAKE,uBAAM1B,UAAU,oBAAhB,UACE,oBAAIA,UAAU,8BAAd,SAA6CuC,IAC7C,cAAC,IAAD,CAAiBe,KAAM5B,EAAO6B,IAAcC,WAGhD,oBAAIxD,UAAS,0BAAqB0B,EAAO,GAAK,OAA9C,SACGF,EAAOiB,QAAQ3B,KAAI,SAAC2C,GAAD,OAClB,qBAAkBzD,UAAU,yBAA5B,UACE,uBACEvB,GAAE,UAAK8D,EAAL,YAAckB,EAAElB,OAClBvC,UAAU,OACVkD,MAAO,CAAEC,KAAM,KACfH,KAAK,WACLJ,QAAStB,EAAOuB,SAASY,EAAEd,OAC3BS,SAAU,SAAC5D,GAAD,OAAOkD,EAAce,EAAEd,MAAOnD,EAAEjD,OAAOqG,YAEnD,uBAAOc,QAAO,UAAKnB,EAAL,YAAckB,EAAElB,OAASvC,UAAU,mBAAjD,SACGoB,EAAeqC,EAAElB,MAAOxD,KAE3B,sBAAMiB,UAAU,gBAAhB,SAAiCyD,EAAEE,UAZ5BF,EAAEd,gBErCNiB,EAhBW,WAAO,IAEnBC,EACRhC,qBAAWlD,GADb6C,OAAUqC,QAGZ,OACE,oBAAI7D,UAAU,uBAAd,SACG6D,EAAQ/C,KAAI,SAACgD,GAAD,OACX,6BACE,cAAC,EAAD,CAAQtC,OAAQsC,KADTA,EAAElC,iBCZJ,MAA0B,iCCsC1BmC,EAjCU,WAAO,IACtB7D,EAAMpB,cAANoB,EAER,OACE,yBAAQF,UAAU,+CAAlB,UACE,mBACEM,KAAK,wCACL/D,OAAO,SACPgE,IAAI,aAHN,SAKE,qBACEP,UAAU,YACVU,IAAKR,EAAE,kDACPM,IAAKwD,MAGT,gCACE,8BACG9D,EAAE,yBAEL,cAAC,IAAD,CACEF,UAAU,yCACViE,KAAK,OACLC,GAAG,SACHC,SAAU,EAJZ,SAMGjE,EAAE,yBCtBEkE,EAPkB,kBAC/B,sBAAKpE,UAAU,yFAAf,UACE,qBAAKA,UAAU,mDACf,qBAAKA,UAAU,uBAAuBvB,GAAG,iB,QCY9B4F,G,OAJczF,wBAC3B,KCQa0F,EAjBV,SAAC,GAAiB,IAAfC,EAAc,EAAdA,QACErE,EAAMpB,cAANoB,EAER,OACE,qBAAKF,UAAU,YAAf,SACGuE,EAAQzD,KAAI,SAAC0D,GAAD,OACX,qBAEExE,UAAU,oDAFZ,SAIGE,EAAEsE,IAHEA,S,QCDFC,EAAgB,SAC3BC,EACAC,GAEA,IACMC,GADiBF,EAAIG,KAAKF,IAAqB,IAElDG,OACA9F,MAAM,SACN8B,IAAIiE,QACJjC,QAAO,SAACkC,GAAD,OAAOA,GAAKA,EAAI,IAAMA,GAAK,MACrC,OAAmC,IAA5BJ,EAAiBlI,OAAekI,EAAmB,MC0B7CK,EAnCV,SAAC,GAA8B,IAA5BC,EAA2B,EAA3BA,aAAcC,EAAa,EAAbA,OACZ3D,EAAWK,qBAAWlD,GAAtB6C,OACF4D,EAASX,EACbS,EACA1D,EAAO6D,uBAAuBC,aAGhC,IAAKF,EACH,OAAO,KARwB,IAWzBP,EAAeK,EAAfL,KAAMU,EAASL,EAATK,KAERhB,EV2BsB,SAACM,GAG7B,OAFuBA,EAAK,mCAGzB7F,MAAM,KACN8B,KAAI,SAACtB,GAAD,OAAOA,EAAER,MAAM,QACnBwG,QAAO,SAACC,EAAKC,GAAN,OAAcA,EAAIC,OAAOF,KAAM,IACtC3C,QAAO,SAACtD,GAAD,QAASA,KAChBsB,KAAI,SAACC,GAAD,OAAOH,EAAUG,MUnCR6E,CAAef,GAAMgB,MAAM,EAAG,GAE9C,OACE,cAAC,IAAD,CAAQC,SAAUV,EAAO,GAAIW,UAAWX,EAAO,GAAIY,OAAO,SAA1D,SACE,qBACE9C,MAAO,CAAE+C,aAAc,SACvBjG,UAAU,QACVkG,aAAcf,EAHhB,SAKE,qBAAKnF,UAAU,gCAAf,SACE,eAAC,IAAD,CAAMkE,GAAE,WAAMqB,GAAQlC,QAAS8B,EAA/B,UACE,oBAAInF,UAAU,sBAAd,SACG6E,EAAKrD,EAAO6D,uBAAuBc,QAErC5B,EAAQ7H,OAAS,GAAK,cAAC,EAAD,CAAS6H,QAASA,cCL/C6B,EAAgB,UAEhBC,GAAc,CALA,gBACK,sBACD,uBA8STC,GAhSV,SAAC,GAOC,IAAD,IANJC,iBAMI,SALJC,EAKI,EALJA,YACAC,EAII,EAJJA,YACAC,EAGI,EAHJA,oBACAC,EAEI,EAFJA,uBACAC,EACI,EADJA,SAEQpF,EAAWK,qBAAWlD,GAAtB6C,OADJ,EAQAK,qBAAWwC,GALbwC,EAHE,EAGFA,cACAC,EAJE,EAIFA,oBACAC,EALE,EAKFA,OACAjG,EANE,EAMFA,IACAkG,EAPE,EAOFA,OAEMC,EAAsBpF,qBAAWhD,GAAjCoI,kBATJ,EAU4BxF,mBAAS,CACvCqE,SAAU,GACVC,UAAW,EACX5C,KAAM,IAbJ,mBAUG+D,EAVH,KAUaC,EAVb,KAiBEC,EAAaC,mBAAiB,WAClC,OFKFC,EEJIT,EFKJU,EEJI/F,EAAO6D,uBAAuBC,YFKlCkC,EEJIhG,EAAO6D,uBAAuBoC,KFM3B,CACLzE,KAAM,oBACN0E,SAAUJ,EACPxG,KAAI,SAAC4D,GAAD,MAAU,CACbjG,GAAIiG,EAAIjG,GACRoG,KAAMH,EAAIG,KACVO,OAAQX,EAAcC,EAAK6C,OAE5BzE,QAAO,SAAC4B,GAAD,OAASA,EAAIU,UACpBtE,KAAI,SAAC4D,GAAD,MAAU,CACb1B,KAAM,UACN2E,SAAU,CACR3E,KAAM,QACNsC,YAAaZ,EAAIU,OAAS,CAACV,EAAIU,OAAO,GAAIV,EAAIU,OAAO,IAAM,CAAC,EAAG,IAEjEwC,WAAY,CACVnJ,GAAIiG,EAAIjG,GACRgJ,KAAMI,SAASnD,EAAIG,KAAK2C,GAAwB,KAAO,QAtBpB,IAC3CF,EACAC,EACAC,IEFG,CACDhG,EAAO6D,uBAAuBC,YAC9B9D,EAAO6D,uBAAuBoC,KAC9BZ,IAIIiB,EAAuBC,uBAAY,WACvC,IAAMC,EAAUlH,EAAYmH,YADiB,EAEXD,EAAOE,eAA5BC,EAFgC,EAErCC,IAAiBC,EAFoB,EAEzBC,IAFyB,EAGXN,EAAOO,eAA5BC,EAHgC,EAGrCJ,IAAiBK,EAHoB,EAGzBH,IACpBrB,EAAkB,CAChB,CAACoB,EAAMF,GACP,CAACM,EAAMD,OAER,CAAC1H,EAAKmG,IAET3H,qBAAU,WAAO,IAAD,EACT0H,GAIAA,EAAOvH,UAKN,OAANuH,QAAM,IAANA,GAAA,UAAAA,EAAQvH,eAAR,SAAiBiJ,SAASC,YACzB,CAACnC,EAAaC,EAAaO,IAG9B1H,qBAAU,WACR,GAAKwB,EAIL,GAAIgG,EAAqB,CACvB,IAAM1B,EAAS0B,EACXrC,EACEqC,EACAtF,EAAO6D,uBAAuBC,aAEhC,KAEAF,GAAUmB,IAEXzF,EAAY8H,OAAO,CAClBC,OAAQ,CAACzD,EAAO,GAAIA,EAAO,IAC3BjC,KAAM,GACN2F,YAAa,MAIfC,WAAWjB,EAAsB,UAE9B,CAEL,IAAME,EF9Gc,SAACgB,GACzB,IAD6D,EACzDb,EAAQ,KACRE,EAAO,KACPG,EAAQ,KACRC,EAAO,KAJkD,cAMvCO,EAAQtB,UAN+B,IAM7D,2BAAwC,CAAC,IAC/BpC,EAD8B,QACNqC,SAAxBrC,cAEH+C,GAAQ/C,EAAY,GAAK+C,KAC3BA,EADiC,YACzB/C,EADyB,SAI/B6C,GAAS7C,EAAY,GAAK6C,KAC1BA,EADiC,YACxB7C,EADwB,SAIjCmD,GAAQnD,EAAY,GAAKmD,KAC3BA,EADiC,YACzBnD,EADyB,SAI/BkD,GAASlD,EAAY,GAAKkD,KAC1BA,EADiC,YACxBlD,EADwB,QArBqB,8BA0B7D,OAAI6C,GAASM,GAAQD,GAASH,EACrB,CACL,CAACA,EAAMF,GACP,CAACM,EAAMD,IAIJ,KE6EYS,CAAW7B,GACtBY,GACDlH,EAAYoI,UAAUlB,EAAQ,CAAEmB,QAAS,KAI5ClC,EAAkB,SAEnB,CACDnG,EACAsG,EACAN,EACAtF,EAAO6D,uBAAuBC,YAC9BwC,EACAb,EACAV,IAGF,IA8BM6C,EAAe,SAAC5J,GAAY,IACxBkI,EAAalI,EAAbkI,SAER,GAAI,OAACA,QAAD,IAACA,OAAD,EAACA,EAAUhL,OAAf,CAKA,IAAM2M,EAAU3B,EAAS,GAEnBxC,EAAe2B,EAAc5E,MACjC,SAACyC,GAAD,OAASA,EAAIjG,KAAO4K,EAAQzB,WAAWnJ,MAGzCkI,EAAuBzB,QAVrByB,EAAuB,OAkB3B,OACE,mCACE,eAAC,IAAD,CACEzD,MAAO,CAAEoG,SAAU,EAAGnL,MAAO,OAAQC,OAAQ,QAC7CmL,SrB9MoBlO,yDqB+MpBmO,YrBhN2BnO,mGqBiN3ByK,SAAUoB,EAASpB,SACnBC,UAAWmB,EAASnB,UACpB5C,KAAM+D,EAAS/D,KACfsG,OArCS,SAACjK,IACTsB,IAAD,OAAQtB,QAAR,IAAQA,OAAR,EAAQA,EAAGjD,SACbwK,EAAOvH,EAAEjD,SAoCPmN,iBA9DmB,SAAC3G,GACxBoE,EAAYpE,GACZ+E,KA6DItJ,IAAKwI,EATP,UAWE,cAAC,IAAD,CACE2C,aAAa,EACbC,UAAQ,EACRC,SAAS,iBAEX,cAAC,IAAD,CAAQpL,GAAG,gBAAgBuE,KAAK,UAAU6B,KAAMuC,IAChD,cAAC,IAAD,CAAQ3I,GAAG,UAAUuE,KAAK,UAAU6B,KAAMuC,EAAY0C,SAAO,IAC/C,YAAblD,EACC,cAAC,IAAD,CACEnI,GAAG,gBACHuE,KAAK,UACLrG,OAAO,gBACPoN,MAAO,CAEL,iBAAkB,CAChBC,SAAU,OACVhH,KAAM,cACNiH,MAAO,CACL,CAAC,EAAG,GACJ,CAAC,IAAK,GACN,CAAC,IAAO,GACR,CAAC,IAAQ,KAIb,gBAAiB,CACf,cACA,CAAC,UACD,CAAC,mBACD,EACA5D,GAAY,GACZ,GACAA,GAAY,GACZ,EACAA,GAAY,OAKlB,qCACE,cAAC,IAAD,CACE5H,GAAG,UACHuE,KAAK,SACLrG,OAAO,UACPuN,QAAS,EACTpH,OAAQ,CAAC,MAAO,eAChBI,MAAO,CAAEiH,OAAQ,WACjB9G,QA3GW,SAAC7D,GACtB,IAAM4K,EAAItJ,EACJ4G,EAAW0C,EAAEC,sBAAsB7K,EAAE8K,MAAO,CAChDC,OAAQ,CAAC,aAELC,EAAY9C,EAAS,GAAGE,WAAW6C,WACzCL,EAAEM,UAAU,WAAWC,wBACrBH,GACA,SAACI,EAAYzH,GACPyH,GAEJR,EAAExB,OAAO,CACPC,OAAQnB,EAAS,GAAGC,SAASrC,YAC7BnC,aA+FI4G,MAAO,CACL,sBAAuB,EACvB,sBAAuB3D,EACvB,iBAAkB,GAClB,eAAgB,CACdpD,KAAM,WACNgH,SAAU,cACVC,MAAO,CACL,CAAC,EAAG5D,GAAY,IAChB,CAAC,EAAGA,GAAY,MAGpB,gBAAiB,CACfrD,KAAM,cACNgH,SAAU,cACVC,MAAO,CACL,CAAC,EAAG,IACJ,CAAC,GAAI,SAKb,cAAC,IAAD,CACExL,GAAG,gBACHuE,KAAK,SACLrG,OAAO,UACPuN,QAAS,EACTW,OAAQ,CACN,aAAc,4BACd,YAAa,MAGjB,cAAC,IAAD,CACEpM,GAAG,sBACHuE,KAAK,SACLrG,OAAO,gBACPmO,QAAS,EACThI,OAAQ,CAAC,IAAK,CAAC,MAAO,gBACtBO,QAxGS,SAAC7D,GACpB4J,EAAa5J,GACZsB,EAAY8H,OAAO,CAAEC,OAAQrJ,EAAEuL,UAuGtBC,QAAS5B,EACTW,MAAO,CACL,eAAgB1D,GAAY,GAC5B,gBAAiB,GACjB,sBAAuB,EACvB,sBAAuBD,QAK9BM,EACC,cAAC,EAAD,CACExB,aAAcwB,EACdvB,OAAQ,kBAAMwB,EAAuB,SAErC,KACJ,cAAC,IAAD,CAAcsE,SAAU,IAAKC,KAAK,SAASrB,SAAS,gBACpD,sBAAK7J,UAAU,kCAAf,UACE,sBAAKA,UAAU,qCAAf,UACE,kCACA,uCAEF,qBAAKA,UAAU,iEAAf,wBC7RKmL,GAjCV,SAAC,GAAgE,IAA9DC,EAA6D,EAA7DA,gBAAiBC,EAA4C,EAA5CA,YAAaC,EAA+B,EAA/BA,cAAeC,EAAgB,EAAhBA,UAC3CrL,EAAMpB,cAANoB,EACR,OACE,sBAAKF,UAAU,qBAAf,UACE,wBAAQgD,KAAK,SAASK,QAAS+H,EAAiBpL,UAAU,eAA1D,SACGE,EAAEoL,EAAgB,qBAAuB,wBAE5C,gCACE,wBACEtI,KAAK,SACLK,QAASgI,EACTrL,UAAS,uDACPuL,EAAY,cAAgB,IAE9BC,SAAUD,EANZ,SAQGrL,EAAE,iBAEL,wBACE8C,KAAK,SACLK,QAASgI,EACTrL,UAAS,4CACPuL,EAAY,GAAK,eAEnBC,UAAWD,EANb,SAQGrL,EAAE,uBClCb,SAAS,KAA2Q,OAA9P,GAAW7D,OAAOC,QAAU,SAAUC,GAAU,IAAK,IAAIC,EAAI,EAAGA,EAAIC,UAAUC,OAAQF,IAAK,CAAE,IAAIG,EAASF,UAAUD,GAAI,IAAK,IAAII,KAAOD,EAAcN,OAAOQ,UAAUC,eAAeC,KAAKJ,EAAQC,KAAQL,EAAOK,GAAOD,EAAOC,IAAY,OAAOL,IAA2BS,MAAMC,KAAMR,WAEhT,SAAS,GAAyBE,EAAQQ,GAAY,GAAc,MAAVR,EAAgB,MAAO,GAAI,IAAkEC,EAAKJ,EAAnED,EAEzF,SAAuCI,EAAQQ,GAAY,GAAc,MAAVR,EAAgB,MAAO,GAAI,IAA2DC,EAAKJ,EAA5DD,EAAS,GAAQa,EAAaf,OAAOgB,KAAKV,GAAqB,IAAKH,EAAI,EAAGA,EAAIY,EAAWV,OAAQF,IAAOI,EAAMQ,EAAWZ,GAAQW,EAASG,QAAQV,IAAQ,IAAaL,EAAOK,GAAOD,EAAOC,IAAQ,OAAOL,EAFxM,CAA8BI,EAAQQ,GAAuB,GAAId,OAAOmB,sBAAuB,CAAE,IAAIC,EAAmBpB,OAAOmB,sBAAsBb,GAAS,IAAKH,EAAI,EAAGA,EAAIiB,EAAiBf,OAAQF,IAAOI,EAAMa,EAAiBjB,GAAQW,EAASG,QAAQV,IAAQ,GAAkBP,OAAOQ,UAAUa,qBAAqBX,KAAKJ,EAAQC,KAAgBL,EAAOK,GAAOD,EAAOC,IAAU,OAAOL,EAMne,IAAI,GAAqB,gBAAoB,OAAQ,CACnDoB,EAAG,kGAGD,GAAqB,gBAAoB,OAAQ,CACnDA,EAAG,oGAGL,SAAS8N,GAAwB3N,EAAMC,GACrC,IAAIC,EAAQF,EAAKE,MACbC,EAAUH,EAAKG,QACfC,EAAQ,GAAyBJ,EAAM,CAAC,QAAS,YAErD,OAAoB,gBAAoB,MAAO,GAAS,CACtDK,MAAO,GACPC,OAAQ,GACRC,QAAS,YACTC,KAAM,UACNC,MAAO,6BACPC,IAAKT,EACL,kBAAmBE,GAClBC,GAAQF,EAAqB,gBAAoB,QAAS,CAC3DS,GAAIR,GACHD,GAAS,KAAM,GAAO,IAG3B,IAAI,GAA0B,aAAiByN,ICLhCC,IDMA,IC5BV,SAAC,GAAwB,IAAtBC,EAAqB,EAArBA,eACEzL,EAAMpB,cAANoB,EAER,OACE,wBAAQF,UAAU,iCAAlB,SACE,qBAAIA,UAAU,4DAAd,UACE,8BAAME,EAAE,WACR,8BACE,wBACE8C,KAAK,SACLK,QAAS,WACPsI,GAAe,IAHnB,SAME,cAAC,GAAD,CAAsB3L,UAAU,uCCG7B4L,GApBa,WAAO,IACzB1L,EAAMpB,cAANoB,EAER,OACE,sBAAKF,UAAU,mGAAf,UACE,mBAAGA,UAAU,OAAb,SAAqBE,EAAE,gCACvB,mBAAGF,UAAU,mBAAb,SACE,cAAC,IAAD,CACEA,UAAU,2BACViE,KAAK,OACLC,GAAG,WACHC,SAAU,EAJZ,SAMGjE,EAAE,wCCfP2L,GAAe,SAAChL,GACpB,MAAM,IAAN,OAAWA,EAAIiL,QAAQ,IAAK,KAA5B,MAIWC,GAAY,SAACC,GACxB,GAAIA,EAAMtP,OAAS,EACjB,MAAO,GAET,IAJkD,EAI5CuP,EAAU5P,OAAOgB,KAAK2O,EAAM,IAC5BE,EAAO,CAACD,EAAQnL,IAAI+K,IAAc1K,KAAK,MALK,cAM/B6K,GAN+B,yBAMvCG,EANuC,QAO1CC,EAAMH,EAAQnL,KAAI,SAACuL,GAAD,OAAOR,GAAaM,EAAKE,OAAKlL,KAAK,KAC3D+K,EAAK7L,KAAK+L,IAFZ,2BAA2B,IANuB,8BAUlD,OAAOF,EAAK/K,KAAK,OCjBJ,OAA0B,sCCA1B,OAA0B,sCCA1B,OAA0B,uCCc5BmL,GAAuB,SAClC1E,EACA2E,EACAxN,EACAyN,GAEA,IAAInL,EAEJoL,QAAQC,IAAIH,GAKZ,IAAMI,EAAS,6BAAkB,OAAb5N,EAAoB,oBAAmB,YAErD6N,EAAmBvR,2aAAYuR,iBACjC/E,SAASxM,2aAAYuR,iBAAkB,IACvC,MAEJ,GAA2B,UAAvBL,EAAcvJ,KAAkB,CAClC,IAAMpG,EAAM2P,EAAclL,QAE1B,GAAkC,SAA9BkL,EAAcM,YAAwB,CAIxC,IAHA,IAAMC,EAAQlF,EAAWhL,GAAKoC,MAAM,KAC9B+N,EAAwB,GAErBvQ,EAAI,EAAGA,EAAIsQ,EAAMpQ,OAAQF,GAAK,EAAG,CACxC,IAAMwQ,EAAIF,EAAMtQ,GACXuQ,EAAYlK,SAASmK,IACxBD,EAAY1M,KAAK2M,GAIrB3L,EAAU0L,EAAYrQ,OAClB,oBAAIsD,UAAU,yBAAd,SAAwC+M,EAAYjM,KAAI,SAACkM,GAAD,OAAO,6BAAaA,GAAJA,QACxEL,OACC,GAAkC,YAA9BJ,EAAcM,YAA2B,CAClD,IAAIvJ,EACJ,OAAQ1G,GACN,IAAK,aACH0G,EAAO,qBAAK5C,IAAI,gBAAgBF,IAAKyM,KACrC,MACF,IAAK,YACH3J,EAAO,qBAAK5C,IAAI,eAAeF,IAAK0M,KACpC,MACF,QACE5J,EAAO,qBAAK5C,IAAI,2BAA2BF,IAAK2M,KAMpD9L,EAFEuG,EAAWhL,KAAStB,GAAqC,MAApBsM,EAAWhL,GAGhD,uBAAMoD,UAAU,uCAAhB,UACGsD,EACAlC,EAAemL,EAAchK,MAAOxD,MAErC,UAKJsC,EAHQ,kCAARzE,GACQ,gCAARA,EAEUgL,EAAWhL,GAAOmI,OAAO6C,EAAWhL,IAAMwQ,UAAYT,EAG9D,8EADF/P,GAEQ,kBAARA,EAEUgL,EAAWhL,GAAX,WAEJmI,OAAO6C,EAAWhL,KACJ,QAAb4P,EAAqBI,EAAmB,IACzCS,eAAetO,GAJX,YAIwByN,GAC9BG,EAEM/E,EAAWhL,GAAOgL,EAAWhL,GAAO+P,OAE3C,GAA2B,QAAvBJ,EAAcvJ,KAAgB,CAQvC3B,EAPckL,EAAclL,QAAmBrC,MAAM,OAElCwG,QACjB,SAAC8H,EAAK1Q,GAAN,OAAc0Q,EAAMzF,SAASD,EAAWhL,GAAM,MAC9C,IAGiB+P,OAEnBtL,EAAUD,EAAemL,EAAclL,QAAStC,GAGlD,OAAQwN,EAAcM,aACpB,IAAK,QACH,OAAO,sBAAM7M,UAAU,sBAAhB,SAAuCqB,IAChD,IAAK,UACH,OAAO,oBAAIrB,UAAU,2BAAd,SAA0CqB,IACnD,QACE,OAAO,+BAAOA,MAIdkM,GAAqB,SACzB3F,EACA2E,EACAxN,EACAyN,GAEA,OACE,qBACExM,UAAS,eAAUuM,EAAcL,KAAKxP,OAAS,EAAI,cAAgB,IADrE,SAGG6P,EAAcL,KAAKpL,KAAI,SAACU,GACvB,OAAOA,EAAOV,KAAI,SAACoB,EAAM1F,GAAP,OAChB,qBAAawD,UAAU,OAAvB,SACGsM,GAAqB1E,EAAY1F,EAAMnD,EAAUyN,IAD1ChQ,YASdgR,GAAoB,SACxB5F,EACApG,EACAzC,EACAyN,GAEA,OACE,mCACGhL,EAAOV,KAAI,SAACuL,EAAG7P,GAAJ,OACV,8BACG6P,EAAEH,KACCqB,GAAmB3F,EAAYyE,EAAGtN,EAAUyN,GAC5CF,GAAqB1E,EAAYyE,EAAGtN,EAAUyN,IAH1ChQ,SAuCHiR,GAzBV,SAAC,GAAkC,IAAhC/I,EAA+B,EAA/BA,IAAKgJ,EAA0B,EAA1BA,UAAWlB,EAAe,EAAfA,SAChBmB,EAAY9L,qBAAWlD,GACvBI,EAAWuD,IAFoB,EAGjBxD,cAAZoB,EAH6B,EAG7BA,EAEF0N,GAL+B,EAG1BjS,KAESkS,IAClB,8DACc,IAAdH,EAAqB,iBAAmB,aAG1C,OACE,eAAC,IAAD,CAAMxJ,GAAE,WAAMQ,EAAIa,MAAQvF,UAAW4N,EAArC,UACGJ,GACC9I,EAAIG,KACJ8I,EAAUnM,OAAOsM,oBACjB/O,EACAyN,GAEF,wBAAQxJ,KAAK,SAAShD,UAAU,iBAAhC,SACGE,EAAE,iCClCI6N,GAtHV,SAAC,GAAuD,IAArDrH,EAAoD,EAApDA,oBAAqBsH,EAA+B,EAA/BA,eAAgBxB,EAAe,EAAfA,SAE/BnH,EACRxD,qBAAWlD,GADb6C,OAAU6D,uBAF8C,EAIvBxD,qBAAWwC,GAAtCwC,EAJkD,EAIlDA,cAAeoH,EAJmC,EAInCA,QACfC,EAAmBrM,qBAAWhD,GAA9BqP,eACAhO,EAAMpB,cAANoB,EANkD,EAOhCuB,mBAbV,IAM0C,mBAOnD0M,EAPmD,KAO5CC,EAP4C,OAQ9B3M,oBAAS,GARqB,mBAQnD4M,EARmD,KAQ3CC,EAR2C,KAW1DhP,qBAAU,WACR8O,EAlBc,MAmBb,CAACvH,IAEJA,EAAc0H,MAAK,SAACC,EAAMC,GACxB,IAAMC,EAAY,SAACvI,GAAD,OAChBA,EAAKwI,WAAW,IAAK,IAAIA,WAAW,IAAK,IAAIA,WAAW,IAAK,IAAI7J,QAE7D8J,EAAgBF,EAAUF,EAAKrI,MAC/B0I,EAAgBH,EAAUD,EAAKtI,MAErC,OAAOyI,EAAcE,cAAcD,MAGrC,IZWAvH,EACAU,EACAT,EYKMwH,EAAuBb,GZP7B5G,EYSMT,EZRNmB,EYSMkG,EZRN3G,EYSMlC,EAAuBC,YZPtBgC,EAAKxE,QAAO,SAAC4B,GAClB,IAAMY,EAAcb,EAAcC,EAAK6C,GACvC,IAAKjC,EACH,OAAO,EAHiB,kBAKPA,EALO,GAKnB8C,EALmB,KAKdE,EALc,mBAMaN,EANb,yBAMlBK,EANkB,KAMZF,EANY,2BAMHM,EANG,KAMGD,EANH,KAO1B,OAAOF,EAAMD,GAAQC,EAAMG,GAAQL,EAAMD,GAASC,EAAMI,MYEtD3B,EAEJ,OAAOoH,EACL,8BACE,4BAAI/N,EAAE,eAGR,sBAAKF,UAAU,OAAf,UACE,sBAAKA,UAAU,mCAAf,UACE,qBAAIA,UAAU,MAAd,UACE,uBAAMA,UAAU,uBAAhB,UACG+O,EAAqBrS,OAAQ,OAEhC,sBAAMsD,UAAU,4BAAhB,SACGE,EAAE,8BAA+B,CAChCyD,MAAOoL,EAAqBrS,cAIlC,wBACEsG,KAAK,SACLK,QAAS,kBAAM2K,GAAe,IAC9BhO,UAAU,MAHZ,SAKE,cAAC,GAAD,CAAsBA,UAAU,iCAGpC,sBAAKA,UAAU,YAAf,UACE,oBACEA,UAAU,YACVgP,SAAS,eACT1O,KAAI,sCAAiC2O,mBACnClD,GAAUgD,EAAqBjO,KAAI,SAAC2C,GAAD,OAAOA,EAAEoB,WAJhD,UAOE,cAAC,IAAD,CAAiBvB,KAAM4L,IAAYlP,UAAU,sBAC5CE,EAAE,6BAEL,yBAAQF,UAAU,OAAOgD,KAAK,SAASK,QA9DzB,WAClB,IAAM8L,EAAYxP,SAASyP,cAAc,YACzCD,EAAUE,UAAYC,OAAOC,SAASjP,KACtCX,SAASC,KAAK4P,YAAYL,GACQ,WAA9BG,OAAOG,UAAUC,SACnBP,EAAUQ,kBAAkB,EAAG,OAE/BR,EAAUS,SAEZjQ,SAASkQ,YAAY,QACrBV,EAAUW,SACVxB,GAAU,GACVvF,YAAW,kBAAMuF,GAAU,KAAQ,MAkD/B,UACE,cAAC,IAAD,CAAiBhL,KAAMyM,IAAQ/P,UAAU,sBACxCE,EAAEmO,EAAS,uBAAyB,4BAGzC,6BACGU,EAAqBlJ,MAAM,EAAGsI,GAAOrN,KAAI,SAAC4D,GAAD,OACxC,6BACE,cAAC,GAAD,CACEA,IAAKA,EACLgJ,WAAc,OAAHhJ,QAAG,IAAHA,OAAA,EAAAA,EAAKjG,OAAL,OAAYiI,QAAZ,IAAYA,OAAZ,EAAYA,EAAqBjI,IAC5C+N,SAAUA,KAJL9H,EAAIjG,SAShB0P,EAAQY,EAAqBrS,OAC5B,qBAAKsD,UAAU,cAAf,SACE,wBACEA,UAAU,0DACVgD,KAAK,SACLK,QAAS,kBAAM+K,EAASD,EAlHlB,KA+GR,SAKGjO,EAAE,+BAGL,S,SC1IK,OAA0B,kCCA1B,OAA0B,iCCoBnC8P,GAAkB,SAACC,EAAclR,GACrC,GAAIkR,EAAM,CAGR,IAAMC,EAAYC,UAAOC,MAAMH,EAAM,CAAEI,YAAY,EAAMC,QAAQ,IACjE,MAAO,CAAEC,OAAO,QAAD,OAAUL,EAAV,WAKjB,MAAO,CAAEK,OADM,OAAbxR,EAAoB,6BAA4B,qBAiHrCyR,GA3GV,SAAC,GAAkB,IAAhBhE,EAAe,EAAfA,SACArM,EAAUC,cADK,EAKjBtB,cAFMC,EAHW,EAGnBpD,KAAQoD,SACRmB,EAJmB,EAInBA,EAEMqF,EAASkL,cAATlL,KANa,EASjB1D,qBAAWlD,GADb6C,OAAUkP,EARS,EAQTA,oBAAqBrL,EARZ,EAQYA,uBARZ,EAU6BxD,qBAChDwC,GADMwC,EAVa,EAUbA,cAAe8J,EAVF,EAUEA,uBAIjBzL,EAAe2B,EAAc5E,MAAK,SAACwB,GAAD,OAAOA,EAAE8B,OAASA,KAQ1D,GANAjG,qBAAU,WACJ4F,GACFyL,EAAuBzL,KAExB,CAACA,EAAcyL,KAEbzL,EACH,OAAO,KAvBY,IA0BbL,EAASK,EAATL,KAEF+L,ExBpC2B,SAAC/L,GAAD,OACjCA,EAAK,6BwBmCSgM,CAAoBhM,GAC5BiM,ExBlCyB,SAC/BjM,GAEA,IAAMkM,EACJlM,EAAK,oDAEP,GAAsB,KAAlBkM,EAAsB,CACxB,IAAMC,EAAeC,MAAMC,KAAKC,IAAQJ,IASxC,OARmCC,EAAalO,QAAO,SAACsO,GACtD,OACkC,IAAhCA,EAAQvO,SAAS,aACgB,IAAjCuO,EAAQvO,SAAS,cACe,IAAhCuO,EAAQvO,SAAS,cAIa,GAAKmO,EAAa,GAAK,KAG3D,OAAO,KwBeYK,CAAkBxM,GAErC,OACE,cAAC,EAAD,CAAO3F,eAAgB,kBAAMiB,EAAQE,KAAK,MAA1C,SACE,gCACE,oBAAIL,UAAU,sCAAd,SACG6E,EAAKQ,EAAuBc,QAE/B,sBAAKnG,UAAU,4BAAf,UACG4Q,GACC,oBACE5Q,UAAU,8CACVM,KAAI,iBAAYsQ,GAFlB,UAIE,qBACElQ,IAAI,GACJV,UAAU,cACVQ,IAAK8Q,GACLpO,MAAO,CAAE/E,MAAO,MAEjB+B,EAAE,+BAGN4Q,GACC,oBACE9Q,UAAU,yCACVM,KAAMwQ,EACNvU,OAAO,SACPgE,IAAI,aAJN,UAME,qBACEG,IAAI,GACJV,UAAU,cACVQ,IAAK+Q,GACLrO,MAAO,CAAE/E,MAAO,MAEjB+B,EAAE,qCAIRwQ,EAAoB5P,KAAI,SAACoB,EAAM1F,GAAP,OACvB,sBAEEwD,UAAS,eACPxD,IAAMkU,EAAoBhU,OAAS,EAAI,GAAK,mBAHhD,UAME,oBAAIsD,UAAU,2BAAd,SACGoB,EAAec,EAAKsP,QAASzS,KAE/BmD,EAAKtC,MACJ,qBACEI,UAAU,OACVyR,wBACEzB,GACEnL,EAAK3C,EAAKtC,MACVb,KAIPmD,EAAKgK,MACJ,qBAAKlM,UAAU,mBAAf,SACGkC,EAAKgK,KAAKpL,KAAI,SAACsL,GAAD,OACbA,EAAItL,KAAI,SAAC4Q,EAAKC,GAAN,OACN,qBAAK3R,UAAU,OAAf,SACGsM,GAAqBzH,EAAM6M,EAAK3S,EAAUyN,IADlBmF,aAtB9BnV,YCyHFoV,GA3MO,WACpB,IAAM7S,EAAWuD,IADS,EAEMb,mBAAS,OAFf,mBAEnB+K,EAFmB,KAETqF,EAFS,OAGN/S,cAAZoB,EAHkB,EAGlBA,EAAGvE,EAHe,EAGfA,KACHmW,EAAUjQ,qBAAWlD,GAArBmT,MAJkB,EAKIrQ,mBAAS6N,OAAOyC,WnCvBf,KmCkBL,mBAKnBC,EALmB,KAKTC,EALS,OAMgBxQ,mBAASuQ,GANzB,mBAMnB1G,EANmB,KAMJ4G,EANI,OAOQzQ,mBAASuQ,GAPjB,mBAOnBzG,EAPmB,KAOR4G,EAPQ,KAQlBC,EAAoBvQ,qBAAWhD,GAA/BuT,gBAER9S,qBAAU,WACR,IAAM+S,EAAiB,WACrB,IAAMC,EAAchD,OAAOyC,WnC9BA,ImC+B3BE,EAAUK,GACVJ,EAAiBI,GACjBH,EAAaG,IAGf,OADAhD,OAAOzP,iBAAiB,SAAUwS,GAC3B,kBAAM/C,OAAOvP,oBAAoB,SAAUsS,MACjD,IAnBuB,MAqBY5Q,oBAAS,GArBrB,mBAqBnB+E,EArBmB,KAqBNmF,EArBM,OAsBYlK,oBAAS,GAtBrB,mBAsBnBgF,EAtBmB,KAsBNuH,EAtBM,OAuBMvM,mBAAS,UAvBf,mBAuBnBmF,EAvBmB,KAuBT2L,EAvBS,OA4BtB9Q,qBA5BsB,mBA0BxBiF,EA1BwB,KA2BxBC,GA3BwB,KAkCpB6L,GACJ,qBAAKxS,UAAU,8DAAf,SACE,wBACEgD,KAAK,SACLK,QAAS,WACPsI,GAAe,IAHnB,SAME,cAAC,EAAD,CAAuB3L,UAAU,gCAKjCyS,GACJ,sBAAKzS,UAAU,oHAAf,UACE,gCACE,cAAC,GAAD,CAAQ2L,eAAgBA,IACxB,cAAC,GAAD,IACA,cAAC,GAAD,CACEL,cAAeA,EACfC,UAAWA,EACXH,gBAAiB,kBAAM8G,GAAkB5G,IACzCD,YAAa,kBAAM8G,GAAc5G,MAElCD,EAAgB,KAAO,cAAC,EAAD,IACxB,qBAAKtL,UAAU,MAAf,SACE,wBACEA,UAAU,kCACVgD,KAAK,SACLK,QAAS,WAhCjB+O,KA6BM,SAKGlS,EAAE,yBAIP8R,GAAY,cAAC,EAAD,OAIZU,GAAuB7E,IAC3B,mGACAtC,EAAY,QAAU,UAGlBoH,GACJ,sBAAK3S,UAAW0S,GAAhB,UACE,cAAC,GAAD,CACEhM,oBAAqBA,EACrBsH,eAAgBA,EAChBxB,SAAUA,IAEXwF,GAAY,cAAC,EAAD,OAIXY,GACJ,qBAAK5S,UAAU,6DAAf,SACE,wBACEgD,KAAK,SACLK,QAAS,WACP2K,GAAe,IAEjBhO,UAAU,UALZ,SAOE,cAAC,EAAD,CAAuBA,UAAU,gCAKjC6S,GAAwBhF,IAC5B,kDACc,uBAGViF,GAAmBjF,IACvB,qDACAtC,EAAY,YAAc,UAC1B/E,EAAc,YAAc,UAGxBuM,GAAqBlF,IACzB,oDACa,WAAbjH,EACI,0BACA,4BAGAoM,GAAuBnF,IAC3B,+DACa,YAAbjH,EACI,0BACA,4BAGN,OACE,qCACE,cAAC,IAAD,UACE,gCAAQ1G,EAAE,aAEX4R,EACC,eAAC,IAAD,WACE,sBAAK9R,UAAW6S,GAAhB,UACGrM,EAAciM,GAAgBD,GAC/B,sBAAKxS,UAAU,yCAAf,UACE,yBACEA,UAAU,YACV2C,MAAO6J,EACPpJ,SAAU,SAAC5D,GAAD,OAAOqS,EAAYrS,EAAEjD,OAAOoG,QAHxC,UAKE,wBAAQA,MAAM,MAAd,iBACA,wBAAQA,MAAM,OAAd,qBAEF,yBACE3C,UAAU,OACV2C,MAAO5D,EACPqE,SAAU,SAAC5D,GAAD,OAAO7D,EAAKsX,eAAezT,EAAEjD,OAAOoG,QAHhD,UAKE,wBAAQA,MAAM,KAAd,yBACA,wBAAQA,MAAM,KAAd,2BAGH8D,EAAckM,GAAcC,GAC7B,sBAAK5S,UAAW8S,GAAhB,UACE,sBAAK9S,UAAU,oBAAf,UACE,wBACEqD,QAAS,kBAAMkP,EAAY,WAC3BvP,KAAK,SACLhD,UAAW+S,GAHb,SAKG7S,EAAE,gBAEL,wBACEmD,QAAS,kBAAMkP,EAAY,YAC3BvP,KAAK,SACLhD,UAAWgT,GAHb,SAKG9S,EAAE,oBAGP,cAAC,GAAD,CACEqG,WAAYyL,EACZxL,YAAaA,EACbC,YAAaA,EACbC,oBAAqBA,EACrBC,uBAAwBA,GACxBC,SAAUA,UAIhB,eAAC,IAAD,WACE,cAAC,IAAD,CAAOsM,KAAK,SAAZ,SACE,cAAC,EAAD,MAEF,cAAC,IAAD,CAAOA,KAAK,WAAZ,SACE,cAAC,EAAD,MAEF,cAAC,IAAD,CAAOA,KAAK,SAAZ,SACE,cAAC,GAAD,CAAS1G,SAAUA,MAErB,cAAC,IAAD,CAAO0G,KAAK,YAIhB,cAAC,EAAD,Q,yECxMFC,G,QAASC,EAAMC,SAoCAC,G,yPAIMC,E,gCAClBD,EAAIE,UAAWD,E,0CAEOJ,GAAOM,IAAIrY,EAAoC,CACpEsY,mBAAoB,SAACC,GACnB,IAAMC,EAAiBjU,SAASkU,cAAc,cAAgBxX,SAC1DuX,IAAmBvX,WAErBuX,EAAeE,YAAf,kBAAwCC,KAAKC,MAAQL,EAAcM,OAAU,KAAW,KAAxF,S,OALAC,E,OASAV,EAA2BU,EAASrP,KAEpCrD,EAAoB,CACxBqC,QAAS,GACTiK,oBAAqB0F,EAAQW,eAAeC,QAC5C1D,oBAAqB8C,EAAQW,eAAeE,QAC5ChP,uBAAwB,CACtBc,KAAMqN,EAAQW,eAAeG,eAC7BC,QAASf,EAAQW,eAAeK,kBAChClP,YAAakO,EAAQW,eAAeM,iBACpCC,OAAQlB,EAAQW,eAAeQ,iBAC/BC,OAAQpB,EAAQW,eAAeU,iBAC/BC,WAAYtB,EAAQW,eAAeY,sBACnCC,WAAYxB,EAAQW,eAAec,qBACnCxN,KAAM+L,EAAQW,eAAee,eAC7BC,OAAQ3B,EAAQW,eAAeiB,mBAI7BvO,EAAgB2M,EAAQ3O,KAAK/D,KAAI,SAACoB,GAAD,OACrCoR,EAAI+B,sBAAsBnT,EAAMV,MAG5BqC,EAAUyP,EAAIgC,qBAClB9B,EAAQW,eAAetQ,QACvBgD,GAGFyM,EAAIE,QAAU,CACZhS,OAAO,6BACFA,GADC,IAEJqC,YAEFgD,iB,kDAKF4F,QAAQ8I,MAAM,KAAEC,S,iCAGblC,EAAIE,S,2RAGWD,E,yCACAD,EAAImC,YAAYlC,G,cAAhCC,E,yBACCA,EAAQhS,Q,oLAIfqC,G,iGACA0P,E,yCAMUD,EAAImC,YAAYlC,G,uBAFxB1M,E,EAAAA,cACmB6O,E,EAAnBlU,OAAUqC,Q,kBAKLgD,EAAc/D,QAAO,SAAC4B,GAE3B,QAAKA,EAAIG,MAKFhB,EAAQ2B,QAAgB,SAACmQ,EAAQ7S,GAEtC,IAAK6S,EACH,OAAO,EAIT,IAAK7S,EAAOxB,OAAO5E,OACjB,OAAO,EAKT,GAA0C,qBAA/BgI,EAAIG,KAAK/B,EAAOlB,WACzB,OAAO,EAGT,IAAMgU,EAAeF,EAAczT,MACjC,SAAC6B,GAAD,OAAOA,EAAElC,YAAckB,EAAOlB,aAGhC,GAA2B,cAAX,OAAZgU,QAAY,IAAZA,OAAA,EAAAA,EAAc5S,MAAqB,CACrC,IAAM6S,EAAW9Q,OAAOL,EAAIG,KAAK/B,EAAOlB,YAIlCkU,EAHcF,EAAZnT,QAGuBR,MAC7B,SAACwB,GAAD,OAAOsB,OAAOtB,EAAEd,OAASkT,KAI3B,OADEC,GAAkBhT,EAAOxB,OAAOuB,SAASiT,EAAenT,SAC1C,EASlB,OALkB+B,EAAIG,KAAK/B,EAAOlB,WAC/B5C,MAAM,KACN8B,KAAI,SAACC,GAAD,OAAOA,EAAE+D,UACbhC,OAAOiT,SACkBjT,QAAO,SAACC,GAAD,OAAOD,EAAOxB,OAAOuB,SAASE,MAChDrG,OAAS,KACzB,O,8IAaLmI,EAIArD,GAEA,I1BtMoBX,E0BsMd9B,EAA6B,UAAlBpD,EAAKoD,SAAuB,KAAOpD,EAAKoD,SAEnDiX,EAAiBnR,EAAKoR,SAAShU,MAAK,SAACiU,GAEzC,OAAOA,EAAQnX,WAAaA,KAGxBoX,GAA2B,OAAdH,QAAc,IAAdA,OAAA,EAAAA,EAAgBnR,OAAQ,GACrCsB,EAAOgQ,EAAW3U,EAAO6D,uBAAuBc,MAEhDiQ,EAAY/Z,OAAOgB,KAAK8Y,GAAY3Q,QACxC,SAAC6Q,EAAOzU,GACN,OAAO,6BACFyU,GADL,mBAEGzU,EAAY0R,EAAI8C,UAAUxU,EAAWuU,EAAWvU,GAAYJ,OAGjE,IAQF,OALA4U,EpCrNuC,uBoCqNE9C,EAAIgD,wBAC3CF,EACA5U,GAGK,CACL/C,GAAIoG,EAAK0R,QACTpQ,OACAZ,M1BlOkB1E,E0BkOJsF,E1BjOlBtF,EAAIiL,QAAQ,MAAO,KAAKA,QAAQ,MAAO,M0BkOnCjH,KAAMuR,K,8CAIqBvR,EAAYrD,GACzC,IAAM+C,EAAU,GACVxF,EAA6B,UAAlBpD,EAAKoD,SAAuB,KAAOpD,EAAKoD,SACzD,IACG8F,EAAKrD,EAAO6D,uBAAuBuP,SAAW,IAC5C4B,cACA1R,OACAjC,SAAS,SACXgC,EAAKrD,EAAO6D,uBAAuBuP,SAAW,IAC5C4B,cACA1R,OACAjC,SAAS,OACZ,CACA,IAAMN,EAAqB,OAAbxD,EAAoB,SAAW,QAC7CwF,EAAQlE,KAAKkC,GAEf,IACGsC,EAAKrD,EAAO6D,uBAAuBqP,SAAW,IAC5C8B,cACA1R,OACAjC,SAAS,SACXgC,EAAKrD,EAAO6D,uBAAuBqP,SAAW,IAC5C8B,cACA1R,OACAjC,SAAS,OACZ,CACA,IAAMN,EAAqB,OAAbxD,EAAoB,SAAW,QAC7CwF,EAAQlE,KAAKkC,GAEf,IAAKsC,EAAKrD,EAAO6D,uBAAuByP,aAAe,IAAIhQ,OAAQ,CACjE,IAAMvC,EACS,OAAbxD,EAAoB,2BAA0B,eAChDwF,EAAQlE,KAAKkC,GAEf,OAAOgC,EAAQpD,KAAK,O,gCAGLS,EAAmBf,EAAaW,GAM/C,OAJeX,EAAI7B,MAAM,KAEtB8B,KAAI,SAAC6B,GAAD,OAAW2Q,EAAImD,WAAW7U,EAAWe,EAAOnB,MAChDsB,OAAOiT,SACS5U,KAAK,O,iCAIxBS,EACAe,EACAnB,GAEA,IAAI6U,EAAQ1T,EAAMmC,OAAOgH,QAAQ,KAAM,IAOvC,GANIlK,IAAcJ,EAAO6D,uBAAuBkP,UAC9C8B,EAAQzV,EAAUyV,EAAMvK,QAAQ,SAAU,MACtC,CAAC,gBAAiB,UAAW,eAAejJ,SAASwT,KACvDA,EAAQ,iBAGRzU,IAAcJ,EAAO6D,uBAAuB8P,OAAQ,CACtD,IAAMuB,EAAQL,EAAMxT,SAAS,OACvB8T,EAAQN,EAAMxT,SAAS,OAEvB+T,EAAcvb,2aAAYwb,iBAC5BhP,SAASxM,2aAAYwb,iBAAkB,IACvC,OAEEC,EAAczb,2aAAY0b,iBAC5BlP,SAASxM,2aAAY0b,iBAAkB,IACvC,OAGEC,EAASN,EAAQI,EAAcH,EAAQC,EAAc,EACrDK,EAASpP,SAASwO,EAAMvK,QAAQ,UAAW,IAAK,IACtD,OAAO/G,QAAQkS,EAASD,GAAQE,YAAY,IAE9C,OAAItV,IAAcJ,EAAO6D,uBAAuB2P,WACvC,CAAC,MAAO,OAAOnS,SAASwT,EAAMG,eAAiBlb,EpC1S9B,MoC4SnB+a,I,2CAKPX,EACA7O,GAEA,IADgB,EACVhD,EAAU6R,EAAc5U,KAAI,SAACgD,GACjC,OAAO,6BACFA,GADL,IAEErB,QAAS6Q,EAAI6D,eAAerT,QAJhB,cASE+C,GATF,IAShB,2BAEE,IAFgC,IAAvBnC,EAAsB,qBAE1B,IAAM9C,EAAS,KACZwV,EAAW1S,EAAIG,KAAKjD,GAAWkD,OAG/BhC,EAASe,EAAQ5B,MAAK,SAAC6B,GAAD,OAAOA,EAAElC,YAAcA,KAEnD,GAAIwV,GAAYtU,EACd,GAAoB,SAAhBA,EAAOE,KAWT,IAX2B,IACnBP,EAAYK,EAAZL,QAGF4U,EAAYD,EAASpY,MAAM,KAE3BsY,EAAejb,OAAOgB,KAC1Bga,EAAU7R,QAAO,SAAC+R,EAAKxU,GAAN,oBAAC,gBAAiBwU,GAAlB,mBAAwBxU,GAAI,MAAS,KAP9B,aAWrB,IAAMJ,EAAK,KACV6U,EAAS/U,EAAQR,MAAK,SAACwB,GAAD,OAAOA,EAAEd,QAAUA,KAExC6U,IACHA,EAAS,CAAEjV,MAAOI,EAAOA,QAAOgB,MAAO,GACvClB,EAAQpC,KAAKmX,IAGfA,EAAO7T,OAAS,GARlB,MAAoB2T,EAApB,eAAmC,SAU9B,GAAoB,aAAhBxU,EAAOE,KAAqB,CAAC,IAC9BP,EAAYK,EAAZL,QAEFwU,EAASpP,SAASuP,EAAU,IAElC,GAAIH,EAAQ,CACV,IAAMnB,EAAiBrT,EAAQR,MAC7B,SAACwB,GAAD,OAAOsB,OAAOtB,EAAEd,OAASsU,KAEvBnB,IACFA,EAAenS,OAAS,MAtClC,MAAwBtH,OAAOgB,KAAKqH,EAAIG,MAAxC,eAAgD,IAXlC,8BAyDhB,OAAOhB,I,qCAMaf,GACpB,GAAoB,aAAhBA,EAAOE,KAAqB,CAC9B,IAAMP,EAAU,GACZgV,EAAO,KAEX3U,EAAOL,QAAQ8L,MAAK,SAACmJ,EAAGC,GACtB,OAAO5S,OAAO4S,GAAK5S,OAAO2S,MALE,oBAQT5U,EAAOL,SARE,IAQ9B,2BAAqC,CAAC,IAA3B+U,EAA0B,QAC7BjV,EACK,OAATkV,EAAA,YACSD,EAAOnK,kBADhB,UAEOmK,EAAOnK,iBAFd,cAEoCoK,EAAKpK,kBAE3C5K,EAAQpC,KAAK,CAAEkC,QAAOI,MAAOiV,OAAOJ,GAAS7T,MAAO,IACpD8T,EAAOD,GAfqB,8BAiB9B,OAAO/U,EAGT,OAAQK,EAAOL,SAAW,IAAI3B,KAAI,SAAC2C,GAAD,MAAyB,CACzDlB,MAAOqV,OAAOnU,GACdd,MAAOiV,OAAOnU,GACdE,MAAO,U,KA7VQ2P,GAEZE,a,ECrDT,IA2CeqE,GA3CqB,SAAC,GAAkB,IAAhB1Y,EAAe,EAAfA,SAAe,EAC1BsC,oBAAS,GADiB,mBAC7CqQ,EAD6C,KACtCgG,EADsC,OAExBrW,mBAAoB,CAC9CoC,QAAS,GACTiK,oBAAqB,GACrB4C,oBAAqB,GACrBrL,uBAAwB,CACtBc,KAAM,GACNoO,QAAS,GACTjP,YAAa,GACb0P,WAAY,GACZN,OAAQ,GACRE,OAAQ,GACRE,WAAY,GACZrN,KAAM,GACN0N,OAAQ,MAfwC,mBAE7C3T,EAF6C,KAErCuW,EAFqC,KAoCpD,OAhBAzY,qBAAU,YACE,yCAAG,6BAAAoY,EAAA,sEACgBpE,GAAI0E,aADpB,OACLC,EADK,OAEXF,EAAUE,GACVH,GAAS,GAHE,2CAAH,qDAMVI,KACC,IAEH5Y,qBAAU,WACR3D,EAAKsH,GAAG,kBAAR,wBAA2B,uBAAAyU,EAAA,sDACzBpI,OAAOC,SAAS4I,SADS,+CAM3B,cAAC,EAAiBC,SAAlB,CAA2BzV,MAAO,CAAEmP,QAAOtQ,SAAQsW,WAAUC,aAA7D,SACG5Y,KC2CQkZ,GA3CwB,SAAC,GAAkB,IAAhBlZ,EAAe,EAAfA,SAAe,EACzBsC,mBA7BZ,WAAO,IACnB6W,EAAWhJ,OAAOC,SAAlB+I,OACAzU,EAAwB,GAC9B,IAAKyU,EACH,OAAOzU,EAGT,IAPwB,EAOlB0U,GADND,EAASA,EAAOtX,UAAU,IACJhC,MAAM,KAPJ,cAQJuZ,GARI,mCAUSvZ,MAAM,KAVf,mBAUjB4C,EAViB,KAUNe,EAVM,KAWlBf,EAAU4W,SAAS,QACrB5W,EAAYA,EAAUZ,UAAU,EAAGY,EAAUlF,OAAS,IAExDkF,EAAY6W,mBAAmB7W,GAC/B,IAAIkB,EAASe,EAAQ5B,MAAK,SAAC6B,GAAD,OAAOA,EAAElC,YAAcA,KAC5CkB,IACHA,EAAS,CACPlB,YACAN,OAAQ,IAEVuC,EAAQxD,KAAKyC,IAEfA,EAAOxB,OAAOjB,KAAKoY,mBAAmB9V,KAfxC,2BAA6B,IARL,8BAyBxB,OAAOkB,EAI8C6U,IADE,mBAChD7U,EADgD,KACvC8U,EADuC,OAEXlX,mBAAwB,MAFb,mBAEhDyM,EAFgD,KAEhCjH,EAFgC,KA4BvD,OACE,cAAC,EAAoBmR,SAArB,CACEzV,MAAO,CACLb,aAAc+B,EACd9B,eA1BiB,SAACH,EAAmBN,GACzC,IAAMsX,EAAW,YAAO/U,GACpBf,EAASe,EAAQ5B,MAAK,SAAC6B,GAAD,OAAOA,EAAElC,YAAcA,KAE5CkB,IACHA,EAAS,CAAElB,YAAWN,OAAQ,IAC9BsX,EAAYvY,KAAKyC,IAGnBA,EAAOxB,OAASA,EAvDA,SAACuC,GACnB,IAD6C,EACvCgV,EAAQ,GAD+B,cAExBhV,GAFwB,IAE7C,2BAA8B,CAAC,IAAD,EAAnBf,EAAmB,QACtBlB,EAAYqN,mBAAmBnM,EAAOlB,WADhB,cAERkB,EAAOxB,QAFC,IAE5B,2BAAmC,CAAC,IAAzBqB,EAAwB,QACjCkW,EAAMxY,KAAN,UAAcuB,EAAd,cAA6BqN,mBAAmBtM,MAHtB,gCAFe,8BAQ7C,IAAMmW,EAAG,UAAMxJ,OAAOC,SAASwJ,SAAtB,YAAkCF,EAAM1X,KAAK,MACtDmO,OAAOnP,QAAQ6Y,UAAU,KAAM,GAAIF,GAgDjCG,CAAYL,GACZD,EAAWC,GAGX3R,EAAkB,OAYdmL,gBATkB,WACtBuG,EAAW,KASPzK,iBACAjH,qBANJ,SASG9H,KCzBQ+Z,GAlDyB,SAAC,GAAkB,IAAhB/Z,EAAe,EAAfA,SACjC2S,EAAUjQ,qBAAWlD,GAArBmT,MACAhQ,EAAiBD,qBAAWhD,GAA5BiD,aAFgD,EAI1BL,oBAAS,GAJiB,mBAIjDwM,EAJiD,KAIxCkL,EAJwC,OAKlC1X,mBAAS,MALyB,mBAKjDX,EALiD,KAK5CiG,EAL4C,OAapDtF,mBAA8B,MAbsB,mBAWtDqF,EAXsD,KAYtD6J,EAZsD,OAcdlP,mBAAyB,IAdX,mBAcjDoF,EAdiD,KAclCuS,EAdkC,KAiBxD9Z,qBAAU,WASJwS,GARM,yCAAG,6BAAA4F,EAAA,6DACXyB,GAAW,GAEXxI,EAAuB,MAHZ,SAIQ2C,GAAI+F,kBAAkBvX,GAJ9B,OAILwF,EAJK,OAKX8R,EAAiB9R,GACjB6R,GAAW,GANA,2CAAH,oDASRjB,KAED,CAACpG,EAAOhQ,IAEX,IAAMkF,EAAS3H,mBAEf,OACE,cAAC,EAAqB+Y,SAAtB,CACEzV,MAAO,CACLkE,gBACAoH,UACAnH,sBACA6J,yBACA5J,SACAjG,MACAkG,UARJ,SAWG7H,KC/BPma,IAASC,OACP,cAAC,IAAMC,WAAP,UACE,cAAC,IAAD,UACE,cAAC,GAAD,UACE,cAAC,GAAD,UACE,cAAC,GAAD,UACE,cAAC,GAAD,cAMV7Z,SAAS8Z,eAAe,U","file":"static/js/main.087c675e.chunk.js","sourcesContent":["export const API_URL = process.env.REACT_APP_API_URL;\nexport const MAPBOX_ACCESS_TOKEN = process.env.REACT_APP_MAPBOX_ACCESS_TOKEN;\nexport const MAPBOX_STYLE = process.env.REACT_APP_MAPBOX_STYLE;\n\nexport const DEFAULT_LANGUAGE = \"fr\";\n\nexport const MOBILE_BREAKPOINT = 768;\n\nexport const ORGANISATION_FOCUS_PROPERTY = \"Focus Spécifique\"; // Derived property\n\n// Convert boolean true back to 'Oui' for CSV export\nexport const TRUE_CONSTANT = \"Oui\";\nexport const FALSE_CONSTANT = \"Non\";","import i18n from \"i18next\";\nimport LanguageDetector from \"i18next-browser-languagedetector\";\nimport { initReactI18next } from \"react-i18next\";\n\nimport { DEFAULT_LANGUAGE } from \"./constants\";\nimport enTranslation from \"./lang/en.json\";\nimport frTranslation from \"./lang/fr.json\";\n\n// the translations\nconst resources = {\n en: {\n translation: enTranslation,\n },\n fr: {\n translation: frTranslation,\n },\n};\n\ni18n\n .use(LanguageDetector)\n .use(initReactI18next) // passes i18n down to react-i18next\n .init({\n resources,\n fallbackLng: DEFAULT_LANGUAGE, // Default lang\n interpolation: {\n escapeValue: false, // react already handles xss\n },\n supportedLngs: ['fr', 'en'],\n });\n\nexport default i18n;\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M0.4751 2.2625L6.2001 8L0.475098 13.7375L2.2376 15.5L9.7376 8L2.2376 0.5L0.4751 2.2625Z\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M9.7378 2.2625L15.4628 8L9.73779 13.7375L11.5003 15.5L19.0003 8L11.5003 0.5L9.7378 2.2625Z\"\n});\n\nfunction SvgRightPointingChevrons(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 19,\n height: 16,\n viewBox: \"0 0 19 16\",\n fill: \"#B1D7FF\",\n xmlns: \"http://www.w3.org/2000/svg\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgRightPointingChevrons);\nexport default __webpack_public_path__ + \"static/media/right-pointing-chevrons.09fd5974.svg\";\nexport { ForwardRef as ReactComponent };","import { createContext, Dispatch, SetStateAction } from \"react\";\nimport { AppConfig } from \"../react-app-env\";\n\ninterface AppConfigContextType {\n ready: boolean;\n config: AppConfig;\n setReady: Dispatch>;\n setConfig: Dispatch>;\n}\n\nconst AppConfigContext = createContext(\n {} as AppConfigContextType\n);\n\nexport default AppConfigContext;\n","import { createContext } from \"react\";\nimport { Bounds, FilterStates } from \"../react-app-env\";\n\ninterface FilterStatesContextType {\n filterStates: FilterStates;\n setFilterState: (id: string, values: string[]) => void;\n clearAllFilters: () => void;\n locationFilter: Bounds | null;\n setLocationFilter: (bounds: Bounds | null) => void;\n}\n\n/**\n * Context value can be found in FilterProvider\n */\nconst FilterStatesContext = createContext(\n {} as FilterStatesContextType\n);\n\nexport default FilterStatesContext;\n","import { useTranslation } from \"react-i18next\";\n\nexport default (): string => {\n const { i18n } = useTranslation();\n return i18n.language.split(\"-\")[0];\n};\n","export default __webpack_public_path__ + \"static/media/logo-text.225745ba.svg\";","import React, { useEffect, useRef } from \"react\";\nimport \"./Modal.css\";\n\nconst Modal: React.FC<{ onClickOutside: () => void }> = ({\n onClickOutside,\n children,\n}) => {\n const overlayRef = useRef(null);\n\n useEffect(() => {\n const clickListener = (e: MouseEvent) => {\n if (overlayRef?.current?.contains(e.target as Node)) {\n onClickOutside();\n }\n };\n document.body.addEventListener(\"click\", clickListener);\n\n const keyboardListener = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onClickOutside();\n }\n };\n document.addEventListener(\"keydown\", keyboardListener);\n\n return () => {\n document.body.removeEventListener(\"click\", clickListener);\n document.removeEventListener(\"keydown\", keyboardListener);\n };\n }, [onClickOutside]);\n\n return (\n
\n \n
\n
{children}
\n
\n
\n );\n};\n\nexport default Modal;\n","import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useHistory } from \"react-router-dom\";\n\nimport LogoWithText from \"../../assets/logo-text.svg\";\nimport Modal from \"../modal/Modal\";\n\nconst About: React.FC = () => {\n const { t } = useTranslation();\n const history = useHistory();\n\n return (\n history.push(\"/\")}>\n
\n

{t(\"about\")}

\n
\n

{t(\"about_part_one\")}

\n

{t(\"about_part_two\")}

\n

{t(\"about_part_three\")}

\n

{t(\"about_part_four\")}

\n \n {t(\"United\n \n
\n
\n );\n};\n\nexport default About;\n","import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { useHistory } from \"react-router-dom\";\n\nimport Modal from \"../modal/Modal\";\n\nconst Reports: React.FC = () => {\n const { t } = useTranslation();\n const history = useHistory();\n\n return (\n history.push(\"/\")}>\n
\n

{t(\"reports\")}

\n
\n

Burkina Faso

\n \n

Mali

\n \n

Niger

\n \n
\n
\n );\n};\n\nexport default Reports;\n","import getUrls from \"get-urls\";\nimport { LanguageMap, Organisation } from \"./react-app-env\";\n\nexport const slugify = (str: string): string =>\n str.replace(/\\s/g, \"_\").replace(/\\//g, \"|\");\n\nexport const titleCase = (str: string): string =>\n str\n .split(/\\s+/)\n .map(\n (s) =>\n `${s.substring(0, 1).toLocaleUpperCase()}${s\n .substring(1)\n .toLocaleLowerCase()}`\n )\n .join(\" \");\n\nexport const getTranslation = (\n content: string | LanguageMap,\n language: string\n): string => {\n if (typeof content === \"string\") {\n return content;\n }\n return content[language] || Object.values(content)[0];\n};\n\nexport const extractEmailAddress = (data: Organisation[\"data\"]): string =>\n data[\"Adresse électronique :\"];\n\nexport const extractWebAddress = (\n data: Organisation[\"data\"]\n): string | null => {\n const rawWebAddress =\n data[\"Site web de l'initiative, page facebook ou autre\"];\n\n if (rawWebAddress !== \"\") {\n const webAddresses = Array.from(getUrls(rawWebAddress));\n const webAddressWithoutPlatforms = webAddresses.filter((address) => {\n return (\n address.includes(\"youtube\") === false &&\n address.includes(\"facebook\") === false &&\n address.includes(\"twitter\") === false\n );\n });\n\n return webAddressWithoutPlatforms[0] ? webAddresses[0] : null;\n }\n\n return null;\n};\n\nexport const extractFocuses = (data: Organisation[\"data\"]): string[] => {\n const mainActivities = data[\"Domaine d'activité principal\"];\n\n return mainActivities\n .split(\";\")\n .map((e) => e.split(\",\"))\n .reduce((acc, cur) => cur.concat(acc), [])\n .filter((e) => !!e)\n .map((s) => titleCase(s));\n};\n","import { faChevronDown, faChevronUp } from \"@fortawesome/free-solid-svg-icons\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport React, { useState } from \"react\";\nimport { TRUE_CONSTANT } from \"../../constants\";\nimport useFilter from \"../../hooks/useFilter\";\nimport useLanguage from \"../../hooks/useLanguage\";\nimport { FilterConfig } from \"../../react-app-env\";\nimport { getTranslation } from \"../../util\";\n\nconst Filter: React.FC<{ config: FilterConfig }> = ({ config }) => {\n const [show, setShow] = useState(false);\n const [values, setValues] = useFilter(config.fieldName);\n\n const language = useLanguage();\n const label = getTranslation(config.labels, language);\n\n if (!config.options) {\n // TODO: implement other types of filter\n return null;\n }\n\n const onCheckOption = (value: string, checked: boolean): void => {\n if (checked && !values.includes(value)) {\n setValues([...values, value]);\n } else if (!checked && values.includes(value)) {\n setValues(values.filter((v) => v !== value));\n }\n };\n\n if (config.type === \"boolean\") {\n const on = values[0] === TRUE_CONSTANT;\n return (\n
\n

{label}

\n onCheckOption(TRUE_CONSTANT, !on)}\n />\n
\n );\n }\n\n return (\n
\n setShow(!show)}\n >\n \n

{label}

\n \n
\n \n
    \n {config.options.map((o) => (\n
  • \n onCheckOption(o.value, e.target.checked)}\n />\n \n {o.count}\n
  • \n ))}\n
\n
\n );\n};\n\nexport default Filter;\n","import { useContext } from \"react\";\nimport FilterStatesContext from \"../context/FilterStatesContext\";\n\nexport default (\n fieldName: string\n): [string[], (nextValues: string[]) => void] => {\n const { filterStates, setFilterState } = useContext(FilterStatesContext);\n\n const filterState = filterStates.find((item) => item.fieldName === fieldName);\n\n const values = filterState?.values || [];\n\n const setValues = (nextValues: string[]) => {\n setFilterState(fieldName, nextValues);\n };\n\n return [values, setValues];\n};\n","import React, { useContext } from \"react\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport Filter from \"../filter/Filter\";\n\nconst Filters: React.FC = () => {\n const {\n config: { filters },\n } = useContext(AppConfigContext);\n\n return (\n
    \n {filters.map((f) => (\n
  • \n \n
  • \n ))}\n
\n );\n};\n\nexport default Filters;\n","export default __webpack_public_path__ + \"static/media/logo.aed1712d.svg\";","import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Link } from \"react-router-dom\";\nimport Logo from \"../../assets/logo.svg\";\n\nconst Footer: React.FC = () => {\n const { t } = useTranslation();\n\n return (\n
\n \n \n \n
\n
\n {t(\"footer.initiated_by\")}\n
\n \n {t(\"footer.about\")}\n \n
\n
\n );\n};\n\nexport default Footer;\n","import React from \"react\";\n\nconst LoadingOverlay: React.FC = () => (\n
\n
\n
\n
\n);\n\nexport default LoadingOverlay;\n","import { createContext, MutableRefObject } from \"react\";\nimport { Organisation } from \"../react-app-env\";\n\ninterface OrganisationsContextType {\n loading: boolean;\n organisations: Organisation[]; // Display all organisations on the map for better UX (more coherent heatmap and points)\n focusedOrganisation: Organisation | null;\n setFocusedOrganisation: (org: Organisation | null) => void;\n map: null | boolean;\n setMap: any;\n mapRef: MutableRefObject;\n}\n\nconst OrganisationsContext = createContext(\n {} as OrganisationsContextType\n);\n\nexport default OrganisationsContext;\n","import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nconst Focuses: React.FC<{\n focuses: string[];\n}> = ({ focuses }) => {\n const { t } = useTranslation();\n\n return (\n
\n {focuses.map((focus) => (\n \n {t(focus)}\n
\n ))}\n
\n );\n};\n\nexport default Focuses;\n","import { Bounds, Organisation } from \"../../react-app-env\";\n\nexport interface GeoJSON {\n type: string;\n features: {\n geometry: {\n coordinates: [number, number];\n };\n }[];\n}\n\nexport const extractLatLng = (\n org: Organisation,\n coordinatesField: string\n): number[] | null => {\n const rawCoordinates = org.data[coordinatesField] || \"\";\n const cleanCoordinates = rawCoordinates\n .trim()\n .split(/[ ,]+/)\n .map(Number)\n .filter((n) => n && n < 90 && n > -90);\n return cleanCoordinates.length === 2 ? cleanCoordinates : null;\n};\n\nexport const calcBounds = (geoJSON: GeoJSON): Bounds | null => {\n let north = null;\n let west = null;\n let south = null;\n let east = null;\n // Create a bounding box of all the features\n for (const feature of geoJSON.features) {\n const { coordinates } = feature.geometry;\n\n if (!west || coordinates[0] < west) {\n [west] = coordinates;\n }\n\n if (!north || coordinates[1] > north) {\n [, north] = coordinates;\n }\n\n if (!east || coordinates[0] > east) {\n [east] = coordinates;\n }\n\n if (!south || coordinates[1] < south) {\n [, south] = coordinates;\n }\n }\n\n if (north && east && south && west) {\n return [\n [west, north],\n [east, south],\n ];\n }\n\n return null;\n};\n\nexport const filterOrganisationsByCoordinates = (\n orgs: Organisation[],\n bounds: Bounds,\n organisationCoordinatesField: string\n): Organisation[] => {\n return orgs.filter((org) => {\n const coordinates = extractLatLng(org, organisationCoordinatesField);\n if (!coordinates) {\n return false;\n }\n const [lat, lng] = coordinates;\n const [[west, north], [east, south]] = bounds;\n return lng > west && lng < east && lat < north && lat > south;\n });\n};\n\nexport const convertOrganisationsToGeoJSON = (\n orgs: Organisation[],\n organisationCoordinatesField: string,\n organisationSizeField: string\n): GeoJSON => {\n return {\n type: \"FeatureCollection\",\n features: orgs\n .map((org) => ({\n id: org.id,\n data: org.data,\n latLng: extractLatLng(org, organisationCoordinatesField),\n }))\n .filter((org) => org.latLng)\n .map((org) => ({\n type: \"Feature\",\n geometry: {\n type: \"Point\",\n coordinates: org.latLng ? [org.latLng[1], org.latLng[0]] : [0, 0],\n },\n properties: {\n id: org.id,\n size: parseInt(org.data[organisationSizeField], 10) || 1,\n },\n })),\n };\n};\n","import { Marker } from \"@urbica/react-map-gl\";\nimport React, { useContext } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport { Organisation } from \"../../react-app-env\";\nimport { extractFocuses } from \"../../util\";\nimport Focuses from \"../focuses/Focuses\";\nimport { extractLatLng } from \"./util\";\n\nconst OrganisationMarker: React.FC<{\n organisation: Organisation;\n onHide: () => void;\n}> = ({ organisation, onHide }) => {\n const { config } = useContext(AppConfigContext);\n const latLng = extractLatLng(\n organisation,\n config.organisationFieldNames.coordinates\n );\n\n if (!latLng) {\n return null;\n }\n\n const { data, slug } = organisation;\n\n const focuses = extractFocuses(data).slice(0, 3);\n\n return (\n \n \n
\n \n

\n {data[config.organisationFieldNames.name]}\n

\n {focuses.length > 0 && }\n \n
\n
\n \n );\n};\n\nexport default OrganisationMarker;\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport MapGL, {\n NavigationControl,\n Source,\n Layer,\n ScaleControl,\n} from \"@urbica/react-map-gl\";\nimport React, {\n Dispatch,\n SetStateAction,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\";\nimport \"mapbox-gl/dist/mapbox-gl.css\";\nimport { MAPBOX_ACCESS_TOKEN, MAPBOX_STYLE } from \"../../constants\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport FilterStatesContext from \"../../context/FilterStatesContext\";\nimport OrganisationsContext from \"../../context/OrganisationsContext\";\nimport { Organisation } from \"../../react-app-env\";\nimport OrganisationMarker from \"./OrganisationMarker\";\nimport {\n calcBounds,\n convertOrganisationsToGeoJSON,\n extractLatLng,\n GeoJSON,\n} from \"./util\";\n\nconst TRANSPARENT = \"rgba(0,0,0,0)\";\nconst TRANSLUCENT_BLUE = \"rgba(54,26,198,0.5)\";\nconst TRANSLUCENT_RED = \"rgba(255,13,86,0.5)\";\nconst OUTLINE_COLOR = \"#E4E5EC\";\n\nconst COLOR_SCALE = [TRANSPARENT, TRANSLUCENT_BLUE, TRANSLUCENT_RED];\n\nconst Map: React.FC<{\n autofocus: boolean;\n sidebarOpen: boolean;\n orgListOpen: boolean;\n setHoveredOrganisation: Dispatch<\n SetStateAction\n >;\n hoveredOrganisation: Organisation | null | undefined;\n viewMode: string;\n}> = ({\n autofocus = false,\n sidebarOpen,\n orgListOpen,\n hoveredOrganisation,\n setHoveredOrganisation,\n viewMode,\n}) => {\n const { config } = useContext(AppConfigContext);\n const {\n organisations,\n focusedOrganisation,\n setMap,\n map,\n mapRef,\n } = useContext(OrganisationsContext);\n const { setLocationFilter } = useContext(FilterStatesContext);\n const [viewport, setViewport] = useState({\n latitude: 14,\n longitude: 0,\n zoom: 3,\n });\n\n // Convert the organisations list into GeoJSON so it can be used as a heatmap source\n const orgGeoJSON = useMemo(() => {\n return convertOrganisationsToGeoJSON(\n organisations,\n config.organisationFieldNames.coordinates,\n config.organisationFieldNames.size\n );\n }, [\n config.organisationFieldNames.coordinates,\n config.organisationFieldNames.size,\n organisations,\n ]);\n\n // Call this function to update the global map bounds, used to filter the organisation list\n const updateLocationFilter = useCallback(() => {\n const bounds = (map as any).getBounds();\n const { lat: north, lng: west } = bounds.getNorthWest();\n const { lat: south, lng: east } = bounds.getSouthEast();\n setLocationFilter([\n [west, north],\n [east, south],\n ]);\n }, [map, setLocationFilter]);\n\n useEffect(() => {\n if (!mapRef) {\n return;\n }\n\n if (!mapRef.current) {\n return;\n }\n\n // @ts-expect-error Should error but will never happen.\n mapRef?.current?.getMap().resize();\n }, [sidebarOpen, orgListOpen, mapRef]);\n\n // Update the view when the list of organisations or focus changes\n useEffect(() => {\n if (!map) {\n return;\n }\n\n if (focusedOrganisation) {\n const latLng = focusedOrganisation\n ? extractLatLng(\n focusedOrganisation,\n config.organisationFieldNames.coordinates\n )\n : null;\n\n if (latLng && autofocus) {\n // Center map on focused organisation (desktop only)\n (map as any).easeTo({\n center: [latLng[1], latLng[0]],\n zoom: 10,\n maxDuration: 1000,\n });\n\n // Update the location filter when the ease is done as setViewport is not called automatically\n setTimeout(updateLocationFilter, 1000);\n }\n } else {\n // Zoom map to show all organisations\n const bounds = calcBounds(orgGeoJSON);\n if (bounds) {\n (map as any).fitBounds(bounds, { padding: 50 });\n }\n\n // clear location filter\n setLocationFilter(null);\n }\n }, [\n map,\n orgGeoJSON,\n focusedOrganisation,\n config.organisationFieldNames.coordinates,\n updateLocationFilter,\n setLocationFilter,\n autofocus,\n ]);\n\n const onViewportChange = (v: any) => {\n setViewport(v);\n updateLocationFilter();\n };\n\n const onClickCluster = (e: any) => {\n const m = map as any; // Assert not null\n const features = m.queryRenderedFeatures(e.point, {\n layers: [\"cluster\"],\n });\n const clusterId = features[0].properties.cluster_id;\n m.getSource(\"cluster\").getClusterExpansionZoom(\n clusterId,\n (err: Error, zoom: number) => {\n if (err) return;\n\n m.easeTo({\n center: features[0].geometry.coordinates,\n zoom,\n });\n }\n );\n };\n\n const onLoad = (e: any) => {\n if (!map && e?.target) {\n setMap(e.target);\n }\n };\n\n const onHoverPoint = (e: any) => {\n const { features } = e;\n\n if (!features?.length) {\n setHoveredOrganisation(null);\n return;\n }\n\n const feature = features[0];\n\n const organisation = organisations.find(\n (org) => org.id === feature.properties.id\n );\n\n setHoveredOrganisation(organisation);\n };\n\n const onClickPoint = (e: any) => {\n onHoverPoint(e);\n (map as any).easeTo({ center: e.lngLat });\n };\n\n return (\n <>\n \n \n \n \n {viewMode === \"heatmap\" ? (\n \n ) : (\n <>\n \n \n \n \n )}\n {hoveredOrganisation ? (\n setHoveredOrganisation(null)}\n />\n ) : null}\n \n
\n
\n

1

\n

100

\n
\n
\n .\n
\n
\n \n \n );\n};\n\nexport default Map;\n","import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nconst MobileControls: React.FC<{\n filtersHidden: boolean;\n mapHidden: boolean;\n onToggleFilters: () => void;\n onToggleMap: () => void;\n}> = ({ onToggleFilters, onToggleMap, filtersHidden, mapHidden }) => {\n const { t } = useTranslation();\n return (\n
\n \n
\n \n {t(\"mobile.list\")}\n \n \n {t(\"mobile.map\")}\n \n
\n
\n );\n};\n\nexport default MobileControls;\n","function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\nimport * as React from \"react\";\n\nvar _ref2 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M18.5244 13.7375L12.7994 8L18.5244 2.2625L16.7619 0.5L9.26191 8L16.7619 15.5L18.5244 13.7375Z\"\n});\n\nvar _ref3 = /*#__PURE__*/React.createElement(\"path\", {\n d: \"M9.26269 13.7375L3.53769 8L9.2627 2.2625L7.5002 0.5L0.000194047 8L7.50019 15.5L9.26269 13.7375Z\"\n});\n\nfunction SvgLeftPointingChevrons(_ref, svgRef) {\n var title = _ref.title,\n titleId = _ref.titleId,\n props = _objectWithoutProperties(_ref, [\"title\", \"titleId\"]);\n\n return /*#__PURE__*/React.createElement(\"svg\", _extends({\n width: 19,\n height: 16,\n viewBox: \"0 0 19 16\",\n fill: \"#B1D7FF\",\n xmlns: \"http://www.w3.org/2000/svg\",\n ref: svgRef,\n \"aria-labelledby\": titleId\n }, props), title ? /*#__PURE__*/React.createElement(\"title\", {\n id: titleId\n }, title) : null, _ref2, _ref3);\n}\n\nvar ForwardRef = /*#__PURE__*/React.forwardRef(SvgLeftPointingChevrons);\nexport default __webpack_public_path__ + \"static/media/left-pointing-chevrons.1cf0fe39.svg\";\nexport { ForwardRef as ReactComponent };","import React, { Dispatch, SetStateAction } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n\nimport { ReactComponent as LeftPointingChevrons } from \"../../assets/left-pointing-chevrons.svg\";\n\nconst Navbar: React.FC<{\n setSidebarOpen: Dispatch>;\n}> = ({ setSidebarOpen }) => {\n const { t } = useTranslation();\n\n return (\n
\n

\n
{t(\"title\")}
\n
\n {\n setSidebarOpen(false);\n }}\n >\n
\n

\n
\n );\n};\n\nexport default Navbar;\n","import React from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport { Link } from \"react-router-dom\";\n\nconst IntroText: React.FC = () => {\n const { t } = useTranslation();\n\n return (\n
\n

{t(\"introduction_text_part_one\")}

\n

\n \n {t(\"introduction_text_part_three\")}\n \n

\n
\n );\n};\n\nexport default IntroText;\n","import { Dict } from \"./react-app-env\";\n\nconst escapeQuotes = (str: string): string => {\n return `\"${str.replace(/\"/, '\"')}\"`;\n};\n\n// eslint-disable-next-line import/prefer-default-export\nexport const stringify = (dicts: Dict[]): string => {\n if (dicts.length < 1) {\n return \"\";\n }\n const columns = Object.keys(dicts[0]);\n const rows = [columns.map(escapeQuotes).join(\",\")];\n for (const dict of dicts) {\n const row = columns.map((c) => escapeQuotes(dict[c])).join(\",\");\n rows.push(row);\n }\n return rows.join(\"\\n\");\n};\n","export default __webpack_public_path__ + \"static/media/women-led.e2b032b3.svg\";","export default __webpack_public_path__ + \"static/media/youth-led.baf2c609.svg\";","export default __webpack_public_path__ + \"static/media/registered.bd270c7a.svg\";","/* eslint-disable react/no-array-index-key */\nimport classNames from \"classnames\";\nimport React, { useContext } from \"react\";\nimport { Link } from \"react-router-dom\";\nimport { TRUE_CONSTANT } from \"../../constants\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport { useTranslation } from \"react-i18next\";\nimport useLanguage from \"../../hooks/useLanguage\";\nimport { Dict, DisplayItem, Organisation } from \"../../react-app-env\";\nimport { getTranslation } from \"../../util\";\nimport womenLedIcon from \"../../assets/women-led.svg\";\nimport youthLedIcon from \"../../assets/youth-led.svg\";\nimport registeredIcon from \"../../assets/registered.svg\";\n\nexport const createProfileElement = (\n properties: Dict,\n elementConfig: DisplayItem,\n language: string,\n currency: string\n): JSX.Element => {\n let content;\n // console.log(properties)\n console.log(elementConfig)\n // console.log(language)\n // console.log(currency)\n // console.log('-----------------------------')\n\n const noData = {language === \"fr\" ? \"Pas de données\" : \"No data\"};\n\n const FCFA_TO_USD_RATE = process.env.FCFA_TO_USD_RATE\n ? parseInt(process.env.FCFA_TO_USD_RATE, 10)\n : 0.0018;\n\n if (elementConfig.type === \"field\") {\n const key = elementConfig.content as string;\n\n if (elementConfig.contentType === \"list\") {\n const items = properties[key].split(\";\");\n const uniqueItems: string[] = [];\n\n for (let i = 0; i < items.length; i += 1) {\n const x = items[i];\n if (!uniqueItems.includes(x)) {\n uniqueItems.push(x);\n }\n }\n\n content = uniqueItems.length\n ?
    {uniqueItems.map((x) =>
  • {x}
  • )}
\n : noData;\n } else if (elementConfig.contentType === \"boolean\") {\n let icon;\n switch (key) {\n case \"Female-led\":\n icon = \"female;\n break;\n case \"Youth-led\":\n icon = \"youth;\n break;\n default:\n icon = \"tick;\n }\n\n const display =\n properties[key] === TRUE_CONSTANT || properties[key] === \"1\";\n\n content = display ? (\n \n {icon}\n {getTranslation(elementConfig.label, language)}\n \n ) : null;\n } else if (\n key === \"Nombre de femmes salariées\" ||\n key === \"Nombre d'hommes salariés\"\n ) {\n content = properties[key] ? Number(properties[key]).toFixed() : noData;\n } else if (\n key ===\n \"Si oui, quel est votre budget annuel pour le dernier exercice financier ?\" ||\n key === \"Annual budget\"\n ) {\n content = properties[key]\n ? `${(\n Number(properties[key]) *\n (currency === \"USD\" ? FCFA_TO_USD_RATE : 1)\n ).toLocaleString(language)} ${currency}`\n : noData;\n } else {\n content = properties[key] ? properties[key] : noData;\n }\n } else if (elementConfig.type === \"sum\") {\n const keys = (elementConfig.content as string).split(\" + \");\n\n const total = keys.reduce(\n (sum, key) => sum + parseInt(properties[key], 10),\n 0\n );\n\n content = total || noData;\n } else {\n content = getTranslation(elementConfig.content, language);\n }\n\n switch (elementConfig.contentType) {\n case \"label\":\n return {content};\n case \"heading\":\n return

{content}

;\n default:\n return {content};\n }\n};\n\nconst createProfileTable = (\n properties: Dict,\n elementConfig: DisplayItem,\n language: string,\n currency: string\n) => {\n return (\n 1 ? \"grid-cols-2\" : \"\"}`}\n >\n {elementConfig.rows.map((config) => {\n return config.map((item, i) => (\n
\n {createProfileElement(properties, item, language, currency)}\n
\n ));\n })}\n \n );\n};\n\nconst createProfileHtml = (\n properties: Dict,\n config: DisplayItem[],\n language: string,\n currency: string\n) => {\n return (\n <>\n {config.map((c, i) => (\n
\n {c.rows\n ? createProfileTable(properties, c, language, currency)\n : createProfileElement(properties, c, language, currency)}\n
\n ))}\n \n );\n};\n\nconst OrgListItem: React.FC<{\n org: Organisation;\n highlight: boolean;\n currency: string;\n}> = ({ org, highlight, currency }) => {\n const appConfig = useContext(AppConfigContext);\n const language = useLanguage();\n const { t, i18n } = useTranslation();\n\n const linkClasses = classNames(\n \"org-list-item block p-4 border-2 mb-2 hover:bg-lighterblue\",\n highlight === true ? \"bg-lighterblue\" : \"bg-white\"\n );\n\n return (\n \n {createProfileHtml(\n org.data,\n appConfig.config.organisationSummary,\n language,\n currency\n )}\n \n \n );\n};\n\nexport default OrgListItem;\n","import { faDownload, faLink } from \"@fortawesome/free-solid-svg-icons\";\nimport { FontAwesomeIcon } from \"@fortawesome/react-fontawesome\";\nimport React, {\n useContext,\n useEffect,\n useState,\n Dispatch,\n SetStateAction,\n} from \"react\";\nimport { useTranslation } from \"react-i18next\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport FilterStatesContext from \"../../context/FilterStatesContext\";\nimport OrganisationsContext from \"../../context/OrganisationsContext\";\nimport { stringify } from \"../../csv\";\nimport { Organisation } from \"../../react-app-env\";\nimport { filterOrganisationsByCoordinates } from \"../map/util\";\nimport OrgListItem from \"../orglistitem/OrgListItem\";\nimport { ReactComponent as LeftPointingChevrons } from \"../../assets/left-pointing-chevrons.svg\";\n\nconst PAGE_SIZE = 50;\n\nconst OrgList: React.FC<{\n hoveredOrganisation: Organisation | null | undefined;\n setOrgListOpen: Dispatch>;\n currency: string;\n}> = ({ hoveredOrganisation, setOrgListOpen, currency }) => {\n const {\n config: { organisationFieldNames },\n } = useContext(AppConfigContext);\n const { organisations, loading } = useContext(OrganisationsContext);\n const { locationFilter } = useContext(FilterStatesContext);\n const { t } = useTranslation();\n const [limit, setLimit] = useState(PAGE_SIZE);\n const [copied, setCopied] = useState(false);\n\n // Reset pagination when the organisations change\n useEffect(() => {\n setLimit(PAGE_SIZE);\n }, [organisations]);\n\n organisations.sort((orgA, orgB) => {\n const cleanName = (name: string) =>\n name.replaceAll('\"', '').replaceAll('(', '').replaceAll('/', '').trim();\n\n const cleanOrgAName = cleanName(orgA.name);\n const cleanOrgBName = cleanName(orgB.name);\n\n return cleanOrgAName.localeCompare(cleanOrgBName);\n });\n\n const onClickCopy = () => {\n const textField = document.createElement(\"textarea\");\n textField.innerText = window.location.href;\n document.body.appendChild(textField);\n if (window.navigator.platform === \"iPhone\") {\n textField.setSelectionRange(0, 99999);\n } else {\n textField.select();\n }\n document.execCommand(\"copy\");\n textField.remove();\n setCopied(true);\n setTimeout(() => setCopied(false), 3000);\n };\n\n // Only show organisations that are currently visible on the map\n // This filter isn't done globally because the map needs all the data to render\n // the heatmap properly\n const visibleOrganisations = locationFilter\n ? filterOrganisationsByCoordinates(\n organisations,\n locationFilter,\n organisationFieldNames.coordinates\n )\n : organisations;\n\n return loading ? (\n
\n

{t(\"loading\")}

\n
\n ) : (\n
\n
\n

\n \n {visibleOrganisations.length}{\" \"}\n \n \n {t(\"organisations.peacebuilding\", {\n count: visibleOrganisations.length,\n })}\n \n

\n setOrgListOpen(false)}\n className=\"p-2\"\n >\n
\n
\n o.data))\n )}`}\n >\n \n {t(\"organisations.download\")}\n \n \n
\n
    \n {visibleOrganisations.slice(0, limit).map((org) => (\n
  • \n \n
  • \n ))}\n
\n {limit < visibleOrganisations.length ? (\n
\n setLimit(limit + PAGE_SIZE)}\n >\n {t(\"organisations.load_more\")}\n \n
\n ) : null}\n
\n );\n};\n\nexport default OrgList;\n","export default __webpack_public_path__ + \"static/media/email.e0d40520.svg\";","export default __webpack_public_path__ + \"static/media/link.5902933b.svg\";","/* eslint-disable react/no-array-index-key */\nimport React, { useContext, useEffect } from \"react\";\nimport { useTranslation } from \"react-i18next\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport {marked} from \"marked\";\n\nimport { useParams, useHistory } from \"react-router-dom\";\nimport EmailIcon from \"../../assets/email.svg\";\nimport LinkIcon from \"../../assets/link.svg\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport OrganisationsContext from \"../../context/OrganisationsContext\";\nimport {\n getTranslation,\n extractEmailAddress,\n extractWebAddress,\n} from \"../../util\";\nimport Modal from \"../modal/Modal\";\nimport { createProfileElement } from \"../orglistitem/OrgListItem\";\n\nconst getMarkdownText = (text: string, language: string) => {\n if (text) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const rawMarkup = marked.parse(text, { smartLists: true, breaks: true });\n return { __html: `
${rawMarkup}
` };\n }\n\n const noData =\n language === \"fr\" ? \"Pas de données\" : \"No data\";\n return { __html: noData };\n};\n\nconst OrgView: React.FC<{\n currency: string;\n}> = ({ currency }) => {\n const history = useHistory();\n const {\n i18n: { language },\n t,\n } = useTranslation();\n const { slug } = useParams<{ slug: string }>();\n const {\n config: { organisationDisplay, organisationFieldNames },\n } = useContext(AppConfigContext);\n const { organisations, setFocusedOrganisation } = useContext(\n OrganisationsContext\n );\n\n const organisation = organisations.find((o) => o.slug === slug);\n\n useEffect(() => {\n if (organisation) {\n setFocusedOrganisation(organisation);\n }\n }, [organisation, setFocusedOrganisation]);\n\n if (!organisation) {\n return null;\n }\n\n const { data } = organisation;\n\n const email = extractEmailAddress(data);\n const webAddress = extractWebAddress(data);\n\n return (\n history.push(\"/\")}>\n
\n

\n {data[organisationFieldNames.name]}\n

\n
\n {email && (\n \n \n {t(\"organisations.send_email\")}\n \n )}\n {webAddress && (\n \n \n {t(\"organisations.visit_website\")}\n \n )}\n
\n {organisationDisplay.map((item, i) => (\n \n

\n {getTranslation(item.heading, language)}\n

\n {item.body && (\n \n )}\n {item.rows && (\n
\n {item.rows.map((row) =>\n row.map((col, j) => (\n
\n {createProfileElement(data, col, language, currency)}\n
\n ))\n )}\n
\n )}\n
\n ))}\n \n
\n );\n};\n\nexport default OrgView;\n","import classNames from \"classnames\";\nimport React, { useContext, useEffect, useState } from \"react\";\nimport { Helmet } from \"react-helmet-async\";\nimport { useTranslation } from \"react-i18next\";\nimport { BrowserRouter as Router, Route, Switch } from \"react-router-dom\";\nimport { ReactComponent as RightPointingChevrons } from \"../../assets/right-pointing-chevrons.svg\";\nimport { MOBILE_BREAKPOINT } from \"../../constants\";\nimport AppConfigContext from \"../../context/AppConfigContext\";\nimport FilterStatesContext from \"../../context/FilterStatesContext\";\nimport useLanguage from \"../../hooks/useLanguage\";\nimport { Organisation } from \"../../react-app-env\";\nimport About from \"../about/About\";\nimport Reports from \"../reports/Reports\";\nimport Filters from \"../filters/Filters\";\nimport Footer from \"../footer/Footer\";\nimport LoadingOverlay from \"../loadingoverlay/LoadingOverlay\";\nimport Map from \"../map/Map\";\nimport MobileControls from \"../mobilecontrols/MobileControls\";\nimport Navbar from \"../navbar/Navbar\";\nimport IntroText from \"../navbar/IntroText\";\nimport OrgList from \"../orglist/OrgList\";\nimport OrgView from \"../orgview/OrgView\";\n\n// This component handles the layout, but look in index.tsx for data management\nconst App: React.FC = () => {\n const language = useLanguage();\n const [currency, setCurrency] = useState(\"USD\");\n const { t, i18n } = useTranslation();\n const { ready } = useContext(AppConfigContext);\n const [isMobile, setMobile] = useState(window.innerWidth < MOBILE_BREAKPOINT);\n const [filtersHidden, setFiltersHidden] = useState(isMobile);\n const [mapHidden, setMapHidden] = useState(isMobile);\n const { clearAllFilters } = useContext(FilterStatesContext);\n\n useEffect(() => {\n const resizeListener = () => {\n const isNowMobile = window.innerWidth < MOBILE_BREAKPOINT;\n setMobile(isNowMobile);\n setFiltersHidden(isNowMobile);\n setMapHidden(isNowMobile);\n };\n window.addEventListener(\"resize\", resizeListener);\n return () => window.removeEventListener(\"resize\", resizeListener);\n }, []);\n\n const [sidebarOpen, setSidebarOpen] = useState(true);\n const [orgListOpen, setOrgListOpen] = useState(true);\n const [viewMode, setViewMode] = useState(\"points\");\n\n const [\n hoveredOrganisation,\n setHoveredOrganisation,\n ] = useState();\n\n const clearFilters = () => {\n clearAllFilters();\n };\n\n const closedLeftPanel = (\n
\n {\n setSidebarOpen(true);\n }}\n >\n
\n );\n\n const openLeftPanel = (\n
\n
\n \n \n setFiltersHidden(!filtersHidden)}\n onToggleMap={() => setMapHidden(!mapHidden)}\n />\n {filtersHidden ? null : }\n
\n clearFilters()}\n >\n {t(\"clear_filters\")}\n \n
\n
\n {!isMobile &&
}\n
\n );\n\n const orgListColumnClasses = classNames(\n \"flex-1 md:block md:border-r-2 overflow-auto p-2 bg-gray-100 md:max-h-screen md:overflow-y-scroll\",\n mapHidden ? \"block\" : \"hidden\"\n );\n\n const openOrgList = (\n
\n \n {isMobile &&
}\n
\n );\n\n const closedOrgList = (\n
\n {\n setOrgListOpen(true);\n }}\n className=\"py-tiny\"\n >\n
\n );\n\n const panelContainerClasses = classNames(\n \"flex flex-col min-h-screen md:min-h-0 md:h-full\",\n sidebarOpen ? \"md:flex md:flex-row\" : \"md:flex md:flex-row\"\n );\n\n const mapColumnClasses = classNames(\n \"flex flex-col md:max-h-screen md:overflow-y-scroll\",\n mapHidden ? \"invisible\" : \"visible\",\n sidebarOpen ? \"flex-grow\" : \"flex-2\"\n );\n\n const pointButtonClasses = classNames(\n \"border p-3 border-solid border-gray-400 rounded-l\",\n viewMode === \"points\"\n ? \"bg-gray-200 font-medium\"\n : \"bg-white font-extralight\"\n );\n\n const heatmapButtonClasses = classNames(\n \"border p-3 border-l-0 border-solid border-gray-400 rounded-r\",\n viewMode === \"heatmap\"\n ? \"bg-gray-200 font-medium\"\n : \"bg-white font-extralight\"\n );\n\n return (\n <>\n \n {t(\"title\")}\n \n {ready ? (\n \n
\n {sidebarOpen ? openLeftPanel : closedLeftPanel}\n
\n setCurrency(e.target.value)}\n >\n \n \n \n i18n.changeLanguage(e.target.value)}\n >\n \n \n \n
\n {orgListOpen ? openOrgList : closedOrgList}\n
\n
\n setViewMode(\"points\")}\n type=\"button\"\n className={pointButtonClasses}\n >\n {t(\"map.points\")}\n \n setViewMode(\"heatmap\")}\n type=\"button\"\n className={heatmapButtonClasses}\n >\n {t(\"map.heatmap\")}\n \n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n ) : (\n \n )}\n \n );\n};\n\nexport default App;\n","import axios from \"axios\";\nimport {\n API_URL,\n FALSE_CONSTANT,\n ORGANISATION_FOCUS_PROPERTY,\n TRUE_CONSTANT,\n} from \"../constants\";\nimport i18n from \"../i18n\";\nimport {\n AppConfig,\n Dict,\n DisplayItem,\n FilterConfig,\n FilterStates,\n LanguageMap,\n Option,\n Organisation,\n} from \"../react-app-env\";\nimport { slugify, titleCase } from \"../util\";\n\n// const client = axios.create({ baseURL: API_URL });\nconst client = axios.create();\nconst apiURL = API_URL;\n\ninterface PartialFilterConfig {\n type: string;\n labels: LanguageMap;\n fieldName: string;\n options: (string | number)[];\n}\n\ninterface AppDataResponse {\n display_config: {\n filters: PartialFilterConfig[];\n summary: DisplayItem[];\n profile: DisplayItem[];\n name_fieldname: string;\n country_fieldname: string;\n coords_fieldname: string;\n jeunes_fieldname: string;\n femmes_fieldname: string;\n border_base_fieldname: string;\n registered_fieldname: string;\n size_fieldname: string;\n budget_fieldname: string;\n };\n data: {\n data_id: string;\n versions: { data: Dict }[];\n }[];\n}\n\ninterface AppData {\n config: AppConfig;\n organisations: Organisation[];\n}\n\nexport default class API {\n // Always access through API.loadAppData() to ensure data is available\n static appData: AppData;\n\n static async loadAppData(refreshAppData = false): Promise {\n if (!API.appData || refreshAppData) {\n try {\n const response = await client.get(API_URL || \"/mapping_project.json\", {\n onDownloadProgress: (progressEvent) => {\n const progressStatus = document.querySelector('#progress') || Object();\n if (progressStatus !== Object()) {\n // Temporarily hardcoding the expected size of data\n progressStatus.textContent = `Loaded: ${Math.round(((progressEvent.loaded) / 4300000) * 100)}%`;\n }\n }\n });\n const appData: AppDataResponse = response.data;\n\n const config: AppConfig = {\n filters: [],\n organisationSummary: appData.display_config.summary,\n organisationDisplay: appData.display_config.profile,\n organisationFieldNames: {\n name: appData.display_config.name_fieldname,\n country: appData.display_config.country_fieldname,\n coordinates: appData.display_config.coords_fieldname,\n jeunes: appData.display_config.jeunes_fieldname,\n femmes: appData.display_config.femmes_fieldname,\n borderBase: appData.display_config.border_base_fieldname,\n registered: appData.display_config.registered_fieldname,\n size: appData.display_config.size_fieldname,\n budget: appData.display_config.budget_fieldname,\n },\n };\n\n const organisations = appData.data.map((item) =>\n API.parseOrganisationData(item, config)\n );\n\n const filters = API.extractFilterOptions(\n appData.display_config.filters,\n organisations\n );\n\n API.appData = {\n config: {\n ...config,\n filters,\n },\n organisations,\n };\n } catch (e: any) {\n // TODO: global error handling\n // eslint-disable-next-line no-console\n console.error(e.message);\n }\n }\n return API.appData;\n }\n\n static async loadConfig(refreshAppData = false): Promise {\n const appData = await API.loadAppData(refreshAppData);\n return appData.config;\n }\n\n static async loadOrganisations(\n filters: FilterStates,\n refreshAppData = false\n ): Promise {\n // TODO: do the filtering on the server\n const {\n organisations,\n config: { filters: filterConfigs },\n } = await API.loadAppData(refreshAppData);\n\n // Filter the organisations\n // Organisations must match at least one value in each filter to be included\n return organisations.filter((org) => {\n // Don't show organisations with no data\n if (!org.data) {\n return false;\n }\n\n // Iterate through all the filters, AND-ing them together\n return filters.reduce((result, filter) => {\n // Early exit if an earlier filter failed\n if (!result) {\n return false;\n }\n\n // If no options are specified, don't filter anything\n if (!filter.values.length) {\n return true;\n }\n\n // If the organisation doesn't have a matching field, don't filter it\n // This could happen with incorrect or out-of-date URLs\n if (typeof org.data[filter.fieldName] === \"undefined\") {\n return true;\n }\n\n const filterConfig = filterConfigs.find(\n (f) => f.fieldName === filter.fieldName\n );\n\n if (filterConfig?.type === \"interval\") {\n const orgValue = Number(org.data[filter.fieldName]);\n const { options } = filterConfig;\n // This works because the options are in descending order\n // See API.prepareOptions()\n const matchingOption = options.find(\n (o) => Number(o.value) < orgValue\n );\n const match =\n matchingOption && filter.values.includes(matchingOption.value);\n return match || false;\n }\n\n // Check that there is a matching value in the organisation and the filter\n const orgValues = org.data[filter.fieldName]\n .split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n const intersect = orgValues.filter((v) => filter.values.includes(v));\n return intersect.length > 0;\n }, true);\n });\n }\n\n /**\n * Convert the raw data from the API to an Organisation.\n * Cleans some fields, and adds derived fields.\n *\n * At the moment, all the fields are strings, but this should\n * change if and when Organisation becomes properly defined and typed.\n *\n */\n static parseOrganisationData(\n data: {\n data_id: string;\n versions: { data: Dict }[];\n },\n config: AppConfig\n ): Organisation {\n const language = i18n.language === \"en-GB\" ? \"en\" : i18n.language;\n\n const dataInLanguage = data.versions.find((version) => {\n // @ts-expect-error Need to tighten typescript definitions here.\n return version.language === language;\n });\n\n const latestData = dataInLanguage?.data || {};\n const name = latestData[config.organisationFieldNames.name];\n\n const cleanData = Object.keys(latestData).reduce(\n (clean, fieldName) => {\n return {\n ...clean,\n [fieldName]: API.cleanData(fieldName, latestData[fieldName], config),\n };\n },\n {}\n );\n\n cleanData[ORGANISATION_FOCUS_PROPERTY] = API.deriveOrganisationFocus(\n cleanData,\n config\n );\n\n return {\n id: data.data_id,\n name,\n slug: slugify(name),\n data: cleanData,\n };\n }\n\n static deriveOrganisationFocus(data: Dict, config: AppConfig): string {\n const focuses = [];\n const language = i18n.language === \"en-GB\" ? \"en\" : i18n.language;\n if (\n (data[config.organisationFieldNames.femmes] || \"\")\n .toLowerCase()\n .trim()\n .includes(\"oui\") ||\n (data[config.organisationFieldNames.femmes] || \"\")\n .toLowerCase()\n .trim()\n .includes(\"yes\")\n ) {\n const label = language === \"fr\" ? \"Femmes\" : \"Women\";\n focuses.push(label);\n }\n if (\n (data[config.organisationFieldNames.jeunes] || \"\")\n .toLowerCase()\n .trim()\n .includes(\"oui\") ||\n (data[config.organisationFieldNames.jeunes] || \"\")\n .toLowerCase()\n .trim()\n .includes(\"yes\")\n ) {\n const label = language === \"fr\" ? \"Jeunes\" : \"Youth\";\n focuses.push(label);\n }\n if ((data[config.organisationFieldNames.borderBase] || \"\").trim()) {\n const label =\n language === \"fr\" ? \"Base transfrontalière\" : \"Cross-border\";\n focuses.push(label);\n }\n return focuses.join(\";\");\n }\n\n static cleanData(fieldName: string, str: string, config: AppConfig): string {\n // Organisations encode multiple values with ';'\n const values = str.split(\";\");\n const cleanValues = values\n .map((value) => API.cleanValue(fieldName, value, config))\n .filter(Boolean);\n return cleanValues.join(\";\");\n }\n\n static cleanValue(\n fieldName: string,\n value: string,\n config: AppConfig\n ): string | number {\n let clean = value.trim().replace(/,$/, \"\");\n if (fieldName === config.organisationFieldNames.country) {\n clean = titleCase(clean.replace(/[\\s-]+/, \" \"));\n if ([\"Burkirna Faso\", \"Burkina\", \"Burkina Fso\"].includes(clean)) {\n clean = \"Burkina Faso\";\n }\n }\n if (fieldName === config.organisationFieldNames.budget) {\n const isEUR = clean.includes(\"EUR\");\n const isUSD = clean.includes(\"USD\");\n\n const USD_TO_FCFA = process.env.USD_TO_FCFA_RATE\n ? parseInt(process.env.USD_TO_FCFA_RATE, 10)\n : 565.66;\n\n const EUR_TO_FCFA = process.env.EUR_TO_FCFA_RATE\n ? parseInt(process.env.EUR_TO_FCFA_RATE, 10)\n : 656.92;\n\n // eslint-disable-next-line no-nested-ternary\n const scalar = isEUR ? EUR_TO_FCFA : isUSD ? USD_TO_FCFA : 1;\n const intVal = parseInt(clean.replace(/[^0-9]/g, \"\"), 10);\n return Number((intVal * scalar).toPrecision(3));\n }\n if (fieldName === config.organisationFieldNames.registered) {\n return [\"oui\", \"yes\"].includes(clean.toLowerCase()) ? TRUE_CONSTANT : FALSE_CONSTANT;\n }\n return clean;\n }\n\n // Combine the list of filters with the list of organisations to populate the filters with options\n static extractFilterOptions(\n filterConfigs: PartialFilterConfig[],\n organisations: Organisation[]\n ): FilterConfig[] {\n const filters = filterConfigs.map((f) => {\n return {\n ...f,\n options: API.prepareOptions(f),\n };\n });\n\n // For each organisation add its properties to the corresponding filter\n for (const org of organisations) {\n // Iterate over data properties\n for (const fieldName of Object.keys(org.data)) {\n const rawValue = org.data[fieldName].trim();\n\n // Find the matching filter\n const filter = filters.find((f) => f.fieldName === fieldName);\n\n if (rawValue && filter) {\n if (filter.type === \"list\") {\n const { options } = filter;\n\n // Organisations encode multiple values for a filter with ';'\n const allValues = rawValue.split(\";\");\n\n const uniqueValues = Object.keys(\n allValues.reduce((obj, v) => ({ ...obj, [v]: true }), {})\n );\n\n // For each value, add it to the filter as an option\n for (const value of uniqueValues) {\n let option = options.find((o) => o.value === value);\n\n if (!option) {\n option = { label: value, value, count: 0 };\n options.push(option);\n }\n\n option.count += 1;\n }\n } else if (filter.type === \"interval\") {\n const { options } = filter;\n\n const intVal = parseInt(rawValue, 10);\n\n if (intVal) {\n const matchingOption = options.find(\n (o) => Number(o.value) < intVal\n );\n if (matchingOption) {\n matchingOption.count += 1;\n }\n }\n }\n }\n }\n }\n\n return filters;\n }\n\n /**\n * Converts filter options from the API into Options objects.\n */\n static prepareOptions(filter: PartialFilterConfig): Option[] {\n if (filter.type === \"interval\") {\n const options = [];\n let last = null;\n\n filter.options.sort((a, b) => {\n return Number(b) - Number(a);\n });\n\n for (const option of filter.options) {\n const label =\n last === null\n ? `> ${option.toLocaleString()}`\n : `${option.toLocaleString()} - ${last.toLocaleString()}`;\n\n options.push({ label, value: String(option), count: 0 });\n last = option;\n }\n return options;\n }\n\n return (filter.options || []).map((o: string | number) => ({\n label: String(o),\n value: String(o),\n count: 0,\n }));\n }\n}\n","import React, { useEffect, useState } from \"react\";\nimport AppConfigContext from \"../context/AppConfigContext\";\nimport i18n from \"../i18n\";\nimport { AppConfig } from \"../react-app-env\";\nimport API from \"../services/API\";\n\nconst AppConfigProvider: React.FC = ({ children }) => {\n const [ready, setReady] = useState(false);\n const [config, setConfig] = useState({\n filters: [],\n organisationSummary: [],\n organisationDisplay: [],\n organisationFieldNames: {\n name: \"\",\n country: \"\",\n coordinates: \"\",\n registered: \"\",\n jeunes: \"\",\n femmes: \"\",\n borderBase: \"\",\n size: \"\",\n budget: \"\",\n },\n });\n\n // Load the filters from the API when this Provider is mounted\n useEffect(() => {\n const load = async () => {\n const loadedConfig = await API.loadConfig();\n setConfig(loadedConfig);\n setReady(true);\n };\n\n load();\n }, []);\n\n useEffect(() => {\n i18n.on(\"languageChanged\", async () => {\n window.location.reload();\n });\n });\n\n return (\n \n {children}\n \n );\n};\n\nexport default AppConfigProvider;\n","import React, { useState } from \"react\";\nimport FilterStatesContext from \"../context/FilterStatesContext\";\nimport { Bounds, FilterStates } from \"../react-app-env\";\n\nconst saveFilters = (filters: FilterStates) => {\n const query = [];\n for (const filter of filters) {\n const fieldName = encodeURIComponent(filter.fieldName);\n for (const value of filter.values) {\n query.push(`${fieldName}[]=${encodeURIComponent(value)}`);\n }\n }\n const url = `${window.location.pathname}?${query.join(\"&\")}`;\n window.history.pushState(null, \"\", url);\n};\n\nconst loadFilters = () => {\n let { search } = window.location;\n const filters: FilterStates = [];\n if (!search) {\n return filters;\n }\n search = search.substring(1); // remove '?'\n const params = search.split(\"&\");\n for (const param of params) {\n // eslint-disable-next-line prefer-const\n let [fieldName, value] = param.split(\"=\");\n if (fieldName.endsWith(\"[]\")) {\n fieldName = fieldName.substring(0, fieldName.length - 2);\n }\n fieldName = decodeURIComponent(fieldName);\n let filter = filters.find((f) => f.fieldName === fieldName);\n if (!filter) {\n filter = {\n fieldName,\n values: [],\n };\n filters.push(filter);\n }\n filter.values.push(decodeURIComponent(value));\n }\n return filters;\n};\n\nconst FilterStatesProvider: React.FC = ({ children }) => {\n const [filters, setFilters] = useState(loadFilters());\n const [locationFilter, setLocationFilter] = useState(null);\n\n // Function for updating the values of a filter, used by components.\n // Causes OrganisationsProvider to reload data.\n const setFilterState = (fieldName: string, values: string[]) => {\n const nextFilters = [...filters];\n let filter = filters.find((f) => f.fieldName === fieldName);\n\n if (!filter) {\n filter = { fieldName, values: [] };\n nextFilters.push(filter);\n }\n\n filter.values = values;\n\n saveFilters(nextFilters);\n setFilters(nextFilters);\n\n // Reset location filter when the main filters change\n setLocationFilter(null);\n };\n\n const clearAllFilters = () => {\n setFilters([]);\n };\n\n return (\n \n {children}\n \n );\n};\n\nexport default FilterStatesProvider;\n","import React, { useContext, useEffect, useRef, useState } from \"react\";\nimport AppConfigContext from \"../context/AppConfigContext\";\nimport FilterStatesContext from \"../context/FilterStatesContext\";\nimport OrganisationsContext from \"../context/OrganisationsContext\";\nimport { Organisation } from \"../react-app-env\";\nimport API from \"../services/API\";\n\nconst OrganisationsProvider: React.FC = ({ children }) => {\n const { ready } = useContext(AppConfigContext);\n const { filterStates } = useContext(FilterStatesContext);\n\n const [loading, setLoading] = useState(true);\n const [map, setMap] = useState(null);\n\n // focusedOrganisation handles centering the map on the organisation marker\n // it is set when OrgView is rendered, but not unset until the filters change\n // this is so that the map remains centered on the organisation when the user returns to the org list\n const [\n focusedOrganisation,\n setFocusedOrganisation,\n ] = useState(null);\n const [organisations, setOrganisations] = useState([]);\n\n // Reload the data from the API when the filters change\n useEffect(() => {\n const load = async () => {\n setLoading(true);\n // Reset focused organisation when the organisations change\n setFocusedOrganisation(null);\n const orgs = await API.loadOrganisations(filterStates);\n setOrganisations(orgs);\n setLoading(false);\n };\n if (ready) {\n load();\n }\n }, [ready, filterStates]);\n\n const mapRef = useRef();\n\n return (\n \n {children}\n \n );\n};\n\nexport default OrganisationsProvider;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { HelmetProvider } from \"react-helmet-async\";\nimport \"./index.css\";\nimport \"./i18n\";\n\nimport App from \"./components/app/App\";\nimport AppConfigProvider from \"./providers/AppConfigProvider\";\nimport FilterStatesProvider from \"./providers/FilterStatesProvider\";\nimport OrganisationsProvider from \"./providers/OrganisationsProvider\";\n\n/**\n * Provider purposes:\n *\n * - HelmetProvider: Manage tags in components\n * - AppConfigProvider: Loads app config from the API on mount\n * - FilterStatesProvider: Records which filters are selected\n * - OrganisationsProvider: Updates the data when the filters change\n *\n */\n\nReactDOM.render(\n \n \n \n \n \n \n \n \n \n \n ,\n document.getElementById(\"root\")\n);\n"],"sourceRoot":""}