@abcagency/hc-ui-components 1.8.8 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/containers/list/item-list-container.js +8 -2
- package/dist/components/containers/list/item-list-container.js.map +1 -1
- package/dist/components/modules/filter/index.js +11 -2
- package/dist/components/modules/filter/index.js.map +1 -1
- package/dist/contexts/mapContext.js +28 -5
- package/dist/contexts/mapContext.js.map +1 -1
- package/dist/contexts/mapListContext.js +25 -6
- package/dist/contexts/mapListContext.js.map +1 -1
- package/package.json +1 -1
- package/src/components/containers/list/item-list-container.tsx +9 -2
- package/src/components/modules/filter/index.js +8 -2
- package/src/contexts/mapContext.tsx +25 -5
- package/src/contexts/mapListContext.tsx +27 -5
|
@@ -15,10 +15,16 @@ const ItemsListContainer = ({ fieldNames, showMap, fieldsShown, specialFeatures
|
|
|
15
15
|
const { selectedListItem } = useMap();
|
|
16
16
|
const { trackEvent, eventTypes } = useTrackEvent();
|
|
17
17
|
const itemExpandedContent = (item, recruiter) => item ? (ExpandListComponent ? React.createElement(ExpandListComponent, { listing: item }) : React.createElement(ListingDetailsContainer, { item: item, recruiter: recruiter })) : null;
|
|
18
|
+
// Track if component has mounted to avoid hydration mismatch with localStorage
|
|
19
|
+
const [hasMounted, setHasMounted] = React.useState(false);
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
setHasMounted(true);
|
|
22
|
+
}, []);
|
|
18
23
|
// Use useMemo to avoid hydration mismatch - create new array instead of mutating prop
|
|
24
|
+
// Don't add travelTime until after mount to avoid SSR/client mismatch from localStorage
|
|
19
25
|
const effectiveFieldsShown = useMemo(() => {
|
|
20
26
|
const fields = [...fieldsShown];
|
|
21
|
-
if (!fields.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0 && !noEntities) {
|
|
27
|
+
if (hasMounted && !fields.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0 && !noEntities) {
|
|
22
28
|
fields.push('travelTime');
|
|
23
29
|
fieldNames['travelTime'] = 'Commute';
|
|
24
30
|
}
|
|
@@ -26,7 +32,7 @@ const ItemsListContainer = ({ fieldNames, showMap, fieldsShown, specialFeatures
|
|
|
26
32
|
return fields.filter(x => x !== 'travelTime');
|
|
27
33
|
}
|
|
28
34
|
return fields;
|
|
29
|
-
}, [fieldsShown, commuteLocation, noEntities, fieldNames]);
|
|
35
|
+
}, [fieldsShown, commuteLocation, noEntities, fieldNames, hasMounted]);
|
|
30
36
|
const setTrackedSortSetting = (sortSetting) => {
|
|
31
37
|
trackEvent(eventTypes.LIST_SORTED, sortSetting);
|
|
32
38
|
setSortSetting(sortSetting);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"item-list-container.js","sources":["../../../../src/components/containers/list/item-list-container.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport useListLogic from '~/hooks/useList';\nimport { useMap } from '~/contexts/mapContext';\nimport { useMapList } from '~/contexts/mapListContext';\nimport { useTrackEvent } from '~/contexts/trackEventContext';\nimport ItemsList from '~/components/modules/list/item-list';\nimport Accordion from '~/components/modules/accordions/default';\nimport MapAccordionItemContainer from '~/components/containers/accordions/map-accordion-item-container';\nimport { dynamicSort } from '~/util/sortUtil';\nimport { Listing } from '~/types/Listings';\nimport ListingDetailsContainer from '../jobListing/listing-details-container';\n\ninterface ItemsListContainerProps {\n fieldNames: Record<string, string>;\n showMap: boolean;\n fieldsShown: string[];\n specialFeatures: any;\n}\n\nconst ItemsListContainer: React.FC<ItemsListContainerProps> = ({\n\tfieldNames,\n\tshowMap,\n\tfieldsShown,\n\tspecialFeatures\n}) => {\n\tconst { filteredListings, loading, commuteLocation, sortSetting, setSortSetting, ExpandListComponent, favorites, noEntities } = useMapList();\n\tconst { itemLimit, loader, scrollContainerRef, itemRefs } = useListLogic(filteredListings as any);\n\tconst { selectedListItem } = useMap();\n\tconst { trackEvent, eventTypes } = useTrackEvent() as any;\n\tconst itemExpandedContent = (item: any, recruiter: any) =>\n\t\titem ? (ExpandListComponent ? <ExpandListComponent listing={item} /> : <ListingDetailsContainer item={item} recruiter={recruiter} />) : null;\n\n\t// Use useMemo to avoid hydration mismatch - create new array instead of mutating prop\n\tconst effectiveFieldsShown = useMemo(() => {\n\t\tconst fields = [...fieldsShown];\n\t\tif (!fields.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0 && !noEntities) {\n\t\t\tfields.push('travelTime');\n\t\t\tfieldNames['travelTime'] = 'Commute';\n\t\t} else if (fields.includes('travelTime') && (!commuteLocation || noEntities)) {\n\t\t\treturn fields.filter(x => x !== 'travelTime');\n\t\t}\n\t\treturn fields;\n\t}, [fieldsShown, commuteLocation, noEntities, fieldNames]);\n\n\tconst setTrackedSortSetting = (sortSetting: { field: string; type: string }) => {\n\t\ttrackEvent(eventTypes.LIST_SORTED, sortSetting);\n\t\tsetSortSetting(sortSetting);\n\t};\n\t\t//fieldsShown.push('favorite');\n\n\treturn (\n\t\t<ItemsList\n\t\t\tfieldNames={fieldNames}\n\t\t\tshowMap={showMap}\n\t\t\tfieldsShown={effectiveFieldsShown}\n\t\t\tfilteredListings={filteredListings}\n\t\t\tloading={loading}\n\t\t\tsortSetting={sortSetting}\n\t\t\tsetSortSetting={setTrackedSortSetting}\n\t\t\titemLimit={itemLimit}\n\t\t\tloader={loader}\n\t\t\tscrollContainerRef={scrollContainerRef}\n\t\t\titemRefs={itemRefs}\n\t\t\tselectedListItem={selectedListItem}\n\t\t\tincludeFavorite={true}\n\t\t>\n\t\t\t<Accordion className=\"hc-divide-y hc-divide-uiAccent/10\" defaultValue={selectedListItem?.id}>\n\t\t\t\t{(sortSetting ? dynamicSort(filteredListings, sortSetting.field, sortSetting.type, favorites as any) : filteredListings)\n\t\t\t\t\t.slice(0, itemLimit)\n\t\t\t\t\t.map((item: Listing, index: number) => (\n\t\t\t\t\t\t<MapAccordionItemContainer\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tshowMap={showMap}\n\t\t\t\t\t\t\titem={item}\n\t\t\t\t\t\t\titemRefs={itemRefs}\n\t\t\t\t\t\t\tfieldsShown={effectiveFieldsShown}\n\t\t\t\t\t\t\titemExpandedContent={itemExpandedContent}\n\t\t\t\t\t\t\tspecialFeatures={specialFeatures}\n\t\t\t\t\t\t\tisActive={selectedListItem?.id === item.id}\n\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t</Accordion>\n\t\t</ItemsList>\n\t);\n};\n\nexport default ItemsListContainer;\n"],"names":[],"mappings":";;;;;;;;;;;AAmBA,MAAM,kBAAkB,GAAsC,CAAC,EAC9D,UAAU,EACV,OAAO,EACP,WAAW,EACX,eAAe,EACf,KAAI;IACJ,MAAM,EAAE,gBAAgB,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,mBAAmB,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAAC;AAC7I,IAAA,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,kBAAkB,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,gBAAuB,CAAC,CAAC;AAClG,IAAA,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,EAAE,CAAC;IACtC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,aAAa,EAAS,CAAC;IAC1D,MAAM,mBAAmB,GAAG,CAAC,IAAS,EAAE,SAAc,KACrD,IAAI,IAAI,mBAAmB,GAAI,KAAA,CAAA,aAAA,CAAC,mBAAmB,EAAC,EAAA,OAAO,EAAE,IAAI,EAAA,CAAI,GAAG,oBAAC,uBAAuB,EAAA,EAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAI,CAAA,IAAI,IAAI,CAAC;;AAG/I,IAAA,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAK;AACzC,QAAA,MAAM,MAAM,GAAG,CAAC,GAAG,WAAW,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,eAAe,IAAI,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE;
|
|
1
|
+
{"version":3,"file":"item-list-container.js","sources":["../../../../src/components/containers/list/item-list-container.tsx"],"sourcesContent":["import React, { useMemo } from 'react';\nimport useListLogic from '~/hooks/useList';\nimport { useMap } from '~/contexts/mapContext';\nimport { useMapList } from '~/contexts/mapListContext';\nimport { useTrackEvent } from '~/contexts/trackEventContext';\nimport ItemsList from '~/components/modules/list/item-list';\nimport Accordion from '~/components/modules/accordions/default';\nimport MapAccordionItemContainer from '~/components/containers/accordions/map-accordion-item-container';\nimport { dynamicSort } from '~/util/sortUtil';\nimport { Listing } from '~/types/Listings';\nimport ListingDetailsContainer from '../jobListing/listing-details-container';\n\ninterface ItemsListContainerProps {\n fieldNames: Record<string, string>;\n showMap: boolean;\n fieldsShown: string[];\n specialFeatures: any;\n}\n\nconst ItemsListContainer: React.FC<ItemsListContainerProps> = ({\n\tfieldNames,\n\tshowMap,\n\tfieldsShown,\n\tspecialFeatures\n}) => {\n\tconst { filteredListings, loading, commuteLocation, sortSetting, setSortSetting, ExpandListComponent, favorites, noEntities } = useMapList();\n\tconst { itemLimit, loader, scrollContainerRef, itemRefs } = useListLogic(filteredListings as any);\n\tconst { selectedListItem } = useMap();\n\tconst { trackEvent, eventTypes } = useTrackEvent() as any;\n\tconst itemExpandedContent = (item: any, recruiter: any) =>\n\t\titem ? (ExpandListComponent ? <ExpandListComponent listing={item} /> : <ListingDetailsContainer item={item} recruiter={recruiter} />) : null;\n\n\t// Track if component has mounted to avoid hydration mismatch with localStorage\n\tconst [hasMounted, setHasMounted] = React.useState(false);\n\tReact.useEffect(() => {\n\t\tsetHasMounted(true);\n\t}, []);\n\n\t// Use useMemo to avoid hydration mismatch - create new array instead of mutating prop\n\t// Don't add travelTime until after mount to avoid SSR/client mismatch from localStorage\n\tconst effectiveFieldsShown = useMemo(() => {\n\t\tconst fields = [...fieldsShown];\n\t\tif (hasMounted && !fields.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0 && !noEntities) {\n\t\t\tfields.push('travelTime');\n\t\t\tfieldNames['travelTime'] = 'Commute';\n\t\t} else if (fields.includes('travelTime') && (!commuteLocation || noEntities)) {\n\t\t\treturn fields.filter(x => x !== 'travelTime');\n\t\t}\n\t\treturn fields;\n\t}, [fieldsShown, commuteLocation, noEntities, fieldNames, hasMounted]);\n\n\tconst setTrackedSortSetting = (sortSetting: { field: string; type: string }) => {\n\t\ttrackEvent(eventTypes.LIST_SORTED, sortSetting);\n\t\tsetSortSetting(sortSetting);\n\t};\n\t\t//fieldsShown.push('favorite');\n\n\treturn (\n\t\t<ItemsList\n\t\t\tfieldNames={fieldNames}\n\t\t\tshowMap={showMap}\n\t\t\tfieldsShown={effectiveFieldsShown}\n\t\t\tfilteredListings={filteredListings}\n\t\t\tloading={loading}\n\t\t\tsortSetting={sortSetting}\n\t\t\tsetSortSetting={setTrackedSortSetting}\n\t\t\titemLimit={itemLimit}\n\t\t\tloader={loader}\n\t\t\tscrollContainerRef={scrollContainerRef}\n\t\t\titemRefs={itemRefs}\n\t\t\tselectedListItem={selectedListItem}\n\t\t\tincludeFavorite={true}\n\t\t>\n\t\t\t<Accordion className=\"hc-divide-y hc-divide-uiAccent/10\" defaultValue={selectedListItem?.id}>\n\t\t\t\t{(sortSetting ? dynamicSort(filteredListings, sortSetting.field, sortSetting.type, favorites as any) : filteredListings)\n\t\t\t\t\t.slice(0, itemLimit)\n\t\t\t\t\t.map((item: Listing, index: number) => (\n\t\t\t\t\t\t<MapAccordionItemContainer\n\t\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\t\tshowMap={showMap}\n\t\t\t\t\t\t\titem={item}\n\t\t\t\t\t\t\titemRefs={itemRefs}\n\t\t\t\t\t\t\tfieldsShown={effectiveFieldsShown}\n\t\t\t\t\t\t\titemExpandedContent={itemExpandedContent}\n\t\t\t\t\t\t\tspecialFeatures={specialFeatures}\n\t\t\t\t\t\t\tisActive={selectedListItem?.id === item.id}\n\t\t\t\t\t\t\tindex={index}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t</Accordion>\n\t\t</ItemsList>\n\t);\n};\n\nexport default ItemsListContainer;\n"],"names":[],"mappings":"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"}
|
|
@@ -28,9 +28,18 @@ var Filter = function Filter(_ref) {
|
|
|
28
28
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
29
29
|
showFixedFooter = _useState4[0],
|
|
30
30
|
setShowFixedFooter = _useState4[1];
|
|
31
|
+
var _useState5 = useState(false),
|
|
32
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
33
|
+
hasMounted = _useState6[0],
|
|
34
|
+
setHasMounted = _useState6[1];
|
|
31
35
|
var transitionTimeoutRef = useRef(null);
|
|
36
|
+
|
|
37
|
+
// Set mounted state to avoid hydration mismatch
|
|
38
|
+
useEffect(function () {
|
|
39
|
+
setHasMounted(true);
|
|
40
|
+
}, []);
|
|
32
41
|
useEffect(function () {
|
|
33
|
-
if (typeof window === 'undefined') return;
|
|
42
|
+
if (typeof window === 'undefined' || !hasMounted) return;
|
|
34
43
|
var checkOverflow = function checkOverflow() {
|
|
35
44
|
if (contentRef.current) {
|
|
36
45
|
// Add a small tolerance (5px) to avoid false positives from rounding/padding
|
|
@@ -95,7 +104,7 @@ var Filter = function Filter(_ref) {
|
|
|
95
104
|
clearTimeout(transitionTimeoutRef.current);
|
|
96
105
|
}
|
|
97
106
|
};
|
|
98
|
-
}, [children, hasOverflow]);
|
|
107
|
+
}, [children, hasOverflow, hasMounted]);
|
|
99
108
|
|
|
100
109
|
// Reusable button component
|
|
101
110
|
var MobileButtons = function MobileButtons() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/modules/filter/index.js"],"sourcesContent":["\"use client\";\nimport Button from \"~/components/modules/buttons/default\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { twMerge } from '~/util/twMerge';\nimport { useMapList } from \"~/contexts/mapListContext\";\n\nconst Filter = ({\n\tclassName,\n\thasActiveFilters,\n\tfilteredListings,\n\tselectedFilters,\n\tsetMobileTab,\n\thandleReset,\n\tisDesktop = false,\n\tstyle,\n\tchildren\n}) => {\n\tconst { filterConfig } = useMapList();\n\tconst contentRef = useRef(null);\n\tconst containerRef = useRef(null);\n\tconst [hasOverflow, setHasOverflow] = useState(false);\n\tconst [showFixedFooter, setShowFixedFooter] = useState(false);\n\tconst transitionTimeoutRef = useRef(null);\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return;\n\t\t\n\t\tconst checkOverflow = () => {\n\t\t\tif (contentRef.current) {\n\t\t\t\t// Add a small tolerance (5px) to avoid false positives from rounding/padding\n\t\t\t\tconst hasScroll = contentRef.current.scrollHeight > contentRef.current.clientHeight + 5;\n\n\t\t\t\tif (hasScroll !== hasOverflow) {\n\t\t\t\t\tsetHasOverflow(hasScroll);\n\n\t\t\t\t\t// Clear any pending transitions\n\t\t\t\t\tif (transitionTimeoutRef.current) {\n\t\t\t\t\t\tclearTimeout(transitionTimeoutRef.current);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add a delay when transitioning to fixed footer to smooth the transition\n\t\t\t\t\tif (hasScroll) {\n\t\t\t\t\t\ttransitionTimeoutRef.current = setTimeout(() => setShowFixedFooter(true), 200);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Delay hiding fixed footer to allow animation to complete and prevent flashing\n\t\t\t\t\t\ttransitionTimeoutRef.current = setTimeout(() => setShowFixedFooter(false), 200);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Delay initial check to ensure layout is complete\n\t\tsetTimeout(checkOverflow, 100);\n\n\t\t// Check on resize\n\t\twindow.addEventListener('resize', checkOverflow);\n\n\t\t// Use ResizeObserver to detect container size changes\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tsetTimeout(checkOverflow, 50);\n\t\t});\n\t\tif (containerRef.current) {\n\t\t\tresizeObserver.observe(containerRef.current);\n\t\t}\n\t\tif (contentRef.current) {\n\t\t\tresizeObserver.observe(contentRef.current);\n\t\t}\n\n\t\t// Use MutationObserver to detect content changes\n\t\tconst mutationObserver = new MutationObserver(() => {\n\t\t\tsetTimeout(checkOverflow, 50);\n\t\t});\n\t\tif (contentRef.current) {\n\t\t\tmutationObserver.observe(contentRef.current, { childList: true, subtree: true, attributes: true });\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('resize', checkOverflow);\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t\t// Clear timeout on unmount\n\t\t\tif (transitionTimeoutRef.current) {\n\t\t\t\tclearTimeout(transitionTimeoutRef.current);\n\t\t\t}\n\t\t};\n\t}, [children, hasOverflow]);\n\n\t// Reusable button component\n\tconst MobileButtons = () => (\n\t\t<>\n\t\t\t<Button.Btn\n\t\t\t\tonClick={handleReset}\n\t\t\t\tvariant=\"outline\"\n\t\t\t\tsize=\"sm\"\n\t\t\t\tclassName={filterConfig?.classNames?.resetButton}\n\t\t\t>\n\t\t\t\tReset All\n\t\t\t</Button.Btn>\n\t\t\t{selectedFilters && Object.keys(selectedFilters).length > 0 && (\n\t\t\t\t<Button.Btn\n\t\t\t\t\tonClick={() => setMobileTab(\"listTab\")}\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tclassName={twMerge(\n\t\t\t\t\t\t`${hasActiveFilters ? \"hc-opacity-0 hc-pointer-events-none\" : \"hc-opacity-100\"}`,\n\t\t\t\t\t\tfilterConfig?.classNames?.showJobsButton\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Button.Body>\n\t\t\t\t\t\t<Button.Icon icon=\"fluent:search-12-filled\" size=\"hc-size-3.5\" />\n\t\t\t\t\t\tShow {filteredListings.length} Jobs\n\t\t\t\t\t</Button.Body>\n\t\t\t\t</Button.Btn>\n\t\t\t)}\n\t\t</>\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tstyle={isDesktop ? style : undefined}\n\t\t\tclassName={twMerge(\n `/* Mobile layout */\n hc-relative hc-w-full hc-h-full hc-flex hc-flex-col\n\n /* Desktop layout */\n md:hc-relative md:hc-flex md:hc-flex-col md:hc-max-h-[100%]\n\n ${className ?? \"\"}`,\n filterConfig?.classNames?.filterContainer\n )}\n\t\t>\n\t\t\t{/* Content area with scroll */}\n\t\t\t<div\n\t\t\t\tref={contentRef}\n\t\t\t\tclassName={twMerge(\n\t\t\t\t\t`hc-w-full hc-flex-grow hc-max-h-full hc-overflow-auto ${hasOverflow ? 'hc-pb-16' : ''} md:hc-overflow-y-auto ${hasOverflow ? 'md:hc-pb-16' : 'md:hc-pb-0'}`,\n\t\t\t\t\tfilterConfig?.classNames?.filterContent\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<div className=\"hc-px-4 md:hc-pt-4 hc-space-y-4\">\n\t\t\t\t\t{children}\n\n\t\t\t\t\t{/* Inline buttons when no overflow - both mobile and desktop */}\n\t\t\t\t\t{!hasOverflow && !showFixedFooter && (\n\t\t\t\t\t\t<div className={twMerge(\n\t\t\t\t\t\t\t\"hc-flex hc-items-center hc-justify-between hc-gap-2 hc-py-2 hc-border-t hc-border-gray-200 hc-animate-in hc-fade-in hc-duration-300\",\n\t\t\t\t\t\t\tfilterConfig?.classNames?.filterFooter\n\t\t\t\t\t\t)}>\n\t\t\t\t\t\t\t{/* Mobile buttons */}\n\t\t\t\t\t\t\t<div className=\"hc-flex hc-items-center hc-justify-between hc-gap-2 hc-w-full md:hc-hidden\">\n\t\t\t\t\t\t\t\t<MobileButtons />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{/* Desktop button */}\n\t\t\t\t\t\t\t<div className=\"hc-hidden md:hc-flex\">\n\t\t\t\t\t\t\t\t<Button.Btn\n\t\t\t\t\t\t\t\t\tonClick={handleReset}\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tclassName={filterConfig?.classNames?.resetButton}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tReset All\n\t\t\t\t\t\t\t\t</Button.Btn>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Mobile Footer - fixed at bottom (only when overflow) */}\n\t\t\t{showFixedFooter && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"hc-w-full hc-absolute hc-bottom-0 hc-left-0 hc-right-0 hc-flex hc-items-center hc-justify-between hc-gap-2 hc-py-2 hc-px-4 hc-bg-gray-100 hc-border-t hc-border-gray-200 hc-z-50 md:hc-hidden hc-animate-in hc-fade-in hc-slide-in-from-bottom-2 hc-duration-200\"\n\t\t\t\t>\n\t\t\t\t\t<MobileButtons />\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Desktop Footer - fixed at bottom (only when overflow) */}\n\t\t\t{showFixedFooter && (\n\t\t\t\t<div className=\"hc-hidden md:hc-flex md:hc-justify-start hc-px-4 hc-py-4 hc-absolute hc-bottom-0 hc-left-0 hc-right-0 hc-bg-gray-100 hc-border-t hc-border-gray-200 hc-z-50 hc-animate-in hc-fade-in hc-slide-in-from-bottom-2 hc-duration-200\">\n\t\t\t\t\t<Button.Btn\n\t\t\t\t\t\tonClick={handleReset}\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tclassName={filterConfig?.classNames?.resetButton}\n\t\t\t\t\t>\n\t\t\t\t\t\tReset All\n\t\t\t\t\t</Button.Btn>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n\nexport default Filter;\n"],"names":["Filter","_ref","_filterConfig$classNa3","_filterConfig$classNa4","_filterConfig$classNa5","_filterConfig$classNa6","_filterConfig$classNa7","className","hasActiveFilters","filteredListings","selectedFilters","setMobileTab","handleReset","_ref$isDesktop","isDesktop","style","children","_useMapList","useMapList","filterConfig","contentRef","useRef","containerRef","_useState","useState","_useState2","_slicedToArray","hasOverflow","setHasOverflow","_useState3","_useState4","showFixedFooter","setShowFixedFooter","transitionTimeoutRef","useEffect","window","checkOverflow","current","hasScroll","scrollHeight","clientHeight","clearTimeout","setTimeout","addEventListener","resizeObserver","ResizeObserver","observe","mutationObserver","MutationObserver","childList","subtree","attributes","removeEventListener","disconnect","MobileButtons","_filterConfig$classNa","_filterConfig$classNa2","React","createElement","Fragment","Button","Btn","onClick","variant","size","classNames","resetButton","Object","keys","length","twMerge","concat","showJobsButton","Body","Icon","icon","ref","undefined","filterContainer","filterContent","filterFooter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/modules/filter/index.js"],"sourcesContent":["\"use client\";\nimport Button from \"~/components/modules/buttons/default\";\nimport React, { useEffect, useRef, useState } from \"react\";\nimport { twMerge } from '~/util/twMerge';\nimport { useMapList } from \"~/contexts/mapListContext\";\n\nconst Filter = ({\n\tclassName,\n\thasActiveFilters,\n\tfilteredListings,\n\tselectedFilters,\n\tsetMobileTab,\n\thandleReset,\n\tisDesktop = false,\n\tstyle,\n\tchildren\n}) => {\n\tconst { filterConfig } = useMapList();\n\tconst contentRef = useRef(null);\n\tconst containerRef = useRef(null);\n\tconst [hasOverflow, setHasOverflow] = useState(false);\n\tconst [showFixedFooter, setShowFixedFooter] = useState(false);\n\tconst [hasMounted, setHasMounted] = useState(false);\n\tconst transitionTimeoutRef = useRef(null);\n\n\t// Set mounted state to avoid hydration mismatch\n\tuseEffect(() => {\n\t\tsetHasMounted(true);\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined' || !hasMounted) return;\n\t\t\n\t\tconst checkOverflow = () => {\n\t\t\tif (contentRef.current) {\n\t\t\t\t// Add a small tolerance (5px) to avoid false positives from rounding/padding\n\t\t\t\tconst hasScroll = contentRef.current.scrollHeight > contentRef.current.clientHeight + 5;\n\n\t\t\t\tif (hasScroll !== hasOverflow) {\n\t\t\t\t\tsetHasOverflow(hasScroll);\n\n\t\t\t\t\t// Clear any pending transitions\n\t\t\t\t\tif (transitionTimeoutRef.current) {\n\t\t\t\t\t\tclearTimeout(transitionTimeoutRef.current);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add a delay when transitioning to fixed footer to smooth the transition\n\t\t\t\t\tif (hasScroll) {\n\t\t\t\t\t\ttransitionTimeoutRef.current = setTimeout(() => setShowFixedFooter(true), 200);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Delay hiding fixed footer to allow animation to complete and prevent flashing\n\t\t\t\t\t\ttransitionTimeoutRef.current = setTimeout(() => setShowFixedFooter(false), 200);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// Delay initial check to ensure layout is complete\n\t\tsetTimeout(checkOverflow, 100);\n\n\t\t// Check on resize\n\t\twindow.addEventListener('resize', checkOverflow);\n\n\t\t// Use ResizeObserver to detect container size changes\n\t\tconst resizeObserver = new ResizeObserver(() => {\n\t\t\tsetTimeout(checkOverflow, 50);\n\t\t});\n\t\tif (containerRef.current) {\n\t\t\tresizeObserver.observe(containerRef.current);\n\t\t}\n\t\tif (contentRef.current) {\n\t\t\tresizeObserver.observe(contentRef.current);\n\t\t}\n\n\t\t// Use MutationObserver to detect content changes\n\t\tconst mutationObserver = new MutationObserver(() => {\n\t\t\tsetTimeout(checkOverflow, 50);\n\t\t});\n\t\tif (contentRef.current) {\n\t\t\tmutationObserver.observe(contentRef.current, { childList: true, subtree: true, attributes: true });\n\t\t}\n\n\t\treturn () => {\n\t\t\twindow.removeEventListener('resize', checkOverflow);\n\t\t\tresizeObserver.disconnect();\n\t\t\tmutationObserver.disconnect();\n\t\t\t// Clear timeout on unmount\n\t\t\tif (transitionTimeoutRef.current) {\n\t\t\t\tclearTimeout(transitionTimeoutRef.current);\n\t\t\t}\n\t\t};\n\t}, [children, hasOverflow, hasMounted]);\n\n\t// Reusable button component\n\tconst MobileButtons = () => (\n\t\t<>\n\t\t\t<Button.Btn\n\t\t\t\tonClick={handleReset}\n\t\t\t\tvariant=\"outline\"\n\t\t\t\tsize=\"sm\"\n\t\t\t\tclassName={filterConfig?.classNames?.resetButton}\n\t\t\t>\n\t\t\t\tReset All\n\t\t\t</Button.Btn>\n\t\t\t{selectedFilters && Object.keys(selectedFilters).length > 0 && (\n\t\t\t\t<Button.Btn\n\t\t\t\t\tonClick={() => setMobileTab(\"listTab\")}\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\tclassName={twMerge(\n\t\t\t\t\t\t`${hasActiveFilters ? \"hc-opacity-0 hc-pointer-events-none\" : \"hc-opacity-100\"}`,\n\t\t\t\t\t\tfilterConfig?.classNames?.showJobsButton\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Button.Body>\n\t\t\t\t\t\t<Button.Icon icon=\"fluent:search-12-filled\" size=\"hc-size-3.5\" />\n\t\t\t\t\t\tShow {filteredListings.length} Jobs\n\t\t\t\t\t</Button.Body>\n\t\t\t\t</Button.Btn>\n\t\t\t)}\n\t\t</>\n\t);\n\n\treturn (\n\t\t<div\n\t\t\tref={containerRef}\n\t\t\tstyle={isDesktop ? style : undefined}\n\t\t\tclassName={twMerge(\n `/* Mobile layout */\n hc-relative hc-w-full hc-h-full hc-flex hc-flex-col\n\n /* Desktop layout */\n md:hc-relative md:hc-flex md:hc-flex-col md:hc-max-h-[100%]\n\n ${className ?? \"\"}`,\n filterConfig?.classNames?.filterContainer\n )}\n\t\t>\n\t\t\t{/* Content area with scroll */}\n\t\t\t<div\n\t\t\t\tref={contentRef}\n\t\t\t\tclassName={twMerge(\n\t\t\t\t\t`hc-w-full hc-flex-grow hc-max-h-full hc-overflow-auto ${hasOverflow ? 'hc-pb-16' : ''} md:hc-overflow-y-auto ${hasOverflow ? 'md:hc-pb-16' : 'md:hc-pb-0'}`,\n\t\t\t\t\tfilterConfig?.classNames?.filterContent\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t<div className=\"hc-px-4 md:hc-pt-4 hc-space-y-4\">\n\t\t\t\t\t{children}\n\n\t\t\t\t\t{/* Inline buttons when no overflow - both mobile and desktop */}\n\t\t\t\t\t{!hasOverflow && !showFixedFooter && (\n\t\t\t\t\t\t<div className={twMerge(\n\t\t\t\t\t\t\t\"hc-flex hc-items-center hc-justify-between hc-gap-2 hc-py-2 hc-border-t hc-border-gray-200 hc-animate-in hc-fade-in hc-duration-300\",\n\t\t\t\t\t\t\tfilterConfig?.classNames?.filterFooter\n\t\t\t\t\t\t)}>\n\t\t\t\t\t\t\t{/* Mobile buttons */}\n\t\t\t\t\t\t\t<div className=\"hc-flex hc-items-center hc-justify-between hc-gap-2 hc-w-full md:hc-hidden\">\n\t\t\t\t\t\t\t\t<MobileButtons />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t{/* Desktop button */}\n\t\t\t\t\t\t\t<div className=\"hc-hidden md:hc-flex\">\n\t\t\t\t\t\t\t\t<Button.Btn\n\t\t\t\t\t\t\t\t\tonClick={handleReset}\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\t\t\tclassName={filterConfig?.classNames?.resetButton}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\tReset All\n\t\t\t\t\t\t\t\t</Button.Btn>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t{/* Mobile Footer - fixed at bottom (only when overflow) */}\n\t\t\t{showFixedFooter && (\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"hc-w-full hc-absolute hc-bottom-0 hc-left-0 hc-right-0 hc-flex hc-items-center hc-justify-between hc-gap-2 hc-py-2 hc-px-4 hc-bg-gray-100 hc-border-t hc-border-gray-200 hc-z-50 md:hc-hidden hc-animate-in hc-fade-in hc-slide-in-from-bottom-2 hc-duration-200\"\n\t\t\t\t>\n\t\t\t\t\t<MobileButtons />\n\t\t\t\t</div>\n\t\t\t)}\n\n\t\t\t{/* Desktop Footer - fixed at bottom (only when overflow) */}\n\t\t\t{showFixedFooter && (\n\t\t\t\t<div className=\"hc-hidden md:hc-flex md:hc-justify-start hc-px-4 hc-py-4 hc-absolute hc-bottom-0 hc-left-0 hc-right-0 hc-bg-gray-100 hc-border-t hc-border-gray-200 hc-z-50 hc-animate-in hc-fade-in hc-slide-in-from-bottom-2 hc-duration-200\">\n\t\t\t\t\t<Button.Btn\n\t\t\t\t\t\tonClick={handleReset}\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tclassName={filterConfig?.classNames?.resetButton}\n\t\t\t\t\t>\n\t\t\t\t\t\tReset All\n\t\t\t\t\t</Button.Btn>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n\nexport default Filter;\n"],"names":["Filter","_ref","_filterConfig$classNa3","_filterConfig$classNa4","_filterConfig$classNa5","_filterConfig$classNa6","_filterConfig$classNa7","className","hasActiveFilters","filteredListings","selectedFilters","setMobileTab","handleReset","_ref$isDesktop","isDesktop","style","children","_useMapList","useMapList","filterConfig","contentRef","useRef","containerRef","_useState","useState","_useState2","_slicedToArray","hasOverflow","setHasOverflow","_useState3","_useState4","showFixedFooter","setShowFixedFooter","_useState5","_useState6","hasMounted","setHasMounted","transitionTimeoutRef","useEffect","window","checkOverflow","current","hasScroll","scrollHeight","clientHeight","clearTimeout","setTimeout","addEventListener","resizeObserver","ResizeObserver","observe","mutationObserver","MutationObserver","childList","subtree","attributes","removeEventListener","disconnect","MobileButtons","_filterConfig$classNa","_filterConfig$classNa2","React","createElement","Fragment","Button","Btn","onClick","variant","size","classNames","resetButton","Object","keys","length","twMerge","concat","showJobsButton","Body","Icon","icon","ref","undefined","filterContainer","filterContent","filterFooter"],"mappings":"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"}
|
|
@@ -10,14 +10,37 @@ const useMap = () => {
|
|
|
10
10
|
return context;
|
|
11
11
|
};
|
|
12
12
|
const MapProvider = ({ children, resetFilters, defaultZoomOverride, localStorageKey = '' }) => {
|
|
13
|
-
|
|
14
|
-
const [
|
|
15
|
-
const [
|
|
16
|
-
const [
|
|
13
|
+
// Initialize with defaults to avoid hydration mismatch - load from localStorage after mount
|
|
14
|
+
const [selectedListItem, setSelectedListItem] = useState(null);
|
|
15
|
+
const [location, setLocation] = useState(null);
|
|
16
|
+
const [center, setCenter] = useState({ lat: 39.8283, lng: -98.5795 });
|
|
17
|
+
const [zoom, setZoom] = useState(9);
|
|
17
18
|
const [selectedPlaces, setSelectedPlaces] = useState([]);
|
|
18
19
|
const [mapInteracted, setMapInteracted] = useState(false);
|
|
19
|
-
const [firstLoadListItem] = useState(
|
|
20
|
+
const [firstLoadListItem, setFirstLoadListItem] = useState({ id: "defaultId" });
|
|
20
21
|
const userSetZoom = useRef(true);
|
|
22
|
+
const [hasMounted, setHasMounted] = useState(false);
|
|
23
|
+
// Load from localStorage after mount to avoid hydration mismatch
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (typeof window !== 'undefined') {
|
|
26
|
+
const storedItem = getStorageObject(localStorageKey + 'selectedListItem');
|
|
27
|
+
const storedLocation = getStorageObject(localStorageKey + 'location');
|
|
28
|
+
const storedCenter = getStorageObject(localStorageKey + "center", { lat: 39.8283, lng: -98.5795 });
|
|
29
|
+
const storedZoom = getStorageObject(localStorageKey + "zoom", 9);
|
|
30
|
+
const storedFirstLoad = getStorageObject(localStorageKey + 'selectedListItem', { id: "defaultId" });
|
|
31
|
+
if (storedItem)
|
|
32
|
+
setSelectedListItem(storedItem);
|
|
33
|
+
if (storedLocation)
|
|
34
|
+
setLocation(storedLocation);
|
|
35
|
+
if (storedCenter)
|
|
36
|
+
setCenter(storedCenter);
|
|
37
|
+
if (storedZoom)
|
|
38
|
+
setZoom(storedZoom);
|
|
39
|
+
if (storedFirstLoad)
|
|
40
|
+
setFirstLoadListItem(storedFirstLoad);
|
|
41
|
+
setHasMounted(true);
|
|
42
|
+
}
|
|
43
|
+
}, [localStorageKey]);
|
|
21
44
|
useEffect(() => {
|
|
22
45
|
setStorageObject(localStorageKey + "selectedListItem", selectedListItem);
|
|
23
46
|
}, [selectedListItem, localStorageKey]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapContext.js","sources":["../../src/contexts/mapContext.tsx"],"sourcesContent":["import React, { createContext, useState, useContext, useEffect, useRef, ReactNode } from 'react';\nimport { getStorageObject, setStorageObject } from '~/util/localStorageUtil';\nimport { Listing } from '~/types/Listings';\nimport { LatLng } from '~/types/LatLng';\ninterface IMapContext {\n selectedListItem: Listing | null;\n setSelectedListItem: (item: Listing | null) => void;\n location: any | null;\n setLocation: (location: LatLng | null) => void;\n center: LatLng;\n setCenter: (center: LatLng) => void;\n zoom: number;\n setZoom: (zoom: number) => void;\n selectedPlaces: string[];\n setSelectedPlaces: (places: string[]) => void;\n mapInteracted: boolean;\n setMapInteracted: (interacted: boolean) => void;\n userSetZoom: React.MutableRefObject<boolean>;\n firstLoadListItem: any;\n selectItem: (item: Listing, itemLocation: LatLng | null, zoom: number, center: LatLng) => void;\n filterReset: () => void;\n selectLocationEntity: (location: LatLng) => void;\n\tdefaultZoomOverride?: number | null;\n}\n\nconst MapContext = createContext<IMapContext | undefined>(undefined);\n\nexport const useMap = () => {\n\tconst context = useContext(MapContext);\n\tif (!context) {\n\t\tthrow new Error(\"useMap must be used within a MapProvider\");\n\t}\n\treturn context;\n};\n\ninterface MapProviderProps {\n children: ReactNode;\n resetFilters: boolean;\n\tdefaultZoomOverride?: number | null;\n\tlocalStorageKey?: string;\n}\n\nexport const MapProvider: React.FC<MapProviderProps> = ({ children, resetFilters, defaultZoomOverride, localStorageKey = '' }) => {\n\tconst [selectedListItem, setSelectedListItem] = useState<Listing | null>(
|
|
1
|
+
{"version":3,"file":"mapContext.js","sources":["../../src/contexts/mapContext.tsx"],"sourcesContent":["import React, { createContext, useState, useContext, useEffect, useRef, ReactNode } from 'react';\nimport { getStorageObject, setStorageObject } from '~/util/localStorageUtil';\nimport { Listing } from '~/types/Listings';\nimport { LatLng } from '~/types/LatLng';\ninterface IMapContext {\n selectedListItem: Listing | null;\n setSelectedListItem: (item: Listing | null) => void;\n location: any | null;\n setLocation: (location: LatLng | null) => void;\n center: LatLng;\n setCenter: (center: LatLng) => void;\n zoom: number;\n setZoom: (zoom: number) => void;\n selectedPlaces: string[];\n setSelectedPlaces: (places: string[]) => void;\n mapInteracted: boolean;\n setMapInteracted: (interacted: boolean) => void;\n userSetZoom: React.MutableRefObject<boolean>;\n firstLoadListItem: any;\n selectItem: (item: Listing, itemLocation: LatLng | null, zoom: number, center: LatLng) => void;\n filterReset: () => void;\n selectLocationEntity: (location: LatLng) => void;\n\tdefaultZoomOverride?: number | null;\n}\n\nconst MapContext = createContext<IMapContext | undefined>(undefined);\n\nexport const useMap = () => {\n\tconst context = useContext(MapContext);\n\tif (!context) {\n\t\tthrow new Error(\"useMap must be used within a MapProvider\");\n\t}\n\treturn context;\n};\n\ninterface MapProviderProps {\n children: ReactNode;\n resetFilters: boolean;\n\tdefaultZoomOverride?: number | null;\n\tlocalStorageKey?: string;\n}\n\nexport const MapProvider: React.FC<MapProviderProps> = ({ children, resetFilters, defaultZoomOverride, localStorageKey = '' }) => {\n\t// Initialize with defaults to avoid hydration mismatch - load from localStorage after mount\n\tconst [selectedListItem, setSelectedListItem] = useState<Listing | null>(null);\n\tconst [location, setLocation] = useState<any>(null);\n\tconst [center, setCenter] = useState<LatLng>({ lat: 39.8283, lng: -98.5795 });\n\tconst [zoom, setZoom] = useState<number>(9);\n\tconst [selectedPlaces, setSelectedPlaces] = useState<string[]>([]);\n\tconst [mapInteracted, setMapInteracted] = useState<boolean>(false);\n\tconst [firstLoadListItem, setFirstLoadListItem] = useState<any>({ id: \"defaultId\" });\n\tconst userSetZoom = useRef<boolean>(true);\n\tconst [hasMounted, setHasMounted] = useState(false);\n\n\t// Load from localStorage after mount to avoid hydration mismatch\n\tuseEffect(() => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tconst storedItem = getStorageObject(localStorageKey + 'selectedListItem');\n\t\t\tconst storedLocation = getStorageObject(localStorageKey + 'location');\n\t\t\tconst storedCenter = getStorageObject(localStorageKey + \"center\", { lat: 39.8283, lng: -98.5795 });\n\t\t\tconst storedZoom = getStorageObject(localStorageKey + \"zoom\", 9);\n\t\t\tconst storedFirstLoad = getStorageObject(localStorageKey + 'selectedListItem', { id: \"defaultId\" });\n\t\t\t\n\t\t\tif (storedItem) setSelectedListItem(storedItem);\n\t\t\tif (storedLocation) setLocation(storedLocation);\n\t\t\tif (storedCenter) setCenter(storedCenter);\n\t\t\tif (storedZoom) setZoom(storedZoom);\n\t\t\tif (storedFirstLoad) setFirstLoadListItem(storedFirstLoad);\n\t\t\tsetHasMounted(true);\n\t\t}\n\t}, [localStorageKey]);\n\n\tuseEffect(() => {\n\t\tsetStorageObject(localStorageKey + \"selectedListItem\", selectedListItem);\n\t}, [selectedListItem, localStorageKey]);\n\n\tuseEffect(() => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tlocalStorage.setItem(localStorageKey + \"zoom\", zoom.toString());\n\t\t}\n\t}, [zoom, localStorageKey]);\n\n\tuseEffect(() => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tif (location == null) {\n\t\t\t\tlocalStorage.removeItem(localStorageKey + \"location\");\n\t\t\t} else {\n\t\t\t\tsetStorageObject(localStorageKey + \"location\", location);\n\t\t\t}\n\t\t}\n\t}, [location, localStorageKey]);\n\n\tuseEffect(() => {\n\t\tsetStorageObject(localStorageKey + \"center\", center);\n\t}, [center, localStorageKey]);\n\n\tconst selectItem = (item: Listing, itemLocation: LatLng | null, zoom: number, center: LatLng) => {\n\t\tsetSelectedListItem(item);\n\t\tif (mapInteracted === false && itemLocation != null) {\n\t\t\tsetLocation(itemLocation);\n\t\t}\n\t\tif (mapInteracted === false || itemLocation != null) {\n\t\t\tsetLocation(itemLocation);\n\t\t\tsetCenter(center);\n\t\t}\n\t\tif (mapInteracted === false) {\n\t\t\tsetZoom(zoom);\n\t\t}\n\t};\n\n\tconst filterReset = () => {\n\t\tsetSelectedPlaces([]);\n\t\tsetSelectedListItem(null);\n\t\tsetLocation(null);\n\t\tsetZoom(8);\n\t\tsetMapInteracted(false);\n\t};\n\n\tuseEffect(() => {\n\t\tif (resetFilters === true) {\n\t\t\tfilterReset();\n\t\t}\n\t}, [resetFilters]);\n\n\tconst selectLocationEntity = (location: LatLng) => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tlocalStorage.removeItem(localStorageKey + \"selectedListItem\");\n\t\t}\n\t\tsetTimeout(() => setLocation(location), 200);\n\t\tsetSelectedListItem(null);\n\t};\n\n\treturn (\n\t\t<MapContext.Provider\n\t\t\tvalue={{\n\t\t\t\tselectedListItem,\n\t\t\t\tsetSelectedListItem,\n\t\t\t\tlocation,\n\t\t\t\tcenter,\n\t\t\t\tsetCenter,\n\t\t\t\tzoom,\n\t\t\t\tsetZoom,\n\t\t\t\tselectItem,\n\t\t\t\tsetSelectedPlaces,\n\t\t\t\tselectedPlaces,\n\t\t\t\tselectLocationEntity,\n\t\t\t\tsetLocation,\n\t\t\t\tsetMapInteracted,\n\t\t\t\tmapInteracted,\n\t\t\t\tuserSetZoom,\n\t\t\t\tfirstLoadListItem,\n\t\t\t\tfilterReset,\n\t\t\t\tdefaultZoomOverride\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</MapContext.Provider>\n\t);\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { createContext, useContext, useState,
|
|
1
|
+
import React, { createContext, useContext, useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { applyFilters, generateFilterOptions, filterListingsByLocation } from '../util/filterUtil.js';
|
|
3
3
|
import { getStorageObject, setStorageObject } from '../util/localStorageUtil.js';
|
|
4
4
|
import { filtersFromURL, updateURLWithFilters } from '../util/urlFilterUtil.js';
|
|
@@ -72,13 +72,32 @@ const MapListProvider = ({ children, siteConfig, googleMapsApiKey, resetFilters,
|
|
|
72
72
|
const [allListings, setAllListings] = useState([]);
|
|
73
73
|
const [filteredListings, setFilteredListings] = useState([]);
|
|
74
74
|
const [loading, setLoading] = useState(false);
|
|
75
|
-
const [mapItems, setMapItems] = useState(
|
|
76
|
-
const [query, setQuery] = useState(
|
|
77
|
-
const [sortSetting, setSortSetting] = useState(
|
|
75
|
+
const [mapItems, setMapItems] = useState([]);
|
|
76
|
+
const [query, setQuery] = useState(null);
|
|
77
|
+
const [sortSetting, setSortSetting] = useState({ field: 'position', type: 'asc' });
|
|
78
78
|
const [listingEntities, setListingEntities] = useState({});
|
|
79
79
|
const [firstLoad, setFirstLoad] = useState(true);
|
|
80
|
-
const [commuteLocation, setCommuteLocation] = useState(
|
|
81
|
-
const [selectedFilters, setSelectedFilters] = useState(
|
|
80
|
+
const [commuteLocation, setCommuteLocation] = useState(null);
|
|
81
|
+
const [selectedFilters, setSelectedFilters] = useState({});
|
|
82
|
+
const [hasMounted, setHasMounted] = useState(false);
|
|
83
|
+
// Load from localStorage/URL after mount to avoid hydration mismatch
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (typeof window !== 'undefined') {
|
|
86
|
+
const storedMapItems = getStorageObject(localStorageKey + 'mapItems', []) || [];
|
|
87
|
+
const storedSortSetting = getStorageObject(localStorageKey + 'sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' };
|
|
88
|
+
const storedCommuteLocation = getStorageObject(localStorageKey + 'commuteLocation');
|
|
89
|
+
setMapItems(storedMapItems);
|
|
90
|
+
setSortSetting(storedSortSetting);
|
|
91
|
+
if (storedCommuteLocation)
|
|
92
|
+
setCommuteLocation(storedCommuteLocation);
|
|
93
|
+
// Load filters and query
|
|
94
|
+
if (!resetFilters) {
|
|
95
|
+
setSelectedFilters(firstLoadFilters());
|
|
96
|
+
setQuery(firstLoadQuery());
|
|
97
|
+
}
|
|
98
|
+
setHasMounted(true);
|
|
99
|
+
}
|
|
100
|
+
}, [localStorageKey]);
|
|
82
101
|
const [filterOptions, setFilterOptions] = useState();
|
|
83
102
|
const [recruiters, setRecruiters] = useState({});
|
|
84
103
|
const [filterDialogIsOpen, setFilterDialogIsOpen] = useState(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapListContext.js","sources":["../../src/contexts/mapListContext.tsx"],"sourcesContent":["import React, { createContext, useState, useEffect, useContext, useRef, ReactNode } from 'react';\n\nimport { generateFilterOptions, applyFilters, filterListingsByLocation } from '~/util/filterUtil';\nimport { getStorageObject, setStorageObject } from '~/util/localStorageUtil';\nimport { updateURLWithFilters, filtersFromURL } from '~/util/urlFilterUtil';\n\nimport { Listing } from '~/types/Listings';\nimport { ListingEntity } from '~/types/ListingEntity';\nimport { Recruiter } from '~/types/Recruiter';\nimport { MapConfig, MapConfig as SiteConfig } from '~/types/config/MapConfig';\nimport { get } from 'http';\n\ninterface MapListContextProps {\n loading: boolean;\n allListings: Listing[];\n filteredListings: Listing[];\n mapItems: any;\n query: string | null;\n setNewFilteredListings: (filteredListings: Listing[]) => void;\n setQuery: (query: string | null) => void;\n listingEntities: Record<number, ListingEntity> | null;\n selectedFilters: Record<string, any>;\n setSelectedFilters: (filters: Record<string, any>) => void;\n filterOptions: any;\n recruiters: Record<number, Recruiter>;\n handleFilterListingsByLocation: (selectedLocation: any) => void;\n filterDialogIsOpen: boolean;\n setFilterDialogIsOpen: (isOpen: boolean) => void;\n setMobileTab: (tab: string) => void;\n mobileTab: string;\n siteConfig: SiteConfig;\n googleMapsApiKey?: string;\n favorites: number[];\n resetEntityFilter: () => void;\n handleSettingFavorites: (favorites: number[] | null) => void;\n setFilterByFavorites: (filter: boolean) => void;\n filterByFavorites: boolean;\n commuteLocation: any | null;\n setCommuteLocation: (location: any | null) => void;\n navigateToDetails: (id: number) => void;\n navigateToEasyApply: (id: number) => void;\n Link: React.ComponentType<any>;\n linkFormat: string;\n easyApplyUrl: string;\n easyApplyText: string;\n\tisIframe: boolean;\n sortSetting: { field: string; type: string };\n setSortSetting: (setting: { field: string; type: string }) => void;\n trackEvent: (event: string) => void;\n defaultFilters?: Record<string, any>;\n hiddenFilters?: string[];\n containerStyle?: any;\n ExpandListComponent?: React.ComponentType<{ listing: any }> | ((listing: any) => JSX.Element) | null;\n noEntities?: boolean;\n filterConfig?: {\n hideZeroResults?: boolean;\n dynamicCounts?: boolean;\n showFavorites?: boolean;\n collapsedByDefault?: boolean;\n sortAlphabetically?: boolean;\n classNames?: {\n filterContainer?: string;\n filterContent?: string;\n filterAccordion?: string;\n filterAccordionHeader?: string;\n filterAccordionContent?: string;\n filterItem?: string;\n filterItemLabel?: string;\n filterItemCheckbox?: string;\n filterItemCount?: string;\n searchInput?: string;\n resetButton?: string;\n showJobsButton?: string;\n filterFooter?: string;\n };\n };\n}\n\nconst MapListContext = createContext<MapListContextProps | undefined>(undefined);\n\nexport const useMapList = () => {\n\tconst context = useContext(MapListContext);\n\tif (!context) {\n\t\tthrow new Error('useMapList must be used within a MapListProvider');\n\t}\n\treturn context;\n};\n\nconst getQuery = (localStorageKey: string = ''): string | null => {\n\tlet query: string | null = null;\n\tif (typeof window !== 'undefined') {\n\t\tquery = localStorage.getItem(localStorageKey + 'query');\n\t}\n\treturn query;\n};\n\ninterface MapListProviderProps {\n children: ReactNode;\n siteConfig: MapConfig;\n googleMapsApiKey?: string;\n resetFilters: boolean;\n navigateToDetails: (id: number) => void;\n navigateToEasyApply: (id: number) => void;\n Link: React.ComponentType<any>;\n linkFormat: string;\n easyApplyUrl: string;\n easyApplyText: string;\n\tisIframe: boolean;\n trackEvent: (event: string) => void;\n listings?: Listing[];\n\tentities?: ListingEntity[];\n setFiltersUrl?:boolean;\n hiddenFilters?: string[];\n handleUrlUpdate: (searchParams: string) => void;\n defaultFilters?: Record<string, any>;\n containerStyle?: any;\n\tlocalStorageKey: string;\n\tgetListingEntitiesCallback?: (origin?: string) => Promise<any>;\n ExpandListComponent?: React.ComponentType<{ listing: Listing }> | ((listing: Listing) => JSX.Element) | null;\n hideMap?: boolean;\n hideFilters?: boolean;\n noEntities?: boolean;\n filterConfig?: {\n hideZeroResults?: boolean;\n dynamicCounts?: boolean;\n showFavorites?: boolean;\n collapsedByDefault?: boolean;\n sortAlphabetically?: boolean;\n classNames?: {\n filterContainer?: string;\n filterContent?: string;\n filterAccordion?: string;\n filterAccordionHeader?: string;\n filterAccordionContent?: string;\n filterItem?: string;\n filterItemLabel?: string;\n filterItemCheckbox?: string;\n filterItemCount?: string;\n searchInput?: string;\n resetButton?: string;\n showJobsButton?: string;\n filterFooter?: string;\n };\n };\n}\n\nexport const MapListProvider: React.FC<MapListProviderProps> = ({\n\tchildren,\n\tsiteConfig,\n\tgoogleMapsApiKey,\n\tresetFilters,\n\tnavigateToDetails,\n\tnavigateToEasyApply,\n\tLink,\n\tlinkFormat,\n\teasyApplyUrl,\n\teasyApplyText,\n\tisIframe,\n\ttrackEvent,\n\tlistings = [],\n\tentities = [],\n\tsetFiltersUrl,\n\thiddenFilters,\n\thandleUrlUpdate,\n\tdefaultFilters,\n\tcontainerStyle,\n\tExpandListComponent,\n\tgetListingEntitiesCallback,\n\tlocalStorageKey,\n\thideMap = false,\n\thideFilters = false,\n\tnoEntities = false,\n\tfilterConfig = {\n\t\thideZeroResults: false,\n\t\tdynamicCounts: true,\n\t\tshowFavorites: true,\n\t\tcollapsedByDefault: false,\n\t\tsortAlphabetically: false,\n\t\tclassNames: {\n\t\t\tfilterContainer: '',\n\t\t\tfilterContent: '',\n\t\t\tfilterAccordion: '',\n\t\t\tfilterAccordionHeader: '',\n\t\t\tfilterAccordionContent: '',\n\t\t\tfilterItem: '',\n\t\t\tfilterItemLabel: '',\n\t\t\tfilterItemCheckbox: '',\n\t\t\tfilterItemCount: '',\n\t\t\tsearchInput: '',\n\t\t\tresetButton: '',\n\t\t\tshowJobsButton: '',\n\t\t\tfilterFooter: ''\n\t\t}\n\t}\n}) => {\n\tconst firstLoadFilters = () =>{\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn getStorageObject(localStorageKey + 'selectedFilters', {}) || {};\n\t\t}\n\t\tlet urlData = filtersFromURL(window.location);\n\t\tlet urlFilters = urlData?.filters;\n\n\t\t// If ls-ignore=true is in URL, don't load from localStorage\n\t\tif (urlData?.lsIgnore) {\n\t\t\treturn urlFilters || {};\n\t\t}\n\n\t\treturn (setFiltersUrl === true && urlFilters && Object.keys(urlFilters).length > 0) ? urlFilters : getStorageObject(localStorageKey + 'selectedFilters', {}) || {}\n\t}\n\n\tconst firstLoadQuery = (): string | null => {\n\t\tif (resetFilters) return null;\n\t\tif (typeof window === 'undefined') return getQuery(localStorageKey);\n\t\t// Check URL first\n\t\tconst urlData = filtersFromURL(window.location);\n\n\t\t// If ls-ignore=true is in URL, don't load from localStorage\n\t\tif (urlData?.lsIgnore) {\n\t\t\treturn urlData?.query || null;\n\t\t}\n\n\t\tif (setFiltersUrl === true && urlData?.query) {\n\t\t\treturn urlData.query;\n\t\t}\n\t\t// Fall back to localStorage\n\t\treturn getQuery(localStorageKey);\n\t}\n\n\tconst [allListings, setAllListings] = useState<Listing[]>([]);\n\tconst [filteredListings, setFilteredListings] = useState<Listing[]>([]);\n\tconst [loading, setLoading] = useState<boolean>(false);\n\tconst [mapItems, setMapItems] = useState<any>(getStorageObject(localStorageKey + 'mapItems', []) || []);\n\tconst [query, setQuery] = useState<string | null>(() => firstLoadQuery());\n\tconst [sortSetting, setSortSetting] = useState<{ field: string; type: string }>(getStorageObject(localStorageKey + 'sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' });\n\tconst [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>({});\n\tconst [firstLoad, setFirstLoad] = useState<boolean>(true);\n\tconst [commuteLocation, setCommuteLocation] = useState<any | null>(getStorageObject(localStorageKey + 'commuteLocation'));\n\tconst [selectedFilters, setSelectedFilters] = useState<Record<string, any>>(() => resetFilters ? {} : firstLoadFilters());\n\tconst [filterOptions, setFilterOptions] = useState<any>();\n\tconst [recruiters, setRecruiters] = useState<Record<number, Recruiter>>({});\n\tconst [filterDialogIsOpen, setFilterDialogIsOpen] = useState<boolean>(false);\n\tconst [mobileTab, setMobileTab] = useState<string>(\"listTab\");\n\tconst [favorites, setFavorites] = useState<number[]>([]);\n\tconst [filterByFavorites, setFilterByFavorites] = useState<boolean>(false);\n\tconst entitiesInitialized = useRef<boolean>(false);\n\n\tconst setNewFilteredListings = (filteredListings: Listing[]) => {\n\t\tsetFilteredListings(filteredListings);\n\t};\n\n\tuseEffect(() => {\n\t\tif (!sortSetting) return;\n\t\tif (typeof window !== 'undefined') {\n\t\t\tlocalStorage.setItem(localStorageKey + 'sortSetting', JSON.stringify(sortSetting));\n\t\t}\n\t}, [sortSetting, localStorageKey]);\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return;\n\t\tconst loadedFavorites = JSON.parse(localStorage.getItem(localStorageKey + 'favorites') || '[]');\n\t\tsetFavorites(loadedFavorites);\n\t}, [localStorageKey]);\n\n\tuseEffect(() => {\n\t\tsetStorageObject(localStorageKey + \"commuteLocation\", commuteLocation);\n\t}, [commuteLocation, localStorageKey]);\n\n\n\tuseEffect(() => {\n\t\tif (!commuteLocation || noEntities) return;\n\n\t\tasync function fetchEntities() {\n\t\t\ttry {\n\t\t\t\t// Only fetch if callback is provided\n\t\t\t\tif (!getListingEntitiesCallback) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst fetchedEntities = await getListingEntitiesCallback(`${commuteLocation.lat}, ${commuteLocation.lng}`);\n\t\t\t\tsetListingEntities(fetchedEntities);\n\t\t\t\t// Update travelTime on listings\n\t\t\t\tconst newFilteredListings: Listing[] = [...filteredListings];\n\t\t\t\tfor (let i = 0; i < allListings.length; i++) {\n\t\t\t\t\tconst listing = newFilteredListings[i];\n\t\t\t\t\tif (\n\t\t\t\t\t\tlisting &&\n\t\t\t\t\t\tlisting.fields &&\n\t\t\t\t\t\tlisting.fields.entityKey &&\n\t\t\t\t\t\tlisting.fields.entityKey !== ''\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst entityKey = listing.fields.entityKey;\n\t\t\t\t\t\t// Try exact match first, then lowercase match for case-insensitive lookup\n\t\t\t\t\t\tconst travelTime = (fetchedEntities[entityKey] || fetchedEntities[entityKey.toLowerCase()])?.travelTime;\n\t\t\t\t\t\tif (travelTime !== undefined && listing.fields) {\n\t\t\t\t\t\t\tlisting.fields.travelTime = travelTime;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to fetch listing entities:\", error);\n\t\t\t}\n\t\t}\n\n\t\tfetchEntities();\n\t}, [commuteLocation, noEntities]);\n\n\t// Set listingEntities from passed-in entities (only once on initial load)\n\t// Entities should be an object: { \"rochester, mn\": {...}, \"albuquerque, nm\": {...} }\n\t// Note: Commute location changes will fetch updated entities with travel times via separate useEffect\n\tuseEffect(() => {\n\t\tif (!entities || entitiesInitialized.current) return;\n\t\t\n\t\tentitiesInitialized.current = true;\n\t\t\n\t\t// Handle both object (production format) and array (for backwards compatibility)\n\t\tif (Array.isArray(entities)) {\n\t\t\t// Convert array to object\n\t\t\tconst entitiesObj: Record<string, any> = {};\n\t\t\tentities.forEach((entity: any) => {\n\t\t\t\tif (entity.entityKey) {\n\t\t\t\t\tentitiesObj[entity.entityKey.toLowerCase()] = entity;\n\t\t\t\t}\n\t\t\t});\n\t\t\tconsole.log('Set listingEntities from entities array:', entitiesObj);\n\t\t\tsetListingEntities(entitiesObj);\n\t\t} else if (typeof entities === 'object') {\n\t\t\t// Normalize keys to lowercase for production format\n\t\t\tconst normalizedEntities: Record<string, any> = {};\n\t\t\tObject.keys(entities).forEach(key => {\n\t\t\t\tnormalizedEntities[key.toLowerCase()] = entities[key];\n\t\t\t});\n\t\t\tconsole.log('Set listingEntities from entities object:', normalizedEntities);\n\t\t\tsetListingEntities(normalizedEntities);\n\t\t}\n\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, []); // Empty deps - only run once on mount, entities are static data\n\n\t// Set listings from passed-in data\n\tuseEffect(() => {\n\t\tif (!listings || listings.length === 0) {\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tsetLoading(true);\n\n\t\ttry {\n\t\t\t// Apply default filters if provided\n\t\t\tlet processedListings = listings;\n\t\t\tif (defaultFilters) {\n\t\t\t\tprocessedListings = listings.filter(listing => {\n\t\t\t\t\tif (!listing.fields) return false;\n\n\t\t\t\t\treturn Object.keys(defaultFilters).every(filterKey => {\n\t\t\t\t\t\tconst filterValues = defaultFilters[filterKey as keyof typeof defaultFilters];\n\t\t\t\t\t\tconst listingValue = listing.fields ? listing.fields[filterKey as keyof typeof listing.fields] : null;\n\t\t\t\t\t\treturn filterValues.includes(listingValue);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsetAllListings(processedListings);\n\t\t\tconsole.log('Set allListings to', processedListings.length, 'items');\n\t\t\t\n\t\t\t// Map items will be set when entities are processed\n\t\t\t// For now, just set empty object - will be populated when entities arrive\n\t\t\tsetMapItems({});\n\t\t} catch (error) {\n\t\t\tconsole.error('Error processing listings:', error);\n\t\t}\n\t\t\n\t\tsetLoading(false);\n\t}, [listings]);\n\n\tuseEffect(() => {\n\t\tconst processListings = async () => {\n\t\t\t// Don't process if allListings hasn't been loaded yet\n\t\t\tif (allListings.length === 0) {\n\t\t\t\tconsole.log('processListings: Skipping - allListings is empty');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet filteredListings: Listing[];\n\t\t\tlet tempSelectedFilters = selectedFilters;\n\t\t\tlet tempQuery = query;\n\n\t\t\tconsole.log('processListings: Running with query:', tempQuery, 'and', allListings.length, 'listings');\n\n\t\t\tconst { mapItems, filteredListings: tempFilteredListings } = await applyFilters(\n\t\t\t\tallListings,\n\t\t\t\ttempSelectedFilters,\n\t\t\t\ttempQuery,\n\t\t\t\tlistingEntities,\n\t\t\t\tfavorites,\n\t\t\t\tsiteConfig\n\t\t\t);\n\t\t\tfilteredListings = tempFilteredListings;\n\n\t\t\tif (filterByFavorites) {\n\t\t\t\tfilteredListings = filteredListings.filter((x: Listing) => favorites.includes(x.id));\n\t\t\t}\n\n\t\t\t// Batch state updates together\n\t\t\tsetNewFilteredListings(filteredListings);\n\t\t\tsetMapItems(mapItems);\n\n\t\t\tif (firstLoad && tempSelectedFilters) {\n\t\t\t\t// Update URL with filters if needed\n\t\t\t} else if (Object.keys(tempSelectedFilters).length === 0 && !firstLoad) {\n\t\t\t\tlocalStorage.removeItem(localStorageKey + 'selectedFilters');\n\t\t\t} else if (!firstLoad) {\n\t\t\t\tsetStorageObject(localStorageKey + 'selectedFilters', tempSelectedFilters);\n\t\t\t}\n\t\t\tif(setFiltersUrl === true && typeof window !== 'undefined')\n\t\t\t{\n\t\t\t\tupdateURLWithFilters(tempSelectedFilters, window.location, tempQuery, handleUrlUpdate);\n\t\t\t}\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\ttempQuery != null ? localStorage.setItem(localStorageKey + 'query', tempQuery) : localStorage.removeItem(localStorageKey + 'query');\n\t\t\t}\n\n\t\t\tif (tempSelectedFilters) {\n\t\t\t\tconst keys = Object.keys(tempSelectedFilters);\n\t\t\t\tconst lastKey = keys[keys.length - 1];\n\n\t\t\t\t// Ensure all filterConfig properties have values\n\t\t\t\tconst normalizedFilterConfig = {\n\t\t\t\t\thideZeroResults: filterConfig?.hideZeroResults ?? false,\n\t\t\t\t\tdynamicCounts: filterConfig?.dynamicCounts ?? true,\n\t\t\t\t\tshowFavorites: filterConfig?.showFavorites ?? true,\n\t\t\t\t\tcollapsedByDefault: filterConfig?.collapsedByDefault ?? false,\n\t\t\t\t\tsortAlphabetically: filterConfig?.sortAlphabetically ?? false,\n\t\t\t\t\tclassNames: {\n\t\t\t\t\t\tfilterContainer: filterConfig?.classNames?.filterContainer ?? '',\n\t\t\t\t\t\tfilterContent: filterConfig?.classNames?.filterContent ?? '',\n\t\t\t\t\t\tfilterAccordion: filterConfig?.classNames?.filterAccordion ?? '',\n\t\t\t\t\t\tfilterAccordionHeader: filterConfig?.classNames?.filterAccordionHeader ?? '',\n\t\t\t\t\t\tfilterAccordionContent: filterConfig?.classNames?.filterAccordionContent ?? '',\n\t\t\t\t\t\tfilterItem: filterConfig?.classNames?.filterItem ?? '',\n\t\t\t\t\t\tfilterItemLabel: filterConfig?.classNames?.filterItemLabel ?? '',\n\t\t\t\t\t\tfilterItemCheckbox: filterConfig?.classNames?.filterItemCheckbox ?? '',\n\t\t\t\t\t\tfilterItemCount: filterConfig?.classNames?.filterItemCount ?? '',\n\t\t\t\t\t\tsearchInput: filterConfig?.classNames?.searchInput ?? '',\n\t\t\t\t\t\tresetButton: filterConfig?.classNames?.resetButton ?? '',\n\t\t\t\t\t\tshowJobsButton: filterConfig?.classNames?.showJobsButton ?? '',\n\t\t\t\t\t\tfilterFooter: filterConfig?.classNames?.filterFooter ?? ''\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst options = generateFilterOptions(\n\t\t\t\t\tfilteredListings,\n\t\t\t\t\tallListings,\n\t\t\t\t\tsiteConfig,\n\t\t\t\t\tfilterOptions,\n\t\t\t\t\tlastKey,\n\t\t\t\t\tfavorites,\n\t\t\t\t\ttempSelectedFilters,\n\t\t\t\t\tnormalizedFilterConfig\n\t\t\t\t);\n\t\t\t\tif (options) {\n\t\t\t\t\tsetFilterOptions(options);\n\t\t\t\t\tif (firstLoad) setFirstLoad(false);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tprocessListings();\n\t}, [selectedFilters, query, filterByFavorites, favorites, allListings]);\n\n\tconst handleFilterListingsByLocation = (selectedLocation: any) => {\n\t\tconst { filteredListings } = filterListingsByLocation(\n\t\t\tallListings,\n\t\t\tselectedLocation,\n\t\t\tlistingEntities\n\t\t);\n\t\tsetNewFilteredListings(filteredListings);\n\t};\n\n\tconst resetEntityFilter = () => {\n\t\tlet newFilters = {...selectedFilters};\n\t\tdelete newFilters.entityId;\n\t\tsetSelectedFilters(newFilters);\n\t}\n\n\tconst handleSettingFavorites = (newFavorites: number[] | null) => {\n\t\tif (typeof window === 'undefined') return;\n\t\tif (newFavorites == null) {\n\t\t\tlocalStorage.removeItem(localStorageKey + 'favorites');\n\t\t} else {\n\t\t\tsetFavorites(newFavorites);\n\t\t\tlocalStorage.setItem(localStorageKey + 'favorites', JSON.stringify(newFavorites));\n\t\t}\n\t};\n\n\treturn (\n\t\t<MapListContext.Provider value={{\n\t\t\tloading,\n\t\t\tallListings,\n\t\t\tfilteredListings,\n\t\t\tmapItems,\n\t\t\tquery,\n\t\t\tsetNewFilteredListings,\n\t\t\tsetQuery,\n\t\t\tlistingEntities,\n\t\t\tselectedFilters,\n\t\t\tsetSelectedFilters,\n\t\t\tfilterOptions,\n\t\t\trecruiters,\n\t\t\thandleFilterListingsByLocation,\n\t\t\tfilterDialogIsOpen,\n\t\t\tsetFilterDialogIsOpen,\n\t\t\tsetMobileTab,\n\t\t\tmobileTab,\n\t\t\tsiteConfig,\n\t\t\tgoogleMapsApiKey,\n\t\t\tfavorites,\n\t\t\thandleSettingFavorites,\n\t\t\tresetEntityFilter,\n\t\t\tsetFilterByFavorites,\n\t\t\tfilterByFavorites,\n\t\t\tcommuteLocation,\n\t\t\tsetCommuteLocation,\n\t\t\tnavigateToDetails,\n\t\t\tnavigateToEasyApply,\n\t\t\tLink,\n\t\t\tlinkFormat,\n\t\t\teasyApplyUrl,\n\t\t\teasyApplyText,\n\t\t\tisIframe,\n\t\t\tsortSetting,\n\t\t\tsetSortSetting,\n\t\t\ttrackEvent,\n\t\t\tdefaultFilters,\n\t\t\thiddenFilters,\n\t\t\tcontainerStyle,\n\t\t\tExpandListComponent,\n\t\t\tnoEntities,\n\t\t\tfilterConfig\n\t\t}}>\n\t\t\t{children}\n\t\t</MapListContext.Provider>\n\t);\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mapListContext.js","sources":["../../src/contexts/mapListContext.tsx"],"sourcesContent":["import React, { createContext, useState, useEffect, useContext, useRef, ReactNode } from 'react';\n\nimport { generateFilterOptions, applyFilters, filterListingsByLocation } from '~/util/filterUtil';\nimport { getStorageObject, setStorageObject } from '~/util/localStorageUtil';\nimport { updateURLWithFilters, filtersFromURL } from '~/util/urlFilterUtil';\n\nimport { Listing } from '~/types/Listings';\nimport { ListingEntity } from '~/types/ListingEntity';\nimport { Recruiter } from '~/types/Recruiter';\nimport { MapConfig, MapConfig as SiteConfig } from '~/types/config/MapConfig';\nimport { get } from 'http';\n\ninterface MapListContextProps {\n loading: boolean;\n allListings: Listing[];\n filteredListings: Listing[];\n mapItems: any;\n query: string | null;\n setNewFilteredListings: (filteredListings: Listing[]) => void;\n setQuery: (query: string | null) => void;\n listingEntities: Record<number, ListingEntity> | null;\n selectedFilters: Record<string, any>;\n setSelectedFilters: (filters: Record<string, any>) => void;\n filterOptions: any;\n recruiters: Record<number, Recruiter>;\n handleFilterListingsByLocation: (selectedLocation: any) => void;\n filterDialogIsOpen: boolean;\n setFilterDialogIsOpen: (isOpen: boolean) => void;\n setMobileTab: (tab: string) => void;\n mobileTab: string;\n siteConfig: SiteConfig;\n googleMapsApiKey?: string;\n favorites: number[];\n resetEntityFilter: () => void;\n handleSettingFavorites: (favorites: number[] | null) => void;\n setFilterByFavorites: (filter: boolean) => void;\n filterByFavorites: boolean;\n commuteLocation: any | null;\n setCommuteLocation: (location: any | null) => void;\n navigateToDetails: (id: number) => void;\n navigateToEasyApply: (id: number) => void;\n Link: React.ComponentType<any>;\n linkFormat: string;\n easyApplyUrl: string;\n easyApplyText: string;\n\tisIframe: boolean;\n sortSetting: { field: string; type: string };\n setSortSetting: (setting: { field: string; type: string }) => void;\n trackEvent: (event: string) => void;\n defaultFilters?: Record<string, any>;\n hiddenFilters?: string[];\n containerStyle?: any;\n ExpandListComponent?: React.ComponentType<{ listing: any }> | ((listing: any) => JSX.Element) | null;\n noEntities?: boolean;\n filterConfig?: {\n hideZeroResults?: boolean;\n dynamicCounts?: boolean;\n showFavorites?: boolean;\n collapsedByDefault?: boolean;\n sortAlphabetically?: boolean;\n classNames?: {\n filterContainer?: string;\n filterContent?: string;\n filterAccordion?: string;\n filterAccordionHeader?: string;\n filterAccordionContent?: string;\n filterItem?: string;\n filterItemLabel?: string;\n filterItemCheckbox?: string;\n filterItemCount?: string;\n searchInput?: string;\n resetButton?: string;\n showJobsButton?: string;\n filterFooter?: string;\n };\n };\n}\n\nconst MapListContext = createContext<MapListContextProps | undefined>(undefined);\n\nexport const useMapList = () => {\n\tconst context = useContext(MapListContext);\n\tif (!context) {\n\t\tthrow new Error('useMapList must be used within a MapListProvider');\n\t}\n\treturn context;\n};\n\nconst getQuery = (localStorageKey: string = ''): string | null => {\n\tlet query: string | null = null;\n\tif (typeof window !== 'undefined') {\n\t\tquery = localStorage.getItem(localStorageKey + 'query');\n\t}\n\treturn query;\n};\n\ninterface MapListProviderProps {\n children: ReactNode;\n siteConfig: MapConfig;\n googleMapsApiKey?: string;\n resetFilters: boolean;\n navigateToDetails: (id: number) => void;\n navigateToEasyApply: (id: number) => void;\n Link: React.ComponentType<any>;\n linkFormat: string;\n easyApplyUrl: string;\n easyApplyText: string;\n\tisIframe: boolean;\n trackEvent: (event: string) => void;\n listings?: Listing[];\n\tentities?: ListingEntity[];\n setFiltersUrl?:boolean;\n hiddenFilters?: string[];\n handleUrlUpdate: (searchParams: string) => void;\n defaultFilters?: Record<string, any>;\n containerStyle?: any;\n\tlocalStorageKey: string;\n\tgetListingEntitiesCallback?: (origin?: string) => Promise<any>;\n ExpandListComponent?: React.ComponentType<{ listing: Listing }> | ((listing: Listing) => JSX.Element) | null;\n hideMap?: boolean;\n hideFilters?: boolean;\n noEntities?: boolean;\n filterConfig?: {\n hideZeroResults?: boolean;\n dynamicCounts?: boolean;\n showFavorites?: boolean;\n collapsedByDefault?: boolean;\n sortAlphabetically?: boolean;\n classNames?: {\n filterContainer?: string;\n filterContent?: string;\n filterAccordion?: string;\n filterAccordionHeader?: string;\n filterAccordionContent?: string;\n filterItem?: string;\n filterItemLabel?: string;\n filterItemCheckbox?: string;\n filterItemCount?: string;\n searchInput?: string;\n resetButton?: string;\n showJobsButton?: string;\n filterFooter?: string;\n };\n };\n}\n\nexport const MapListProvider: React.FC<MapListProviderProps> = ({\n\tchildren,\n\tsiteConfig,\n\tgoogleMapsApiKey,\n\tresetFilters,\n\tnavigateToDetails,\n\tnavigateToEasyApply,\n\tLink,\n\tlinkFormat,\n\teasyApplyUrl,\n\teasyApplyText,\n\tisIframe,\n\ttrackEvent,\n\tlistings = [],\n\tentities = [],\n\tsetFiltersUrl,\n\thiddenFilters,\n\thandleUrlUpdate,\n\tdefaultFilters,\n\tcontainerStyle,\n\tExpandListComponent,\n\tgetListingEntitiesCallback,\n\tlocalStorageKey,\n\thideMap = false,\n\thideFilters = false,\n\tnoEntities = false,\n\tfilterConfig = {\n\t\thideZeroResults: false,\n\t\tdynamicCounts: true,\n\t\tshowFavorites: true,\n\t\tcollapsedByDefault: false,\n\t\tsortAlphabetically: false,\n\t\tclassNames: {\n\t\t\tfilterContainer: '',\n\t\t\tfilterContent: '',\n\t\t\tfilterAccordion: '',\n\t\t\tfilterAccordionHeader: '',\n\t\t\tfilterAccordionContent: '',\n\t\t\tfilterItem: '',\n\t\t\tfilterItemLabel: '',\n\t\t\tfilterItemCheckbox: '',\n\t\t\tfilterItemCount: '',\n\t\t\tsearchInput: '',\n\t\t\tresetButton: '',\n\t\t\tshowJobsButton: '',\n\t\t\tfilterFooter: ''\n\t\t}\n\t}\n}) => {\n\tconst firstLoadFilters = () =>{\n\t\tif (typeof window === 'undefined') {\n\t\t\treturn getStorageObject(localStorageKey + 'selectedFilters', {}) || {};\n\t\t}\n\t\tlet urlData = filtersFromURL(window.location);\n\t\tlet urlFilters = urlData?.filters;\n\n\t\t// If ls-ignore=true is in URL, don't load from localStorage\n\t\tif (urlData?.lsIgnore) {\n\t\t\treturn urlFilters || {};\n\t\t}\n\n\t\treturn (setFiltersUrl === true && urlFilters && Object.keys(urlFilters).length > 0) ? urlFilters : getStorageObject(localStorageKey + 'selectedFilters', {}) || {}\n\t}\n\n\tconst firstLoadQuery = (): string | null => {\n\t\tif (resetFilters) return null;\n\t\tif (typeof window === 'undefined') return getQuery(localStorageKey);\n\t\t// Check URL first\n\t\tconst urlData = filtersFromURL(window.location);\n\n\t\t// If ls-ignore=true is in URL, don't load from localStorage\n\t\tif (urlData?.lsIgnore) {\n\t\t\treturn urlData?.query || null;\n\t\t}\n\n\t\tif (setFiltersUrl === true && urlData?.query) {\n\t\t\treturn urlData.query;\n\t\t}\n\t\t// Fall back to localStorage\n\t\treturn getQuery(localStorageKey);\n\t}\n\n\tconst [allListings, setAllListings] = useState<Listing[]>([]);\n\tconst [filteredListings, setFilteredListings] = useState<Listing[]>([]);\n\tconst [loading, setLoading] = useState<boolean>(false);\n\tconst [mapItems, setMapItems] = useState<any>([]);\n\tconst [query, setQuery] = useState<string | null>(null);\n\tconst [sortSetting, setSortSetting] = useState<{ field: string; type: string }>({ field: 'position', type: 'asc' });\n\tconst [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>({});\n\tconst [firstLoad, setFirstLoad] = useState<boolean>(true);\n\tconst [commuteLocation, setCommuteLocation] = useState<any | null>(null);\n\tconst [selectedFilters, setSelectedFilters] = useState<Record<string, any>>({});\n\tconst [hasMounted, setHasMounted] = useState(false);\n\n\t// Load from localStorage/URL after mount to avoid hydration mismatch\n\tuseEffect(() => {\n\t\tif (typeof window !== 'undefined') {\n\t\t\tconst storedMapItems = getStorageObject(localStorageKey + 'mapItems', []) || [];\n\t\t\tconst storedSortSetting = getStorageObject(localStorageKey + 'sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' };\n\t\t\tconst storedCommuteLocation = getStorageObject(localStorageKey + 'commuteLocation');\n\t\t\t\n\t\t\tsetMapItems(storedMapItems);\n\t\t\tsetSortSetting(storedSortSetting);\n\t\t\tif (storedCommuteLocation) setCommuteLocation(storedCommuteLocation);\n\t\t\t\n\t\t\t// Load filters and query\n\t\t\tif (!resetFilters) {\n\t\t\t\tsetSelectedFilters(firstLoadFilters());\n\t\t\t\tsetQuery(firstLoadQuery());\n\t\t\t}\n\t\t\t\n\t\t\tsetHasMounted(true);\n\t\t}\n\t}, [localStorageKey]);\n\tconst [filterOptions, setFilterOptions] = useState<any>();\n\tconst [recruiters, setRecruiters] = useState<Record<number, Recruiter>>({});\n\tconst [filterDialogIsOpen, setFilterDialogIsOpen] = useState<boolean>(false);\n\tconst [mobileTab, setMobileTab] = useState<string>(\"listTab\");\n\tconst [favorites, setFavorites] = useState<number[]>([]);\n\tconst [filterByFavorites, setFilterByFavorites] = useState<boolean>(false);\n\tconst entitiesInitialized = useRef<boolean>(false);\n\n\tconst setNewFilteredListings = (filteredListings: Listing[]) => {\n\t\tsetFilteredListings(filteredListings);\n\t};\n\n\tuseEffect(() => {\n\t\tif (!sortSetting) return;\n\t\tif (typeof window !== 'undefined') {\n\t\t\tlocalStorage.setItem(localStorageKey + 'sortSetting', JSON.stringify(sortSetting));\n\t\t}\n\t}, [sortSetting, localStorageKey]);\n\n\tuseEffect(() => {\n\t\tif (typeof window === 'undefined') return;\n\t\tconst loadedFavorites = JSON.parse(localStorage.getItem(localStorageKey + 'favorites') || '[]');\n\t\tsetFavorites(loadedFavorites);\n\t}, [localStorageKey]);\n\n\tuseEffect(() => {\n\t\tsetStorageObject(localStorageKey + \"commuteLocation\", commuteLocation);\n\t}, [commuteLocation, localStorageKey]);\n\n\n\tuseEffect(() => {\n\t\tif (!commuteLocation || noEntities) return;\n\n\t\tasync function fetchEntities() {\n\t\t\ttry {\n\t\t\t\t// Only fetch if callback is provided\n\t\t\t\tif (!getListingEntitiesCallback) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tconst fetchedEntities = await getListingEntitiesCallback(`${commuteLocation.lat}, ${commuteLocation.lng}`);\n\t\t\t\tsetListingEntities(fetchedEntities);\n\t\t\t\t// Update travelTime on listings\n\t\t\t\tconst newFilteredListings: Listing[] = [...filteredListings];\n\t\t\t\tfor (let i = 0; i < allListings.length; i++) {\n\t\t\t\t\tconst listing = newFilteredListings[i];\n\t\t\t\t\tif (\n\t\t\t\t\t\tlisting &&\n\t\t\t\t\t\tlisting.fields &&\n\t\t\t\t\t\tlisting.fields.entityKey &&\n\t\t\t\t\t\tlisting.fields.entityKey !== ''\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst entityKey = listing.fields.entityKey;\n\t\t\t\t\t\t// Try exact match first, then lowercase match for case-insensitive lookup\n\t\t\t\t\t\tconst travelTime = (fetchedEntities[entityKey] || fetchedEntities[entityKey.toLowerCase()])?.travelTime;\n\t\t\t\t\t\tif (travelTime !== undefined && listing.fields) {\n\t\t\t\t\t\t\tlisting.fields.travelTime = travelTime;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"Failed to fetch listing entities:\", error);\n\t\t\t}\n\t\t}\n\n\t\tfetchEntities();\n\t}, [commuteLocation, noEntities]);\n\n\t// Set listingEntities from passed-in entities (only once on initial load)\n\t// Entities should be an object: { \"rochester, mn\": {...}, \"albuquerque, nm\": {...} }\n\t// Note: Commute location changes will fetch updated entities with travel times via separate useEffect\n\tuseEffect(() => {\n\t\tif (!entities || entitiesInitialized.current) return;\n\t\t\n\t\tentitiesInitialized.current = true;\n\t\t\n\t\t// Handle both object (production format) and array (for backwards compatibility)\n\t\tif (Array.isArray(entities)) {\n\t\t\t// Convert array to object\n\t\t\tconst entitiesObj: Record<string, any> = {};\n\t\t\tentities.forEach((entity: any) => {\n\t\t\t\tif (entity.entityKey) {\n\t\t\t\t\tentitiesObj[entity.entityKey.toLowerCase()] = entity;\n\t\t\t\t}\n\t\t\t});\n\t\t\tconsole.log('Set listingEntities from entities array:', entitiesObj);\n\t\t\tsetListingEntities(entitiesObj);\n\t\t} else if (typeof entities === 'object') {\n\t\t\t// Normalize keys to lowercase for production format\n\t\t\tconst normalizedEntities: Record<string, any> = {};\n\t\t\tObject.keys(entities).forEach(key => {\n\t\t\t\tnormalizedEntities[key.toLowerCase()] = entities[key];\n\t\t\t});\n\t\t\tconsole.log('Set listingEntities from entities object:', normalizedEntities);\n\t\t\tsetListingEntities(normalizedEntities);\n\t\t}\n\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, []); // Empty deps - only run once on mount, entities are static data\n\n\t// Set listings from passed-in data\n\tuseEffect(() => {\n\t\tif (!listings || listings.length === 0) {\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tsetLoading(true);\n\n\t\ttry {\n\t\t\t// Apply default filters if provided\n\t\t\tlet processedListings = listings;\n\t\t\tif (defaultFilters) {\n\t\t\t\tprocessedListings = listings.filter(listing => {\n\t\t\t\t\tif (!listing.fields) return false;\n\n\t\t\t\t\treturn Object.keys(defaultFilters).every(filterKey => {\n\t\t\t\t\t\tconst filterValues = defaultFilters[filterKey as keyof typeof defaultFilters];\n\t\t\t\t\t\tconst listingValue = listing.fields ? listing.fields[filterKey as keyof typeof listing.fields] : null;\n\t\t\t\t\t\treturn filterValues.includes(listingValue);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsetAllListings(processedListings);\n\t\t\tconsole.log('Set allListings to', processedListings.length, 'items');\n\t\t\t\n\t\t\t// Map items will be set when entities are processed\n\t\t\t// For now, just set empty object - will be populated when entities arrive\n\t\t\tsetMapItems({});\n\t\t} catch (error) {\n\t\t\tconsole.error('Error processing listings:', error);\n\t\t}\n\t\t\n\t\tsetLoading(false);\n\t}, [listings]);\n\n\tuseEffect(() => {\n\t\tconst processListings = async () => {\n\t\t\t// Don't process if allListings hasn't been loaded yet\n\t\t\tif (allListings.length === 0) {\n\t\t\t\tconsole.log('processListings: Skipping - allListings is empty');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet filteredListings: Listing[];\n\t\t\tlet tempSelectedFilters = selectedFilters;\n\t\t\tlet tempQuery = query;\n\n\t\t\tconsole.log('processListings: Running with query:', tempQuery, 'and', allListings.length, 'listings');\n\n\t\t\tconst { mapItems, filteredListings: tempFilteredListings } = await applyFilters(\n\t\t\t\tallListings,\n\t\t\t\ttempSelectedFilters,\n\t\t\t\ttempQuery,\n\t\t\t\tlistingEntities,\n\t\t\t\tfavorites,\n\t\t\t\tsiteConfig\n\t\t\t);\n\t\t\tfilteredListings = tempFilteredListings;\n\n\t\t\tif (filterByFavorites) {\n\t\t\t\tfilteredListings = filteredListings.filter((x: Listing) => favorites.includes(x.id));\n\t\t\t}\n\n\t\t\t// Batch state updates together\n\t\t\tsetNewFilteredListings(filteredListings);\n\t\t\tsetMapItems(mapItems);\n\n\t\t\tif (firstLoad && tempSelectedFilters) {\n\t\t\t\t// Update URL with filters if needed\n\t\t\t} else if (Object.keys(tempSelectedFilters).length === 0 && !firstLoad) {\n\t\t\t\tlocalStorage.removeItem(localStorageKey + 'selectedFilters');\n\t\t\t} else if (!firstLoad) {\n\t\t\t\tsetStorageObject(localStorageKey + 'selectedFilters', tempSelectedFilters);\n\t\t\t}\n\t\t\tif(setFiltersUrl === true && typeof window !== 'undefined')\n\t\t\t{\n\t\t\t\tupdateURLWithFilters(tempSelectedFilters, window.location, tempQuery, handleUrlUpdate);\n\t\t\t}\n\t\t\tif (typeof window !== 'undefined') {\n\t\t\t\ttempQuery != null ? localStorage.setItem(localStorageKey + 'query', tempQuery) : localStorage.removeItem(localStorageKey + 'query');\n\t\t\t}\n\n\t\t\tif (tempSelectedFilters) {\n\t\t\t\tconst keys = Object.keys(tempSelectedFilters);\n\t\t\t\tconst lastKey = keys[keys.length - 1];\n\n\t\t\t\t// Ensure all filterConfig properties have values\n\t\t\t\tconst normalizedFilterConfig = {\n\t\t\t\t\thideZeroResults: filterConfig?.hideZeroResults ?? false,\n\t\t\t\t\tdynamicCounts: filterConfig?.dynamicCounts ?? true,\n\t\t\t\t\tshowFavorites: filterConfig?.showFavorites ?? true,\n\t\t\t\t\tcollapsedByDefault: filterConfig?.collapsedByDefault ?? false,\n\t\t\t\t\tsortAlphabetically: filterConfig?.sortAlphabetically ?? false,\n\t\t\t\t\tclassNames: {\n\t\t\t\t\t\tfilterContainer: filterConfig?.classNames?.filterContainer ?? '',\n\t\t\t\t\t\tfilterContent: filterConfig?.classNames?.filterContent ?? '',\n\t\t\t\t\t\tfilterAccordion: filterConfig?.classNames?.filterAccordion ?? '',\n\t\t\t\t\t\tfilterAccordionHeader: filterConfig?.classNames?.filterAccordionHeader ?? '',\n\t\t\t\t\t\tfilterAccordionContent: filterConfig?.classNames?.filterAccordionContent ?? '',\n\t\t\t\t\t\tfilterItem: filterConfig?.classNames?.filterItem ?? '',\n\t\t\t\t\t\tfilterItemLabel: filterConfig?.classNames?.filterItemLabel ?? '',\n\t\t\t\t\t\tfilterItemCheckbox: filterConfig?.classNames?.filterItemCheckbox ?? '',\n\t\t\t\t\t\tfilterItemCount: filterConfig?.classNames?.filterItemCount ?? '',\n\t\t\t\t\t\tsearchInput: filterConfig?.classNames?.searchInput ?? '',\n\t\t\t\t\t\tresetButton: filterConfig?.classNames?.resetButton ?? '',\n\t\t\t\t\t\tshowJobsButton: filterConfig?.classNames?.showJobsButton ?? '',\n\t\t\t\t\t\tfilterFooter: filterConfig?.classNames?.filterFooter ?? ''\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tconst options = generateFilterOptions(\n\t\t\t\t\tfilteredListings,\n\t\t\t\t\tallListings,\n\t\t\t\t\tsiteConfig,\n\t\t\t\t\tfilterOptions,\n\t\t\t\t\tlastKey,\n\t\t\t\t\tfavorites,\n\t\t\t\t\ttempSelectedFilters,\n\t\t\t\t\tnormalizedFilterConfig\n\t\t\t\t);\n\t\t\t\tif (options) {\n\t\t\t\t\tsetFilterOptions(options);\n\t\t\t\t\tif (firstLoad) setFirstLoad(false);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tprocessListings();\n\t}, [selectedFilters, query, filterByFavorites, favorites, allListings]);\n\n\tconst handleFilterListingsByLocation = (selectedLocation: any) => {\n\t\tconst { filteredListings } = filterListingsByLocation(\n\t\t\tallListings,\n\t\t\tselectedLocation,\n\t\t\tlistingEntities\n\t\t);\n\t\tsetNewFilteredListings(filteredListings);\n\t};\n\n\tconst resetEntityFilter = () => {\n\t\tlet newFilters = {...selectedFilters};\n\t\tdelete newFilters.entityId;\n\t\tsetSelectedFilters(newFilters);\n\t}\n\n\tconst handleSettingFavorites = (newFavorites: number[] | null) => {\n\t\tif (typeof window === 'undefined') return;\n\t\tif (newFavorites == null) {\n\t\t\tlocalStorage.removeItem(localStorageKey + 'favorites');\n\t\t} else {\n\t\t\tsetFavorites(newFavorites);\n\t\t\tlocalStorage.setItem(localStorageKey + 'favorites', JSON.stringify(newFavorites));\n\t\t}\n\t};\n\n\treturn (\n\t\t<MapListContext.Provider value={{\n\t\t\tloading,\n\t\t\tallListings,\n\t\t\tfilteredListings,\n\t\t\tmapItems,\n\t\t\tquery,\n\t\t\tsetNewFilteredListings,\n\t\t\tsetQuery,\n\t\t\tlistingEntities,\n\t\t\tselectedFilters,\n\t\t\tsetSelectedFilters,\n\t\t\tfilterOptions,\n\t\t\trecruiters,\n\t\t\thandleFilterListingsByLocation,\n\t\t\tfilterDialogIsOpen,\n\t\t\tsetFilterDialogIsOpen,\n\t\t\tsetMobileTab,\n\t\t\tmobileTab,\n\t\t\tsiteConfig,\n\t\t\tgoogleMapsApiKey,\n\t\t\tfavorites,\n\t\t\thandleSettingFavorites,\n\t\t\tresetEntityFilter,\n\t\t\tsetFilterByFavorites,\n\t\t\tfilterByFavorites,\n\t\t\tcommuteLocation,\n\t\t\tsetCommuteLocation,\n\t\t\tnavigateToDetails,\n\t\t\tnavigateToEasyApply,\n\t\t\tLink,\n\t\t\tlinkFormat,\n\t\t\teasyApplyUrl,\n\t\t\teasyApplyText,\n\t\t\tisIframe,\n\t\t\tsortSetting,\n\t\t\tsetSortSetting,\n\t\t\ttrackEvent,\n\t\t\tdefaultFilters,\n\t\t\thiddenFilters,\n\t\t\tcontainerStyle,\n\t\t\tExpandListComponent,\n\t\t\tnoEntities,\n\t\t\tfilterConfig\n\t\t}}>\n\t\t\t{children}\n\t\t</MapListContext.Provider>\n\t);\n};\n"],"names":[],"mappings":";;;;;AA8EA,MAAM,cAAc,GAAG,aAAa,CAAkC,SAAS,CAAC,CAAC;AAE1E,MAAM,UAAU,GAAG,MAAK;AAC9B,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE;AACb,QAAA,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;AACpE,KAAA;AACD,IAAA,OAAO,OAAO,CAAC;AAChB,EAAE;AAEF,MAAM,QAAQ,GAAG,CAAC,eAA0B,GAAA,EAAE,KAAmB;IAChE,IAAI,KAAK,GAAkB,IAAI,CAAC;AAChC,IAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;QAClC,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,CAAC;AACxD,KAAA;AACD,IAAA,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAoDK,MAAM,eAAe,GAAmC,CAAC,EAC/D,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,IAAI,EACJ,UAAU,EACV,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,UAAU,EACV,QAAQ,GAAG,EAAE,EACb,QAAQ,GAAG,EAAE,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,mBAAmB,EACnB,0BAA0B,EAC1B,eAAe,EACf,OAAO,GAAG,KAAK,EACf,WAAW,GAAG,KAAK,EACnB,UAAU,GAAG,KAAK,EAClB,YAAY,GAAG;AACd,IAAA,eAAe,EAAE,KAAK;AACtB,IAAA,aAAa,EAAE,IAAI;AACnB,IAAA,aAAa,EAAE,IAAI;AACnB,IAAA,kBAAkB,EAAE,KAAK;AACzB,IAAA,kBAAkB,EAAE,KAAK;AACzB,IAAA,UAAU,EAAE;AACX,QAAA,eAAe,EAAE,EAAE;AACnB,QAAA,aAAa,EAAE,EAAE;AACjB,QAAA,eAAe,EAAE,EAAE;AACnB,QAAA,qBAAqB,EAAE,EAAE;AACzB,QAAA,sBAAsB,EAAE,EAAE;AAC1B,QAAA,UAAU,EAAE,EAAE;AACd,QAAA,eAAe,EAAE,EAAE;AACnB,QAAA,kBAAkB,EAAE,EAAE;AACtB,QAAA,eAAe,EAAE,EAAE;AACnB,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,WAAW,EAAE,EAAE;AACf,QAAA,cAAc,EAAE,EAAE;AAClB,QAAA,YAAY,EAAE,EAAE;AAChB,KAAA;AACD,CAAA,EACD,KAAI;IACJ,MAAM,gBAAgB,GAAG,MAAK;AAC7B,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;YAClC,OAAO,gBAAgB,CAAC,eAAe,GAAG,iBAAiB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AACvE,SAAA;QACD,IAAI,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC9C,QAAA,IAAI,UAAU,GAAG,OAAO,EAAE,OAAO,CAAC;;QAGlC,IAAI,OAAO,EAAE,QAAQ,EAAE;YACtB,OAAO,UAAU,IAAI,EAAE,CAAC;AACxB,SAAA;AAED,QAAA,OAAQ,CAAC,aAAa,KAAK,IAAI,IAAI,UAAU,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,GAAI,gBAAgB,CAAC,eAAe,GAAG,iBAAiB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;AACrK,KAAC,CAAA;IAED,MAAM,cAAc,GAAG,MAAoB;AAC1C,QAAA,IAAI,YAAY;AAAE,YAAA,OAAO,IAAI,CAAC;QAC9B,IAAI,OAAO,MAAM,KAAK,WAAW;AAAE,YAAA,OAAO,QAAQ,CAAC,eAAe,CAAC,CAAC;;QAEpE,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;;QAGhD,IAAI,OAAO,EAAE,QAAQ,EAAE;AACtB,YAAA,OAAO,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC;AAC9B,SAAA;AAED,QAAA,IAAI,aAAa,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,EAAE;YAC7C,OAAO,OAAO,CAAC,KAAK,CAAC;AACrB,SAAA;;AAED,QAAA,OAAO,QAAQ,CAAC,eAAe,CAAC,CAAC;AAClC,KAAC,CAAA;IAED,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAY,EAAE,CAAC,CAAC;IAC9D,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAY,EAAE,CAAC,CAAC;IACxE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IACvD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAM,EAAE,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;AACxD,IAAA,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAkC,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpH,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAuC,EAAE,CAAC,CAAC;IACjG,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAU,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAa,IAAI,CAAC,CAAC;IACzE,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAsB,EAAE,CAAC,CAAC;IAChF,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;;IAGpD,SAAS,CAAC,MAAK;AACd,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AAClC,YAAA,MAAM,cAAc,GAAG,gBAAgB,CAAC,eAAe,GAAG,UAAU,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AAChF,YAAA,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,eAAe,GAAG,aAAa,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;YACtJ,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,eAAe,GAAG,iBAAiB,CAAC,CAAC;YAEpF,WAAW,CAAC,cAAc,CAAC,CAAC;YAC5B,cAAc,CAAC,iBAAiB,CAAC,CAAC;AAClC,YAAA,IAAI,qBAAqB;gBAAE,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;;YAGrE,IAAI,CAAC,YAAY,EAAE;AAClB,gBAAA,kBAAkB,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACvC,gBAAA,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC;AAC3B,aAAA;YAED,aAAa,CAAC,IAAI,CAAC,CAAC;AACpB,SAAA;AACF,KAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IACtB,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,EAAO,CAAC;IAC1D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAA4B,EAAE,CAAC,CAAC;IAC5E,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC7E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAS,SAAS,CAAC,CAAC;IAC9D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAW,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;AAC3E,IAAA,MAAM,mBAAmB,GAAG,MAAM,CAAU,KAAK,CAAC,CAAC;AAEnD,IAAA,MAAM,sBAAsB,GAAG,CAAC,gBAA2B,KAAI;QAC9D,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;AACvC,KAAC,CAAC;IAEF,SAAS,CAAC,MAAK;AACd,QAAA,IAAI,CAAC,WAAW;YAAE,OAAO;AACzB,QAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AAClC,YAAA,YAAY,CAAC,OAAO,CAAC,eAAe,GAAG,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;AACnF,SAAA;AACF,KAAC,EAAE,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;IAEnC,SAAS,CAAC,MAAK;QACd,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;AAC1C,QAAA,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,eAAe,GAAG,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC;QAChG,YAAY,CAAC,eAAe,CAAC,CAAC;AAC/B,KAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,SAAS,CAAC,MAAK;AACd,QAAA,gBAAgB,CAAC,eAAe,GAAG,iBAAiB,EAAE,eAAe,CAAC,CAAC;AACxE,KAAC,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC,CAAC;IAGvC,SAAS,CAAC,MAAK;QACd,IAAI,CAAC,eAAe,IAAI,UAAU;YAAE,OAAO;AAE3C,QAAA,eAAe,aAAa,GAAA;YAC3B,IAAI;;gBAEH,IAAI,CAAC,0BAA0B,EAAE;oBAChC,OAAO;AACP,iBAAA;AAED,gBAAA,MAAM,eAAe,GAAG,MAAM,0BAA0B,CAAC,CAAG,EAAA,eAAe,CAAC,GAAG,KAAK,eAAe,CAAC,GAAG,CAAA,CAAE,CAAC,CAAC;gBAC3G,kBAAkB,CAAC,eAAe,CAAC,CAAC;;AAEpC,gBAAA,MAAM,mBAAmB,GAAc,CAAC,GAAG,gBAAgB,CAAC,CAAC;AAC7D,gBAAA,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;AAC5C,oBAAA,MAAM,OAAO,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;AACvC,oBAAA,IACC,OAAO;AACP,wBAAA,OAAO,CAAC,MAAM;wBACd,OAAO,CAAC,MAAM,CAAC,SAAS;AACxB,wBAAA,OAAO,CAAC,MAAM,CAAC,SAAS,KAAK,EAAE,EAC9B;AACD,wBAAA,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;;AAE3C,wBAAA,MAAM,UAAU,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,GAAG,UAAU,CAAC;AACxG,wBAAA,IAAI,UAAU,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE;AAC/C,4BAAA,OAAO,CAAC,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;AACvC,yBAAA;AACD,qBAAA;AACD,iBAAA;AACD,aAAA;AAAC,YAAA,OAAO,KAAK,EAAE;AACf,gBAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;AAC1D,aAAA;SACD;AAED,QAAA,aAAa,EAAE,CAAC;AACjB,KAAC,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC;;;;IAKlC,SAAS,CAAC,MAAK;AACd,QAAA,IAAI,CAAC,QAAQ,IAAI,mBAAmB,CAAC,OAAO;YAAE,OAAO;AAErD,QAAA,mBAAmB,CAAC,OAAO,GAAG,IAAI,CAAC;;AAGnC,QAAA,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE;;YAE5B,MAAM,WAAW,GAAwB,EAAE,CAAC;AAC5C,YAAA,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAW,KAAI;gBAChC,IAAI,MAAM,CAAC,SAAS,EAAE;oBACrB,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,GAAG,MAAM,CAAC;AACrD,iBAAA;AACF,aAAC,CAAC,CAAC;AACH,YAAA,OAAO,CAAC,GAAG,CAAC,0CAA0C,EAAE,WAAW,CAAC,CAAC;YACrE,kBAAkB,CAAC,WAAW,CAAC,CAAC;AAChC,SAAA;AAAM,aAAA,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;;YAExC,MAAM,kBAAkB,GAAwB,EAAE,CAAC;YACnD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,IAAG;gBACnC,kBAAkB,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;AACvD,aAAC,CAAC,CAAC;AACH,YAAA,OAAO,CAAC,GAAG,CAAC,2CAA2C,EAAE,kBAAkB,CAAC,CAAC;YAC7E,kBAAkB,CAAC,kBAAkB,CAAC,CAAC;AACvC,SAAA;;AAEF,KAAC,EAAE,EAAE,CAAC,CAAC;;IAGP,SAAS,CAAC,MAAK;QACd,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;YACvC,UAAU,CAAC,KAAK,CAAC,CAAC;YAClB,OAAO;AACP,SAAA;QAED,UAAU,CAAC,IAAI,CAAC,CAAC;QAEjB,IAAI;;YAEH,IAAI,iBAAiB,GAAG,QAAQ,CAAC;AACjC,YAAA,IAAI,cAAc,EAAE;AACnB,gBAAA,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,IAAG;oBAC7C,IAAI,CAAC,OAAO,CAAC,MAAM;AAAE,wBAAA,OAAO,KAAK,CAAC;oBAElC,OAAO,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,SAAS,IAAG;AACpD,wBAAA,MAAM,YAAY,GAAG,cAAc,CAAC,SAAwC,CAAC,CAAC;AAC9E,wBAAA,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,SAAwC,CAAC,GAAG,IAAI,CAAC;AACtG,wBAAA,OAAO,YAAY,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;AAC5C,qBAAC,CAAC,CAAC;AACJ,iBAAC,CAAC,CAAC;AACH,aAAA;YAED,cAAc,CAAC,iBAAiB,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;YAIrE,WAAW,CAAC,EAAE,CAAC,CAAC;AAChB,SAAA;AAAC,QAAA,OAAO,KAAK,EAAE;AACf,YAAA,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;AACnD,SAAA;QAED,UAAU,CAAC,KAAK,CAAC,CAAC;AACnB,KAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,SAAS,CAAC,MAAK;AACd,QAAA,MAAM,eAAe,GAAG,YAAW;;AAElC,YAAA,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE;AAC7B,gBAAA,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;gBAChE,OAAO;AACP,aAAA;AAED,YAAA,IAAI,gBAA2B,CAAC;YAChC,IAAI,mBAAmB,GAAG,eAAe,CAAC;YAC1C,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,YAAA,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAEtG,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,GAAG,MAAM,YAAY,CAC9E,WAAW,EACX,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,SAAS,EACT,UAAU,CACV,CAAC;YACF,gBAAgB,GAAG,oBAAoB,CAAC;AAExC,YAAA,IAAI,iBAAiB,EAAE;AACtB,gBAAA,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAU,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACrF,aAAA;;YAGD,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;YACzC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAEtB,IAAI,SAAS,IAAI,mBAAmB,EAAE,CAErC;AAAM,iBAAA,IAAI,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE;AACvE,gBAAA,YAAY,CAAC,UAAU,CAAC,eAAe,GAAG,iBAAiB,CAAC,CAAC;AAC7D,aAAA;iBAAM,IAAI,CAAC,SAAS,EAAE;AACtB,gBAAA,gBAAgB,CAAC,eAAe,GAAG,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;AAC3E,aAAA;YACD,IAAG,aAAa,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,WAAW,EAC1D;gBACC,oBAAoB,CAAC,mBAAmB,EAAE,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;AACvF,aAAA;AACD,YAAA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;gBAClC,SAAS,IAAI,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,eAAe,GAAG,OAAO,EAAE,SAAS,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC,eAAe,GAAG,OAAO,CAAC,CAAC;AACpI,aAAA;AAED,YAAA,IAAI,mBAAmB,EAAE;gBACxB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;;AAGtC,gBAAA,MAAM,sBAAsB,GAAG;AAC9B,oBAAA,eAAe,EAAE,YAAY,EAAE,eAAe,IAAI,KAAK;AACvD,oBAAA,aAAa,EAAE,YAAY,EAAE,aAAa,IAAI,IAAI;AAClD,oBAAA,aAAa,EAAE,YAAY,EAAE,aAAa,IAAI,IAAI;AAClD,oBAAA,kBAAkB,EAAE,YAAY,EAAE,kBAAkB,IAAI,KAAK;AAC7D,oBAAA,kBAAkB,EAAE,YAAY,EAAE,kBAAkB,IAAI,KAAK;AAC7D,oBAAA,UAAU,EAAE;AACX,wBAAA,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,IAAI,EAAE;AAChE,wBAAA,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,IAAI,EAAE;AAC5D,wBAAA,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,IAAI,EAAE;AAChE,wBAAA,qBAAqB,EAAE,YAAY,EAAE,UAAU,EAAE,qBAAqB,IAAI,EAAE;AAC5E,wBAAA,sBAAsB,EAAE,YAAY,EAAE,UAAU,EAAE,sBAAsB,IAAI,EAAE;AAC9E,wBAAA,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,IAAI,EAAE;AACtD,wBAAA,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,IAAI,EAAE;AAChE,wBAAA,kBAAkB,EAAE,YAAY,EAAE,UAAU,EAAE,kBAAkB,IAAI,EAAE;AACtE,wBAAA,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,eAAe,IAAI,EAAE;AAChE,wBAAA,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,IAAI,EAAE;AACxD,wBAAA,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,IAAI,EAAE;AACxD,wBAAA,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,IAAI,EAAE;AAC9D,wBAAA,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,IAAI,EAAE;AAC1D,qBAAA;iBACD,CAAC;gBAEF,MAAM,OAAO,GAAG,qBAAqB,CACpC,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,aAAa,EACb,OAAO,EACP,SAAS,EACT,mBAAmB,EACnB,sBAAsB,CACtB,CAAC;AACF,gBAAA,IAAI,OAAO,EAAE;oBACZ,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAC1B,oBAAA,IAAI,SAAS;wBAAE,YAAY,CAAC,KAAK,CAAC,CAAC;AACnC,iBAAA;AACD,aAAA;AACF,SAAC,CAAC;AAEF,QAAA,eAAe,EAAE,CAAC;AACnB,KAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;AAExE,IAAA,MAAM,8BAA8B,GAAG,CAAC,gBAAqB,KAAI;AAChE,QAAA,MAAM,EAAE,gBAAgB,EAAE,GAAG,wBAAwB,CACpD,WAAW,EACX,gBAAgB,EAChB,eAAe,CACf,CAAC;QACF,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;AAC1C,KAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,MAAK;AAC9B,QAAA,IAAI,UAAU,GAAG,EAAC,GAAG,eAAe,EAAC,CAAC;QACtC,OAAO,UAAU,CAAC,QAAQ,CAAC;QAC3B,kBAAkB,CAAC,UAAU,CAAC,CAAC;AAChC,KAAC,CAAA;AAED,IAAA,MAAM,sBAAsB,GAAG,CAAC,YAA6B,KAAI;QAChE,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,IAAI,YAAY,IAAI,IAAI,EAAE;AACzB,YAAA,YAAY,CAAC,UAAU,CAAC,eAAe,GAAG,WAAW,CAAC,CAAC;AACvD,SAAA;AAAM,aAAA;YACN,YAAY,CAAC,YAAY,CAAC,CAAC;AAC3B,YAAA,YAAY,CAAC,OAAO,CAAC,eAAe,GAAG,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;AAClF,SAAA;AACF,KAAC,CAAC;AAEF,IAAA,QACC,KAAC,CAAA,aAAA,CAAA,cAAc,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE;YAC/B,OAAO;YACP,WAAW;YACX,gBAAgB;YAChB,QAAQ;YACR,KAAK;YACL,sBAAsB;YACtB,QAAQ;YACR,eAAe;YACf,eAAe;YACf,kBAAkB;YAClB,aAAa;YACb,UAAU;YACV,8BAA8B;YAC9B,kBAAkB;YAClB,qBAAqB;YACrB,YAAY;YACZ,SAAS;YACT,UAAU;YACV,gBAAgB;YAChB,SAAS;YACT,sBAAsB;YACtB,iBAAiB;YACjB,oBAAoB;YACpB,iBAAiB;YACjB,eAAe;YACf,kBAAkB;YAClB,iBAAiB;YACjB,mBAAmB;YACnB,IAAI;YACJ,UAAU;YACV,YAAY;YACZ,aAAa;YACb,QAAQ;YACR,WAAW;YACX,cAAc;YACd,UAAU;YACV,cAAc;YACd,aAAa;YACb,cAAc;YACd,mBAAmB;YACnB,UAAU;YACV,YAAY;SACZ,EACC,EAAA,QAAQ,CACgB,EACzB;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -30,17 +30,24 @@ const ItemsListContainer: React.FC<ItemsListContainerProps> = ({
|
|
|
30
30
|
const itemExpandedContent = (item: any, recruiter: any) =>
|
|
31
31
|
item ? (ExpandListComponent ? <ExpandListComponent listing={item} /> : <ListingDetailsContainer item={item} recruiter={recruiter} />) : null;
|
|
32
32
|
|
|
33
|
+
// Track if component has mounted to avoid hydration mismatch with localStorage
|
|
34
|
+
const [hasMounted, setHasMounted] = React.useState(false);
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
setHasMounted(true);
|
|
37
|
+
}, []);
|
|
38
|
+
|
|
33
39
|
// Use useMemo to avoid hydration mismatch - create new array instead of mutating prop
|
|
40
|
+
// Don't add travelTime until after mount to avoid SSR/client mismatch from localStorage
|
|
34
41
|
const effectiveFieldsShown = useMemo(() => {
|
|
35
42
|
const fields = [...fieldsShown];
|
|
36
|
-
if (!fields.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0 && !noEntities) {
|
|
43
|
+
if (hasMounted && !fields.includes('travelTime') && commuteLocation != null && Object.entries(commuteLocation).length > 0 && !noEntities) {
|
|
37
44
|
fields.push('travelTime');
|
|
38
45
|
fieldNames['travelTime'] = 'Commute';
|
|
39
46
|
} else if (fields.includes('travelTime') && (!commuteLocation || noEntities)) {
|
|
40
47
|
return fields.filter(x => x !== 'travelTime');
|
|
41
48
|
}
|
|
42
49
|
return fields;
|
|
43
|
-
}, [fieldsShown, commuteLocation, noEntities, fieldNames]);
|
|
50
|
+
}, [fieldsShown, commuteLocation, noEntities, fieldNames, hasMounted]);
|
|
44
51
|
|
|
45
52
|
const setTrackedSortSetting = (sortSetting: { field: string; type: string }) => {
|
|
46
53
|
trackEvent(eventTypes.LIST_SORTED, sortSetting);
|
|
@@ -20,10 +20,16 @@ const Filter = ({
|
|
|
20
20
|
const containerRef = useRef(null);
|
|
21
21
|
const [hasOverflow, setHasOverflow] = useState(false);
|
|
22
22
|
const [showFixedFooter, setShowFixedFooter] = useState(false);
|
|
23
|
+
const [hasMounted, setHasMounted] = useState(false);
|
|
23
24
|
const transitionTimeoutRef = useRef(null);
|
|
24
25
|
|
|
26
|
+
// Set mounted state to avoid hydration mismatch
|
|
25
27
|
useEffect(() => {
|
|
26
|
-
|
|
28
|
+
setHasMounted(true);
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (typeof window === 'undefined' || !hasMounted) return;
|
|
27
33
|
|
|
28
34
|
const checkOverflow = () => {
|
|
29
35
|
if (contentRef.current) {
|
|
@@ -83,7 +89,7 @@ const Filter = ({
|
|
|
83
89
|
clearTimeout(transitionTimeoutRef.current);
|
|
84
90
|
}
|
|
85
91
|
};
|
|
86
|
-
}, [children, hasOverflow]);
|
|
92
|
+
}, [children, hasOverflow, hasMounted]);
|
|
87
93
|
|
|
88
94
|
// Reusable button component
|
|
89
95
|
const MobileButtons = () => (
|
|
@@ -41,14 +41,34 @@ interface MapProviderProps {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export const MapProvider: React.FC<MapProviderProps> = ({ children, resetFilters, defaultZoomOverride, localStorageKey = '' }) => {
|
|
44
|
-
|
|
45
|
-
const [
|
|
46
|
-
const [
|
|
47
|
-
const [
|
|
44
|
+
// Initialize with defaults to avoid hydration mismatch - load from localStorage after mount
|
|
45
|
+
const [selectedListItem, setSelectedListItem] = useState<Listing | null>(null);
|
|
46
|
+
const [location, setLocation] = useState<any>(null);
|
|
47
|
+
const [center, setCenter] = useState<LatLng>({ lat: 39.8283, lng: -98.5795 });
|
|
48
|
+
const [zoom, setZoom] = useState<number>(9);
|
|
48
49
|
const [selectedPlaces, setSelectedPlaces] = useState<string[]>([]);
|
|
49
50
|
const [mapInteracted, setMapInteracted] = useState<boolean>(false);
|
|
50
|
-
const [firstLoadListItem] = useState<any>(
|
|
51
|
+
const [firstLoadListItem, setFirstLoadListItem] = useState<any>({ id: "defaultId" });
|
|
51
52
|
const userSetZoom = useRef<boolean>(true);
|
|
53
|
+
const [hasMounted, setHasMounted] = useState(false);
|
|
54
|
+
|
|
55
|
+
// Load from localStorage after mount to avoid hydration mismatch
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (typeof window !== 'undefined') {
|
|
58
|
+
const storedItem = getStorageObject(localStorageKey + 'selectedListItem');
|
|
59
|
+
const storedLocation = getStorageObject(localStorageKey + 'location');
|
|
60
|
+
const storedCenter = getStorageObject(localStorageKey + "center", { lat: 39.8283, lng: -98.5795 });
|
|
61
|
+
const storedZoom = getStorageObject(localStorageKey + "zoom", 9);
|
|
62
|
+
const storedFirstLoad = getStorageObject(localStorageKey + 'selectedListItem', { id: "defaultId" });
|
|
63
|
+
|
|
64
|
+
if (storedItem) setSelectedListItem(storedItem);
|
|
65
|
+
if (storedLocation) setLocation(storedLocation);
|
|
66
|
+
if (storedCenter) setCenter(storedCenter);
|
|
67
|
+
if (storedZoom) setZoom(storedZoom);
|
|
68
|
+
if (storedFirstLoad) setFirstLoadListItem(storedFirstLoad);
|
|
69
|
+
setHasMounted(true);
|
|
70
|
+
}
|
|
71
|
+
}, [localStorageKey]);
|
|
52
72
|
|
|
53
73
|
useEffect(() => {
|
|
54
74
|
setStorageObject(localStorageKey + "selectedListItem", selectedListItem);
|
|
@@ -229,13 +229,35 @@ export const MapListProvider: React.FC<MapListProviderProps> = ({
|
|
|
229
229
|
const [allListings, setAllListings] = useState<Listing[]>([]);
|
|
230
230
|
const [filteredListings, setFilteredListings] = useState<Listing[]>([]);
|
|
231
231
|
const [loading, setLoading] = useState<boolean>(false);
|
|
232
|
-
const [mapItems, setMapItems] = useState<any>(
|
|
233
|
-
const [query, setQuery] = useState<string | null>(
|
|
234
|
-
const [sortSetting, setSortSetting] = useState<{ field: string; type: string }>(
|
|
232
|
+
const [mapItems, setMapItems] = useState<any>([]);
|
|
233
|
+
const [query, setQuery] = useState<string | null>(null);
|
|
234
|
+
const [sortSetting, setSortSetting] = useState<{ field: string; type: string }>({ field: 'position', type: 'asc' });
|
|
235
235
|
const [listingEntities, setListingEntities] = useState<Record<number, ListingEntity> | null>({});
|
|
236
236
|
const [firstLoad, setFirstLoad] = useState<boolean>(true);
|
|
237
|
-
const [commuteLocation, setCommuteLocation] = useState<any | null>(
|
|
238
|
-
const [selectedFilters, setSelectedFilters] = useState<Record<string, any>>(
|
|
237
|
+
const [commuteLocation, setCommuteLocation] = useState<any | null>(null);
|
|
238
|
+
const [selectedFilters, setSelectedFilters] = useState<Record<string, any>>({});
|
|
239
|
+
const [hasMounted, setHasMounted] = useState(false);
|
|
240
|
+
|
|
241
|
+
// Load from localStorage/URL after mount to avoid hydration mismatch
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
if (typeof window !== 'undefined') {
|
|
244
|
+
const storedMapItems = getStorageObject(localStorageKey + 'mapItems', []) || [];
|
|
245
|
+
const storedSortSetting = getStorageObject(localStorageKey + 'sortSetting', { field: 'position', type: 'asc' }) || { field: 'position', type: 'asc' };
|
|
246
|
+
const storedCommuteLocation = getStorageObject(localStorageKey + 'commuteLocation');
|
|
247
|
+
|
|
248
|
+
setMapItems(storedMapItems);
|
|
249
|
+
setSortSetting(storedSortSetting);
|
|
250
|
+
if (storedCommuteLocation) setCommuteLocation(storedCommuteLocation);
|
|
251
|
+
|
|
252
|
+
// Load filters and query
|
|
253
|
+
if (!resetFilters) {
|
|
254
|
+
setSelectedFilters(firstLoadFilters());
|
|
255
|
+
setQuery(firstLoadQuery());
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
setHasMounted(true);
|
|
259
|
+
}
|
|
260
|
+
}, [localStorageKey]);
|
|
239
261
|
const [filterOptions, setFilterOptions] = useState<any>();
|
|
240
262
|
const [recruiters, setRecruiters] = useState<Record<number, Recruiter>>({});
|
|
241
263
|
const [filterDialogIsOpen, setFilterDialogIsOpen] = useState<boolean>(false);
|