@@ -48,10 +48,13 @@ import {
4848 SEND_EMAILS ,
4949 TOTAL_ORG_SUMMARY ,
5050 TOTAL_CONSTRUCTION_SUMMARY ,
51+ PR_PROMOTIONS ,
52+ BLUE_SQUARE_EMAIL_MANAGEMENT ,
53+ JOB_ANALYTICS_REPORT ,
5154} from '../../languages/en/ui' ;
5255import Logout from '../Logout/Logout' ;
5356import '../../App.css' ;
54- import './Header.css' ;
57+ import styles from './Header.module .css' ;
5558import hasPermission , { cantUpdateDevAdminDetails } from '../../utils/permissions' ;
5659import {
5760 getUnreadUserNotifications ,
@@ -62,6 +65,8 @@ import DarkModeButton from './DarkModeButton';
6265import BellNotification from './BellNotification' ;
6366import { getUserProfile } from '../../actions/userProfile' ;
6467import PermissionWatcher from '../Auth/PermissionWatcher' ;
68+ import DisplayBox from '../PRPromotions/DisplayBox' ;
69+ import PropTypes from 'prop-types' ;
6570
6671export function Header ( props ) {
6772 const location = useLocation ( ) ;
@@ -75,6 +80,7 @@ export function Header(props) {
7580 const [ popup , setPopup ] = useState ( false ) ;
7681 const [ isAuthUser , setIsAuthUser ] = useState ( true ) ;
7782 const [ isAckLoading , setIsAckLoading ] = useState ( false ) ;
83+ const [ showPromotionsPopup , setShowPromotionsPopup ] = useState ( false ) ;
7884
7985 const ALLOWED_ROLES_TO_INTERACT = useMemo ( ( ) => [ 'Owner' , 'Administrator' ] , [ ] ) ;
8086 const canInteractWithViewingUser = useMemo (
@@ -92,15 +98,17 @@ export function Header(props) {
9298 'getWeeklySummaries' ,
9399 ! isAuthUser ,
94100 ) ;
101+ const canGetWeeklyVolunteerSummary = props . hasPermission ( 'getWeeklySummaries' ) ;
102+ const canGetJobAnalytics = props . hasPermission ( 'getJobReports' ) ;
95103
96104
97- const canGetWeeklyVolunteerSummary = props . hasPermission ( 'getWeeklySummaries' , ! isAuthUser ) ;
98105 // Users
99106 const canAccessUserManagement =
100107 props . hasPermission ( 'postUserProfile' , ! isAuthUser ) ||
101108 props . hasPermission ( 'deleteUserProfile' , ! isAuthUser ) ||
102109 props . hasPermission ( 'changeUserStatus' , ! isAuthUser ) ||
103- props . hasPermission ( 'getUserProfiles' , ! isAuthUser ) ;
110+ props . hasPermission ( 'getUserProfiles' , ! isAuthUser ) ||
111+ props . hasPermission ( 'setFinalDay' , ! isAuthUser && canInteractWithViewingUser ) ;
104112
105113 // Badges
106114 const canAccessBadgeManagement =
@@ -144,6 +152,7 @@ export function Header(props) {
144152 props . hasPermission ( 'deleteRole' , ! isAuthUser ) ||
145153 props . hasPermission ( 'putUserProfilePermissions' , ! isAuthUser ) ;
146154
155+ const canAccessBlueSquareEmailManagement = props . hasPermission ( 'resendBlueSquareAndSummaryEmails' , ! isAuthUser ) ;
147156 const userId = user . userid ;
148157 const [ isModalVisible , setModalVisible ] = useState ( false ) ;
149158 const [ modalContent , setModalContent ] = useState ( '' ) ;
@@ -185,6 +194,44 @@ export function Header(props) {
185194 } ;
186195 } , [ user . userid , props . auth . firstName ] ) ;
187196
197+ // Debugging Enhancement: Monitor window resize events for responsive testing
198+ useEffect ( ( ) => {
199+ const handleResize = ( ) => {
200+ const currentWidth = window . innerWidth ;
201+ // eslint-disable-next-line no-console
202+ console . log ( `[Header Debug] Window resized to: ${ currentWidth } px` ) ;
203+
204+ // Log breakpoint information for debugging
205+ if ( currentWidth >= 1728 ) {
206+ // eslint-disable-next-line no-console
207+ console . log ( `[Header Debug] Breakpoint: Large screen (90%+) - Owner message below timer` ) ;
208+ } else if ( currentWidth >= 1400 ) {
209+ // eslint-disable-next-line no-console
210+ console . log ( `[Header Debug] Breakpoint: Desktop - Centered layout` ) ;
211+ } else if ( currentWidth >= 1200 ) {
212+ // eslint-disable-next-line no-console
213+ console . log ( `[Header Debug] Breakpoint: Medium desktop - Centered layout` ) ;
214+ } else if ( currentWidth >= 768 ) {
215+ // eslint-disable-next-line no-console
216+ console . log ( `[Header Debug] Breakpoint: Tablet - Stacked layout` ) ;
217+ } else {
218+ // eslint-disable-next-line no-console
219+ console . log ( `[Header Debug] Breakpoint: Mobile - Compact vertical layout` ) ;
220+ }
221+ } ;
222+
223+ // Log initial window size
224+ handleResize ( ) ;
225+
226+ // Add resize event listener
227+ window . addEventListener ( 'resize' , handleResize ) ;
228+
229+ // Cleanup event listener on component unmount
230+ return ( ) => {
231+ window . removeEventListener ( 'resize' , handleResize ) ;
232+ } ;
233+ } , [ ] ) ;
234+
188235 useEffect ( ( ) => {
189236 if ( props . auth . isAuthenticated ) {
190237 props . getHeaderData ( props . auth . user . userid ) ;
@@ -200,10 +247,10 @@ export function Header(props) {
200247 props . getAllRoles ( ) ;
201248 }
202249 // Fetch unread notification
203- if ( isAuthenticated && userId ) {
204- dispatch ( getUnreadUserNotifications ( userId ) ) ;
250+ if ( isAuthenticated && displayUserId ) {
251+ dispatch ( getUnreadUserNotifications ( displayUserId ) ) ;
205252 }
206- } , [ ] ) ;
253+ } , [ isAuthenticated , displayUserId , roles . length ] ) ;
207254
208255 useEffect ( ( ) => {
209256 if ( props . notification ?. error ) {
@@ -333,27 +380,36 @@ export function Header(props) {
333380
334381 const viewingUser = JSON . parse ( window . sessionStorage . getItem ( 'viewingUser' ) ) ;
335382 return (
336- < div className = { `header-wrapper ${ darkMode ? ' dark-mode' : '' } ` } data-testid = "header" >
337- < Navbar className = " py-3 navbar" color = "dark" dark expand = "md" >
383+ < div className = { `${ styles . headerWrapper } ${ darkMode ? ` ${ styles . darkMode } ` : '' } ` } data-testid = "header" >
384+ < Navbar className = { ` py-3 ${ styles . navbar } ` } color = "dark" dark expand = "md" >
338385 { logoutPopup && < Logout open = { logoutPopup } setLogoutPopup = { setLogoutPopup } /> }
339- < div
340- className = "timer-message-section"
341- style = { user . role === 'Owner' ? { marginRight : '0.5rem' } : { marginRight : '1rem' } }
342- >
343- { isAuthenticated && < Timer darkMode = { darkMode } /> }
344- { isAuthenticated && (
345- < div className = "owner-message" >
346- < OwnerMessage />
347- </ div >
348- ) }
349- </ div >
350- < NavbarToggler onClick = { toggle } />
351- { isAuthenticated && (
352- < Collapse isOpen = { isOpen } navbar >
353- < Nav className = "ml-auto nav-links d-flex" navbar >
354- < div
355- className = "d-flex justify-content-center align-items-center"
356- style = { { width : '100%' } }
386+ { showPromotionsPopup &&
387+ ( < DisplayBox onClose = { ( ) => setShowPromotionsPopup ( false ) } /> ) }
388+
389+ < div className = "d-flex justify-content-between align-items-center w-100 p-3" >
390+ { /* Left Component - Timer */ }
391+ < div className = { styles . leftSection } >
392+ { isAuthenticated && < Timer darkMode = { darkMode } /> }
393+ </ div >
394+
395+ { /* Center Component - Owner Message */ }
396+ < div className = { `${ styles . centerSection } text-center flex-grow-1` } >
397+ { isAuthenticated && (
398+ < div className = { styles . ownerMessage } >
399+ < OwnerMessage />
400+ </ div >
401+ ) }
402+ </ div >
403+
404+ { /* Right Component - Navigation */ }
405+ < div className = { styles . rightSection } >
406+ < NavbarToggler onClick = { toggle } />
407+ { isAuthenticated && (
408+ < Collapse isOpen = { isOpen } navbar >
409+ < Nav className = { `${ styles . navLinks } d-flex` } navbar >
410+ < div
411+ className = "d-flex justify-content-center align-items-center"
412+ style = { { width : '100%' } }
357413 >
358414 { canUpdateTask && (
359415 < NavItem className = "responsive-spacing" >
@@ -453,6 +509,11 @@ export function Header(props) {
453509 { TOTAL_ORG_SUMMARY }
454510 </ DropdownItem >
455511 ) }
512+ { canGetJobAnalytics && (
513+ < DropdownItem tag = { Link } to = "/application/analytics" className = { fontColor } >
514+ { JOB_ANALYTICS_REPORT }
515+ </ DropdownItem >
516+ ) }
456517 < DropdownItem tag = { Link } to = "/teamlocations" className = { fontColor } disabled = { headerDisabled } >
457518 { TEAM_LOCATIONS }
458519 </ DropdownItem >
@@ -464,6 +525,9 @@ export function Header(props) {
464525 >
465526 { TOTAL_CONSTRUCTION_SUMMARY }
466527 </ DropdownItem >
528+ < DropdownItem onClick = { ( ) => setShowPromotionsPopup ( true ) } className = { fontColor } >
529+ { PR_PROMOTIONS }
530+ </ DropdownItem >
467531 </ DropdownMenu >
468532 </ UncontrolledDropdown >
469533 ) : (
@@ -482,7 +546,8 @@ export function Header(props) {
482546 canAccessTeams ||
483547 canAccessPopups ||
484548 canAccessSendEmails ||
485- canAccessPermissionsManagement ) && (
549+ canAccessPermissionsManagement ||
550+ canAccessBlueSquareEmailManagement ) && (
486551 < UncontrolledDropdown nav inNavbar className = "responsive-spacing" >
487552 < DropdownToggle nav caret >
488553 < span className = "dashboard-text-link" > { OTHER_LINKS } </ span >
@@ -530,6 +595,15 @@ export function Header(props) {
530595 < DropdownItem tag = { Link } to = "/pr-dashboard/overview" className = { fontColor } disabled = { headerDisabled } >
531596 PR Team Analytics
532597 </ DropdownItem >
598+ { canAccessBlueSquareEmailManagement && (
599+ < DropdownItem
600+ tag = { Link }
601+ to = "/bluesquare-email-management"
602+ className = { fontColor }
603+ >
604+ { BLUE_SQUARE_EMAIL_MANAGEMENT }
605+ </ DropdownItem >
606+ ) }
533607 </ DropdownMenu >
534608 </ UncontrolledDropdown >
535609 ) }
@@ -595,6 +669,8 @@ export function Header(props) {
595669 </ Nav >
596670 </ Collapse >
597671 ) }
672+ </ div >
673+ </ div >
598674 </ Navbar >
599675 { ! isAuthUser && (
600676 < PopUpBar
@@ -660,7 +736,28 @@ const mapStateToProps = state => ({
660736 notification : state . notification ,
661737 darkMode : state . theme . darkMode ,
662738} ) ;
663-
739+ Header . propTypes = {
740+ hasPermission : PropTypes . func . isRequired ,
741+ auth : PropTypes . shape ( {
742+ isAuthenticated : PropTypes . bool ,
743+ user : PropTypes . shape ( {
744+ userid : PropTypes . oneOfType ( [ PropTypes . string , PropTypes . number ] ) ,
745+ role : PropTypes . string
746+ } ) ,
747+ firstName : PropTypes . string ,
748+ profilePic : PropTypes . string
749+ } ) ,
750+ getHeaderData : PropTypes . func ,
751+ getAllRoles : PropTypes . func ,
752+ getWeeklySummaries : PropTypes . func ,
753+ role : PropTypes . shape ( {
754+ roles : PropTypes . array
755+ } ) ,
756+ notification : PropTypes . object ,
757+ userProfile : PropTypes . object ,
758+ darkMode : PropTypes . bool ,
759+ taskEditSuggestionCount : PropTypes . number ,
760+ } ;
664761export default connect ( mapStateToProps , {
665762 getHeaderData,
666763 getAllRoles,
0 commit comments