@@ -21,6 +21,7 @@ import {
2121} from '@/components/search-map/hooks' ;
2222import MapLayersPanel from '@/components/search-map/MapLayersPanel' ;
2323import { selectedWildfireIcon } from '@/components/search-map/styles/icons' ;
24+ import feedBackIcon from '@/images/icons/feedback-icon.svg' ;
2425import searchResultsStore from '@/store/searchResults' ;
2526import {
2627 FireEvacuationPreview ,
@@ -30,7 +31,7 @@ import {
3031import FilterButtonLabel from '@/components/search-map/FilterButtonLabel' ;
3132import FilterMenuSearchMap from '@/components/search/filters/FilterMenuSearchMap' ;
3233import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
33- import { faSliders } from '@fortawesome/free-solid-svg-icons' ;
34+ import { faSliders , faExternalLink } from '@fortawesome/free-solid-svg-icons' ;
3435import { Button , ProgressBar } from 'react-bootstrap' ;
3536import { trackClickEvent } from '@shared/utils' ;
3637import {
@@ -48,6 +49,7 @@ import {
4849 LEGACY_MAP_LINK ,
4950 WILDFIRE_LOCATION_MIN_ZOOM ,
5051} from '@/components/search-map/constants' ;
52+ import { EXTERNAL_LINKS } from '@/constants/urls' ;
5153import RecreationSuggestionForm from '@/components/recreation-suggestion-form/RecreationSuggestionForm' ;
5254import type Feature from 'ol/Feature' ;
5355import MapDisclaimerModal from '@/components/search-map/MapDisclaimerModal' ;
@@ -88,6 +90,7 @@ const SearchMap = (searchViewControlsProps: SearchViewControlsProps) => {
8890 useState ( true ) ;
8991 const [ isWildfireLocationEnabled , setIsWildfireLocationEnabled ] =
9092 useState ( true ) ;
93+ const [ isFeedbackCardVisible , setIsFeedbackCardVisible ] = useState ( false ) ;
9194 const selectedFilterCount = filterChips . length ;
9295
9396 // Current search results and the focused resource (if any),
@@ -106,6 +109,15 @@ const SearchMap = (searchViewControlsProps: SearchViewControlsProps) => {
106109 const popupRef = useRef < HTMLDivElement | null > ( null ) ;
107110 const overlayRef = useRef < Overlay | null > ( null ) ;
108111
112+ const setFeedbackCardCookie = ( ) => {
113+ Cookies . set ( 'hidemap-feedback-card' , 'true' , { expires : 30 } ) ; // expires in 1 month
114+ } ;
115+
116+ const closeFeedbackCard = ( ) => {
117+ setIsFeedbackCardVisible ( false ) ;
118+ setFeedbackCardCookie ( ) ;
119+ } ;
120+
109121 useEffect ( ( ) => {
110122 if ( ! popupRef . current || ! mapRef . current ) return ;
111123 const overlay = new Overlay ( {
@@ -122,6 +134,18 @@ const SearchMap = (searchViewControlsProps: SearchViewControlsProps) => {
122134 } ;
123135 } , [ mapRef , popupRef ] ) ;
124136
137+ // Show the feedback card after 2 minutes if the user hasn't dismissed it before
138+ useEffect ( ( ) => {
139+ const timer = setTimeout ( ( ) => {
140+ const hideFeedbackCard = Cookies . get ( 'hidemap-feedback-card' ) ;
141+ if ( ! hideFeedbackCard ) {
142+ setIsFeedbackCardVisible ( true ) ;
143+ }
144+ } , 120000 ) ;
145+
146+ return ( ) => clearTimeout ( timer ) ;
147+ } , [ ] ) ;
148+
125149 const { layer : clusteredRecreationFeatureLayer , innerSource : pinSource } =
126150 useClusteredRecreationFeatureLayer ( allRelevantIds , mapRef , {
127151 clusterOptions : CLUSTER_OPTIONS ,
@@ -366,6 +390,16 @@ const SearchMap = (searchViewControlsProps: SearchViewControlsProps) => {
366390 }
367391 } ;
368392
393+ const handleFeedbackClick = ( ) => {
394+ trackClickEvent ( {
395+ category : 'Feedback' ,
396+ action : 'Map' ,
397+ name : `Map - Feedback card` ,
398+ } ) ;
399+ window . open ( EXTERNAL_LINKS . FEEDBACK_FORM , '_blank' , 'noopener,noreferrer' ) ;
400+ setFeedbackCardCookie ( ) ;
401+ } ;
402+
369403 return (
370404 < div
371405 className = "search-map-container d-flex flex-column vh-100"
@@ -404,6 +438,36 @@ const SearchMap = (searchViewControlsProps: SearchViewControlsProps) => {
404438 Link to legacy map
405439 </ a >
406440 </ div >
441+ { isFeedbackCardVisible && (
442+ < div className = "feedback-card rounded-2" >
443+ < button
444+ type = "button"
445+ className = "close-button"
446+ onClick = { ( ) => closeFeedbackCard ( ) }
447+ aria-label = "Close feedback card"
448+ data-testid = "feedback-card-close-button"
449+ >
450+ ×
451+ </ button >
452+ < p className = "mb-0" >
453+ < img src = { feedBackIcon } alt = "Feedback" className = "me-2" />
454+ < strong > We'd love to hear from you</ strong >
455+ </ p >
456+ < p className = "mb-0 ms-4" >
457+ Your feedback helps us improve your experience on our website.
458+ Survey takes 1-2 minutes.
459+ </ p >
460+ < button
461+ type = "button"
462+ className = "btn btn-outline-light btn-sm w-100 btn-thin mt-2"
463+ onClick = { handleFeedbackClick }
464+ data-testid = "feedback-card-survey-button"
465+ >
466+ Take Survey{ ' ' }
467+ < FontAwesomeIcon icon = { faExternalLink } className = "ms-1" />
468+ </ button >
469+ </ div >
470+ ) }
407471 </ div >
408472 < div className = "search-map-controls" >
409473 < div className = "map-search-form" >
0 commit comments