Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/js/common/stores/AppObservableStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const nonFluxState = {
showClaimProfileWithOtherWaysModal: false,
showCompleteYourProfileModal: false,
showNotificationBannerAboveHeader: false,
showOfficeBannerAboveHeader: false,
showEditAddressButton: false,
showElectionsWithOrganizationVoterGuidesModal: false,
showHeader: 0,
Expand Down Expand Up @@ -296,6 +297,15 @@ export default {
messageService.sendMessage('state updated showNotificationBannerAboveHeader');
},

getShowOfficeBannerAboveHeader () {
return nonFluxState.showOfficeBannerAboveHeader;
},

setShowOfficeBannerAboveHeader (show) {
nonFluxState.showOfficeBannerAboveHeader = show;
messageService.sendMessage('state updated showOfficeBannerAboveHeader');
},

getWeVoteRootURL () {
const { location: { hostname, origin } } = window;
if (hostname === 'localhost' || hostname === 'quality.wevote.us' || hostname === 'wevotedeveloper.com') {
Expand Down
17 changes: 17 additions & 0 deletions src/js/components/Navigation/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const HeaderBackToVoterGuides = React.lazy(() => import(/* webpackChunkName: 'He
const HeaderBarModals = React.lazy(() => import(/* webpackChunkName: 'HeaderBarModals' */ './HeaderBarModals'));
const HowItWorksModal = React.lazy(() => import(/* webpackChunkName: 'HowItWorksModal' */ '../CompleteYourProfile/HowItWorksModal'));
const NotificationBannerAboveHeader = React.lazy(() => import(/* webpackChunkName: 'NotificationBannerAboveHeader' */ './NotificationBannerAboveHeader'));
const OfficeBannerAboveHeader = React.lazy(() => import(/* webpackChunkName: 'OfficeBannerAboveHeader' */ './OfficeBannerAboveHeader'));
const OrganizationModal = React.lazy(() => import(/* webpackChunkName: 'OrganizationModal' */ '../VoterGuide/OrganizationModal'));
const PositionDrawer = React.lazy(() => import(/* webpackChunkName: 'PositionDrawer' */ '../Ballot/PositionDrawer'));
const SharedItemModal = React.lazy(() => import(/* webpackChunkName: 'SharedItemModal' */ '../Share/SharedItemModal'));
Expand All @@ -43,6 +44,7 @@ export default class Header extends Component {
sharedItemCode: '',
showHowItWorksModal: false,
showNotificationBannerAboveHeader: AppObservableStore.getShowNotificationBannerAboveHeader(),
showOfficeBannerAboveHeader: AppObservableStore.getShowOfficeBannerAboveHeader(),
showVoterPlanModal: false,
showOrganizationModal: false,
showPositionDrawer: false,
Expand Down Expand Up @@ -119,6 +121,7 @@ export default class Header extends Component {
showPositionDrawer: AppObservableStore.showPositionDrawer(),
showSharedItemModal: AppObservableStore.showSharedItemModal(),
showNotificationBannerAboveHeader: AppObservableStore.getShowNotificationBannerAboveHeader(),
showOfficeBannerAboveHeader: AppObservableStore.getShowOfficeBannerAboveHeader(),
});
}

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

if (this.hideHeader()) {
renderLog('Header hidden');
return null;
}
const pathname = normalizedHref();
const isCandidatePage = /^\/[-a-z0-9]+\/-\/?$/.test(pathname);
const isOfficePage = /^\/office\/[a-z0-9]+\/?$/.test(pathname);
const { hideHeader, params } = this.props;
// console.log('Header global.weVoteGlobalHistory', global.weVoteGlobalHistory);
const {
Expand Down Expand Up @@ -488,6 +493,13 @@ export default class Header extends Component {
</Suspense>
</NotificationBannerAboveHeaderWrapper>
)}
{(showOfficeBannerAboveHeader && isOfficePage) && (
<OfficeBannerAboveHeaderWrapper>
<Suspense fallback={<></>}>
<OfficeBannerAboveHeader />
</Suspense>
</OfficeBannerAboveHeaderWrapper>
)}
{(headerNotVisible || hideHeader) ? (
<>
<Suspense fallback={<></>}>
Expand Down Expand Up @@ -587,3 +599,8 @@ const NotificationBannerAboveHeaderWrapper = styled.div`
justify-content: center;
padding: 0 16px;
`;
const OfficeBannerAboveHeaderWrapper = styled.div`
display: flex;
justify-content: center;
padding: 0 16px;
`;
189 changes: 189 additions & 0 deletions src/js/components/Navigation/OfficeBannerAboveHeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { Edit } from '@mui/icons-material';
import React, { useCallback, useEffect, useState } from 'react';
import TagManager from 'react-gtm-module';
import { useHistory } from 'react-router-dom';
import styled from 'styled-components';
import lookupPageNameAndPageTypeDict, { getPageDetails } from '../../utils/lookupPageNameAndPageTypeDict';
import normalizedImagePath from '../../common/utils/normalizedImagePath';
import VoterStore from '../../stores/VoterStore';
import AppObservableStore, { messageService } from '../../common/stores/AppObservableStore';
import DesignTokenColors from '../../common/components/Style/DesignTokenColors';
import useVoterCanEditPolitician from '../../hooks/useVoterCanEditPolitician';
import PoliticianStore from '../../common/stores/PoliticianStore';
import HeaderLogoImage from './HeaderLogoImage';
import {WeVoteLogo} from '../Style/SimpleProcessStyles';

const chosenSiteLogoUrl = '../../../img/global/svg-icons/we-vote-icon-square-color.svg';

export default function OfficeBannerAboveHeader() {
const voterCanEditPoliticianProfile = useVoterCanEditPolitician();
const [politicianWeVoteId, setPoliticianWeVoteId] = useState(AppObservableStore.getPoliticianWeVoteIdBeingViewed());

const history = useHistory();
const handleBallotButtonClick = () => history.push('/ballot')

const onAppObservableStoreChange = useCallback(() => {
if (AppObservableStore.getPoliticianWeVoteIdBeingViewed()) {
setPoliticianWeVoteId(AppObservableStore.getPoliticianWeVoteIdBeingViewed());
// console.log('PoliticianSelfEditDrawer onAppObservableStoreChange politicianWeVoteId:', AppObservableStore.getPoliticianWeVoteIdBeingViewed());
}
}, [setPoliticianWeVoteId]);

const closeEditBar = (buttonId) => {
AppObservableStore.setShowOfficeBannerAboveHeader(false);
const dataLayerObject = {
actionDetails: {
actionType: 'closeModal',
buttonId,
},
event: 'action',
pageDetails: getPageDetails(),
userDetails: VoterStore.getAnalyticsUserDetails(),
};
TagManager.dataLayer({ dataLayer: dataLayerObject });
};

useEffect(() => {
const appStateSubscription = messageService.getMessage().subscribe(onAppObservableStoreChange);
onAppObservableStoreChange();
return () => {
setPoliticianWeVoteId('');
appStateSubscription.unsubscribe();
};
}, [onAppObservableStoreChange]);

return (
<OfficeBannerAboveHeaderContainer>
<BannerTextContainer>
<div style={{display: "flex", gap: "10px"}}>
<WeVoteLogo src={normalizedImagePath(chosenSiteLogoUrl)} className="u-show-desktop-tablet" height="36" width="36" />
<BannerIntroTextMobile className="u-show-mobile">Welcome to WeVote, your personalized voter guide!</BannerIntroTextMobile>
<BannerIntroTextDesktop className="u-show-desktop-tablet">Welcome to WeVote, your personalized voter guide:</BannerIntroTextDesktop>
</div>
<BannerElement>
{/*{' '}*/}
<BannerElementTitle>&#x1F5F3;&ensp; VOTE YOUR VALUES</BannerElementTitle>
<BannerElementText>Get personalized ballot recommendations based on your interests and trusted connections.</BannerElementText>
</BannerElement>
<BannerElement>
<BannerElementTitle>&#x1F91D;&ensp; SHARE & MOBILIZE</BannerElementTitle>
<BannerElementText>Choose the candidates you support or oppose, and tell your friends.</BannerElementText>
</BannerElement>
<BannerElement>
<BannerElementTitle>&#x1F50D;&ensp; SIMPLIFY VOTING</BannerElementTitle>
<BannerElementText>Use clear, nonpartisan tools to understand your ballot and take action confidently.</BannerElementText>
</BannerElement>
</BannerTextContainer>
<VerticalCenter className="u-show-desktop-tablet"><VerticalLine/></VerticalCenter>
<ButtonHolder>
<BallotButton onClick={handleBallotButtonClick}>
<BannerIntroTextMobile className="u-show-mobile">View your full ballot to get started</BannerIntroTextMobile>
<BannerIntroTextDesktop className="u-show-desktop-tablet">View your full ballot to get started</BannerIntroTextDesktop>
</BallotButton>
</ButtonHolder>
<ButtonHolder>
<CloseButton id="closeOfficeBanner" className="u-show-desktop-tablet" onClick={() => closeEditBar('closeOfficeBanner')}>✕</CloseButton>
</ButtonHolder>
</OfficeBannerAboveHeaderContainer>
);
}

const VerticalCenter = styled.div`
margin-inline: 2%;
display: flex;
flex-direction: column;
justify-content: center;
`;

const OfficeBannerAboveHeaderContainer = styled.div`
background: ${DesignTokenColors.secondary800};
color: ${DesignTokenColors.whiteUI};
display: flex;
font-size: 14px;
// flex-direction: column; // only on mobile!
// align-items: center; // only on mobile!
margin-left: -16px;
margin-right: -16px;
padding: 8px 16px;
width: 100vw;
`;

const BannerTextContainer = styled.div`
display: flex;
gap: 12px;
flex-wrap: wrap;
flex-direction: column;
align-items: flex-start;
padding-bottom: 12px;
`;

const BannerIntroTextDesktop = styled('span')`
font-size: 18px;
font-weight: 500;
margin-bottom: 8px;
margin-top: 8px;
`;

const BannerIntroTextMobile = styled('span')`
`;

const BannerElementTitle = styled.div`
font-weight: 500;
margin-bottom: 2px;
margin-left: 1em;
`;

const BannerElementText = styled.div`
margin-left: 2.5em;
`;

const BannerElement = styled('div')`
`;

const VerticalLine = styled('div')`
border-left: 1px solid rgba(105, 105, 105, 0.6);
height: 90%;
margin-inline: 5%;
margin: 5px;
`;

const ButtonHolder = styled.div`
`;

const BallotButton = styled.button`
background: ${DesignTokenColors.whiteUI};
border: none;
border-radius: 24px;
color: ${DesignTokenColors.secondary800};
cursor: pointer;
font-weight: 500;
padding: 8px 16px;
margin-top: 32px;

@media (max-width: 800px) {
margin-top: 8px;
}
@media (max-width: 600px) {
width: auto;
order: 1;
}
`;

const CloseButton = styled.button`
background: transparent;
border: none;
color: ${DesignTokenColors.whiteUI};
cursor: pointer;
font-size: 20px;
margin-left: 16px;

display: flex;
flex-direction: row;
justify-content: center;

@media (max-width: 600px) {
order: 2;
margin-left: 8px;
}
`;