| 1 |
import { __ } from '@wordpress/i18n' |
| 2 |
import { Icon, closeSmall } from '@wordpress/icons' |
| 3 |
import { Button } from '@wordpress/components' |
| 4 |
import WelcomeNotice from './notices/WelcomeNotice' |
| 5 |
import PromotionNotice from './notices/PromotionNotice' |
| 6 |
import FeedbackNotice from './notices/FeedbackNotice' |
| 7 |
import { useUserStore } from '../state/User' |
| 8 |
import { useGlobalStore } from '../state/GlobalState' |
| 9 |
import { useState, useEffect, useRef } from '@wordpress/element' |
| 10 |
|
| 11 |
const NoticesByPriority = { |
| 12 |
welcome: WelcomeNotice, |
| 13 |
promotion: PromotionNotice, |
| 14 |
feedback: FeedbackNotice, |
| 15 |
} |
| 16 |
|
| 17 |
export default function FooterNotice() { |
| 18 |
const [hasNotice, setHasNotice] = useState(null) |
| 19 |
const once = useRef(false) |
| 20 |
const promotionData = useGlobalStore( |
| 21 |
(state) => state.metaData?.banners?.footer, |
| 22 |
) |
| 23 |
|
| 24 |
const showFeedback = () => { |
| 25 |
const imports = useUserStore.getState().imports ?? 0 |
| 26 |
const firstLoadedOn = |
| 27 |
useUserStore.getState()?.firstLoadedOn ?? new Date() |
| 28 |
const timeDifference = |
| 29 |
new Date().getTime() - new Date(firstLoadedOn).getTime() |
| 30 |
const daysSinceActivated = timeDifference / 86_400_000 // 24 hours |
| 31 |
|
| 32 |
return imports >= 3 && daysSinceActivated > 3 |
| 33 |
} |
| 34 |
|
| 35 |
// Find the first notice key to use |
| 36 |
const componentKey = |
| 37 |
Object.keys(NoticesByPriority).find((key) => { |
| 38 |
if (key === 'promotion') { |
| 39 |
return ( |
| 40 |
// When checking promotions, use the key sent from the server |
| 41 |
// to check whether it's been dismissed |
| 42 |
promotionData?.key && |
| 43 |
!useUserStore.getState().noticesDismissedAt[ |
| 44 |
promotionData.key |
| 45 |
] |
| 46 |
) |
| 47 |
} |
| 48 |
|
| 49 |
if (key === 'feedback') { |
| 50 |
return ( |
| 51 |
showFeedback() && |
| 52 |
!useUserStore.getState().noticesDismissedAt[key] |
| 53 |
) |
| 54 |
} |
| 55 |
|
| 56 |
return !useUserStore.getState().noticesDismissedAt[key] |
| 57 |
}) ?? null |
| 58 |
const Notice = NoticesByPriority[componentKey] |
| 59 |
|
| 60 |
const dismiss = () => { |
| 61 |
setHasNotice(false) |
| 62 |
// The noticesDismissedAt key will either be the key from NoticesByPriority, |
| 63 |
// or a key passed in from the server, such as 'holiday-sale2077' |
| 64 |
const key = |
| 65 |
componentKey === 'promotion' ? promotionData.key : componentKey |
| 66 |
useUserStore.setState({ |
| 67 |
noticesDismissedAt: Object.assign( |
| 68 |
{}, |
| 69 |
{ |
| 70 |
...useUserStore.getState().noticesDismissedAt, |
| 71 |
[key]: new Date().toISOString(), |
| 72 |
}, |
| 73 |
), |
| 74 |
}) |
| 75 |
} |
| 76 |
|
| 77 |
useEffect(() => { |
| 78 |
// Only show the notice once on main render and only if a notice exists. |
| 79 |
if (NoticesByPriority[componentKey] && !once.current) { |
| 80 |
setHasNotice(true) |
| 81 |
once.current = true |
| 82 |
} |
| 83 |
}, [componentKey]) |
| 84 |
|
| 85 |
if (!hasNotice) { |
| 86 |
return null |
| 87 |
} |
| 88 |
return ( |
| 89 |
<div className="bg-extendify-secondary hidden lg:flex space-x-4 py-3 px-5 justify-center items-center relative max-w-screen-4xl mx-auto"> |
| 90 |
{/* Pass all data to all components and let them decide what they use */} |
| 91 |
<Notice promotionData={promotionData} /> |
| 92 |
<div className="absolute right-1"> |
| 93 |
<Button |
| 94 |
className="opacity-50 hover:opacity-100 focus:opacity-100 text-extendify-black" |
| 95 |
icon={<Icon icon={closeSmall} />} |
| 96 |
label={__('Dismiss this notice', 'extendify')} |
| 97 |
onClick={dismiss} |
| 98 |
showTooltip={false} |
| 99 |
/> |
| 100 |
</div> |
| 101 |
</div> |
| 102 |
) |
| 103 |
} |
| 104 |
|