Skip to content

Commit b826a44

Browse files
authored
Merge pull request #4623 from atarrh/develop
[Issue #WV-2162]: Adding Office Banner Above Header
2 parents 4219e8e + 16b55bb commit b826a44

File tree

3 files changed

+216
-0
lines changed

3 files changed

+216
-0
lines changed

src/js/common/stores/AppObservableStore.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ const nonFluxState = {
6969
showClaimProfileWithOtherWaysModal: false,
7070
showCompleteYourProfileModal: false,
7171
showNotificationBannerAboveHeader: false,
72+
showOfficeBannerAboveHeader: false,
7273
showEditAddressButton: false,
7374
showElectionsWithOrganizationVoterGuidesModal: false,
7475
showHeader: 0,
@@ -296,6 +297,15 @@ export default {
296297
messageService.sendMessage('state updated showNotificationBannerAboveHeader');
297298
},
298299

300+
getShowOfficeBannerAboveHeader () {
301+
return nonFluxState.showOfficeBannerAboveHeader;
302+
},
303+
304+
setShowOfficeBannerAboveHeader (show) {
305+
nonFluxState.showOfficeBannerAboveHeader = show;
306+
messageService.sendMessage('state updated showOfficeBannerAboveHeader');
307+
},
308+
299309
getWeVoteRootURL () {
300310
const { location: { hostname, origin } } = window;
301311
if (hostname === 'localhost' || hostname === 'quality.wevote.us' || hostname === 'wevotedeveloper.com') {

src/js/components/Navigation/Header.jsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const HeaderBackToVoterGuides = React.lazy(() => import(/* webpackChunkName: 'He
2626
const HeaderBarModals = React.lazy(() => import(/* webpackChunkName: 'HeaderBarModals' */ './HeaderBarModals'));
2727
const HowItWorksModal = React.lazy(() => import(/* webpackChunkName: 'HowItWorksModal' */ '../CompleteYourProfile/HowItWorksModal'));
2828
const NotificationBannerAboveHeader = React.lazy(() => import(/* webpackChunkName: 'NotificationBannerAboveHeader' */ './NotificationBannerAboveHeader'));
29+
const OfficeBannerAboveHeader = React.lazy(() => import(/* webpackChunkName: 'OfficeBannerAboveHeader' */ './OfficeBannerAboveHeader'));
2930
const OrganizationModal = React.lazy(() => import(/* webpackChunkName: 'OrganizationModal' */ '../VoterGuide/OrganizationModal'));
3031
const PositionDrawer = React.lazy(() => import(/* webpackChunkName: 'PositionDrawer' */ '../Ballot/PositionDrawer'));
3132
const SharedItemModal = React.lazy(() => import(/* webpackChunkName: 'SharedItemModal' */ '../Share/SharedItemModal'));
@@ -43,6 +44,7 @@ export default class Header extends Component {
4344
sharedItemCode: '',
4445
showHowItWorksModal: false,
4546
showNotificationBannerAboveHeader: AppObservableStore.getShowNotificationBannerAboveHeader(),
47+
showOfficeBannerAboveHeader: AppObservableStore.getShowOfficeBannerAboveHeader(),
4648
showVoterPlanModal: false,
4749
showOrganizationModal: false,
4850
showPositionDrawer: false,
@@ -119,6 +121,7 @@ export default class Header extends Component {
119121
showPositionDrawer: AppObservableStore.showPositionDrawer(),
120122
showSharedItemModal: AppObservableStore.showSharedItemModal(),
121123
showNotificationBannerAboveHeader: AppObservableStore.getShowNotificationBannerAboveHeader(),
124+
showOfficeBannerAboveHeader: AppObservableStore.getShowOfficeBannerAboveHeader(),
122125
});
123126
}
124127

@@ -182,13 +185,15 @@ export default class Header extends Component {
182185
render () {
183186
renderLog('Header'); // Set LOG_RENDER_EVENTS to log all renders
184187
const { showNotificationBannerAboveHeader } = this.state;
188+
const { showOfficeBannerAboveHeader } = this.state;
185189

186190
if (this.hideHeader()) {
187191
renderLog('Header hidden');
188192
return null;
189193
}
190194
const pathname = normalizedHref();
191195
const isCandidatePage = /^\/[-a-z0-9]+\/-\/?$/.test(pathname);
196+
const isOfficePage = /^\/office\/[a-z0-9]+\/?$/.test(pathname);
192197
const { hideHeader, params } = this.props;
193198
// console.log('Header global.weVoteGlobalHistory', global.weVoteGlobalHistory);
194199
const {
@@ -488,6 +493,13 @@ export default class Header extends Component {
488493
</Suspense>
489494
</NotificationBannerAboveHeaderWrapper>
490495
)}
496+
{(showOfficeBannerAboveHeader && isOfficePage) && (
497+
<OfficeBannerAboveHeaderWrapper>
498+
<Suspense fallback={<></>}>
499+
<OfficeBannerAboveHeader />
500+
</Suspense>
501+
</OfficeBannerAboveHeaderWrapper>
502+
)}
491503
{(headerNotVisible || hideHeader) ? (
492504
<>
493505
<Suspense fallback={<></>}>
@@ -587,3 +599,8 @@ const NotificationBannerAboveHeaderWrapper = styled.div`
587599
justify-content: center;
588600
padding: 0 16px;
589601
`;
602+
const OfficeBannerAboveHeaderWrapper = styled.div`
603+
display: flex;
604+
justify-content: center;
605+
padding: 0 16px;
606+
`;
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
import { Edit } from '@mui/icons-material';
2+
import React, { useCallback, useEffect, useState } from 'react';
3+
import TagManager from 'react-gtm-module';
4+
import { useHistory } from 'react-router-dom';
5+
import styled from 'styled-components';
6+
import lookupPageNameAndPageTypeDict, { getPageDetails } from '../../utils/lookupPageNameAndPageTypeDict';
7+
import normalizedImagePath from '../../common/utils/normalizedImagePath';
8+
import VoterStore from '../../stores/VoterStore';
9+
import AppObservableStore, { messageService } from '../../common/stores/AppObservableStore';
10+
import DesignTokenColors from '../../common/components/Style/DesignTokenColors';
11+
import useVoterCanEditPolitician from '../../hooks/useVoterCanEditPolitician';
12+
import PoliticianStore from '../../common/stores/PoliticianStore';
13+
import HeaderLogoImage from './HeaderLogoImage';
14+
import {WeVoteLogo} from '../Style/SimpleProcessStyles';
15+
16+
const chosenSiteLogoUrl = '../../../img/global/svg-icons/we-vote-icon-square-color.svg';
17+
18+
export default function OfficeBannerAboveHeader() {
19+
const voterCanEditPoliticianProfile = useVoterCanEditPolitician();
20+
const [politicianWeVoteId, setPoliticianWeVoteId] = useState(AppObservableStore.getPoliticianWeVoteIdBeingViewed());
21+
22+
const history = useHistory();
23+
const handleBallotButtonClick = () => history.push('/ballot')
24+
25+
const onAppObservableStoreChange = useCallback(() => {
26+
if (AppObservableStore.getPoliticianWeVoteIdBeingViewed()) {
27+
setPoliticianWeVoteId(AppObservableStore.getPoliticianWeVoteIdBeingViewed());
28+
// console.log('PoliticianSelfEditDrawer onAppObservableStoreChange politicianWeVoteId:', AppObservableStore.getPoliticianWeVoteIdBeingViewed());
29+
}
30+
}, [setPoliticianWeVoteId]);
31+
32+
const closeEditBar = (buttonId) => {
33+
AppObservableStore.setShowOfficeBannerAboveHeader(false);
34+
const dataLayerObject = {
35+
actionDetails: {
36+
actionType: 'closeModal',
37+
buttonId,
38+
},
39+
event: 'action',
40+
pageDetails: getPageDetails(),
41+
userDetails: VoterStore.getAnalyticsUserDetails(),
42+
};
43+
TagManager.dataLayer({ dataLayer: dataLayerObject });
44+
};
45+
46+
useEffect(() => {
47+
const appStateSubscription = messageService.getMessage().subscribe(onAppObservableStoreChange);
48+
onAppObservableStoreChange();
49+
return () => {
50+
setPoliticianWeVoteId('');
51+
appStateSubscription.unsubscribe();
52+
};
53+
}, [onAppObservableStoreChange]);
54+
55+
return (
56+
<OfficeBannerAboveHeaderContainer>
57+
<BannerTextContainer>
58+
<div style={{display: "flex", gap: "10px"}}>
59+
<WeVoteLogo src={normalizedImagePath(chosenSiteLogoUrl)} className="u-show-desktop-tablet" height="36" width="36" />
60+
<BannerIntroTextMobile className="u-show-mobile">Welcome to WeVote, your personalized voter guide!</BannerIntroTextMobile>
61+
<BannerIntroTextDesktop className="u-show-desktop-tablet">Welcome to WeVote, your personalized voter guide:</BannerIntroTextDesktop>
62+
</div>
63+
<BannerElement>
64+
{/*{' '}*/}
65+
<BannerElementTitle>&#x1F5F3;&ensp; VOTE YOUR VALUES</BannerElementTitle>
66+
<BannerElementText>Get personalized ballot recommendations based on your interests and trusted connections.</BannerElementText>
67+
</BannerElement>
68+
<BannerElement>
69+
<BannerElementTitle>&#x1F91D;&ensp; SHARE & MOBILIZE</BannerElementTitle>
70+
<BannerElementText>Choose the candidates you support or oppose, and tell your friends.</BannerElementText>
71+
</BannerElement>
72+
<BannerElement>
73+
<BannerElementTitle>&#x1F50D;&ensp; SIMPLIFY VOTING</BannerElementTitle>
74+
<BannerElementText>Use clear, nonpartisan tools to understand your ballot and take action confidently.</BannerElementText>
75+
</BannerElement>
76+
</BannerTextContainer>
77+
<VerticalCenter className="u-show-desktop-tablet"><VerticalLine/></VerticalCenter>
78+
<ButtonHolder>
79+
<BallotButton onClick={handleBallotButtonClick}>
80+
<BannerIntroTextMobile className="u-show-mobile">View your full ballot to get started</BannerIntroTextMobile>
81+
<BannerIntroTextDesktop className="u-show-desktop-tablet">View your full ballot to get started</BannerIntroTextDesktop>
82+
</BallotButton>
83+
</ButtonHolder>
84+
<ButtonHolder>
85+
<CloseButton id="closeOfficeBanner" className="u-show-desktop-tablet" onClick={() => closeEditBar('closeOfficeBanner')}></CloseButton>
86+
</ButtonHolder>
87+
</OfficeBannerAboveHeaderContainer>
88+
);
89+
}
90+
91+
const VerticalCenter = styled.div`
92+
margin-inline: 2%;
93+
display: flex;
94+
flex-direction: column;
95+
justify-content: center;
96+
`;
97+
98+
const OfficeBannerAboveHeaderContainer = styled.div`
99+
background: ${DesignTokenColors.secondary800};
100+
color: ${DesignTokenColors.whiteUI};
101+
display: flex;
102+
font-size: 14px;
103+
// flex-direction: column; // only on mobile!
104+
// align-items: center; // only on mobile!
105+
margin-left: -16px;
106+
margin-right: -16px;
107+
padding: 8px 16px;
108+
width: 100vw;
109+
`;
110+
111+
const BannerTextContainer = styled.div`
112+
display: flex;
113+
gap: 12px;
114+
flex-wrap: wrap;
115+
flex-direction: column;
116+
align-items: flex-start;
117+
padding-bottom: 12px;
118+
`;
119+
120+
const BannerIntroTextDesktop = styled('span')`
121+
font-size: 18px;
122+
font-weight: 500;
123+
margin-bottom: 8px;
124+
margin-top: 8px;
125+
`;
126+
127+
const BannerIntroTextMobile = styled('span')`
128+
`;
129+
130+
const BannerElementTitle = styled.div`
131+
font-weight: 500;
132+
margin-bottom: 2px;
133+
margin-left: 1em;
134+
`;
135+
136+
const BannerElementText = styled.div`
137+
margin-left: 2.5em;
138+
`;
139+
140+
const BannerElement = styled('div')`
141+
`;
142+
143+
const VerticalLine = styled('div')`
144+
border-left: 1px solid rgba(105, 105, 105, 0.6);
145+
height: 90%;
146+
margin-inline: 5%;
147+
margin: 5px;
148+
`;
149+
150+
const ButtonHolder = styled.div`
151+
`;
152+
153+
const BallotButton = styled.button`
154+
background: ${DesignTokenColors.whiteUI};
155+
border: none;
156+
border-radius: 24px;
157+
color: ${DesignTokenColors.secondary800};
158+
cursor: pointer;
159+
font-weight: 500;
160+
padding: 8px 16px;
161+
margin-top: 32px;
162+
163+
@media (max-width: 800px) {
164+
margin-top: 8px;
165+
}
166+
@media (max-width: 600px) {
167+
width: auto;
168+
order: 1;
169+
}
170+
`;
171+
172+
const CloseButton = styled.button`
173+
background: transparent;
174+
border: none;
175+
color: ${DesignTokenColors.whiteUI};
176+
cursor: pointer;
177+
font-size: 20px;
178+
margin-left: 16px;
179+
180+
display: flex;
181+
flex-direction: row;
182+
justify-content: center;
183+
184+
@media (max-width: 600px) {
185+
order: 2;
186+
margin-left: 8px;
187+
}
188+
`;
189+

0 commit comments

Comments
 (0)