11import { css } from '@emotion/react' ;
2+ import type { ComponentEvent } from '@guardian/ophan-tracker-js' ;
23import {
34 palette ,
45 space ,
@@ -19,7 +20,9 @@ import { hexColourToString } from '@guardian/support-dotcom-components';
1920import type { HexColour } from '@guardian/support-dotcom-components/dist/shared/types' ;
2021import type { ChoiceCard } from '@guardian/support-dotcom-components/dist/shared/types/props/choiceCards' ;
2122import type { Dispatch , SetStateAction } from 'react' ;
23+ import { useEffect } from 'react' ;
2224import sanitise from 'sanitize-html' ;
25+ import { useIsInView } from '../../../lib/useIsInView' ;
2326
2427const supportTierChoiceCardStyles = ( selected : boolean ) => css `
2528 display : block;
@@ -151,102 +154,144 @@ type ThreeTierChoiceCardsProps = {
151154 selectedChoiceCard : ChoiceCard ;
152155 setSelectedChoiceCard : Dispatch < SetStateAction < ChoiceCard | undefined > > ;
153156 choices : ChoiceCard [ ] ;
154- id : string ; // uniquely identify this choice cards component to avoid conflicting with others
157+ id : 'epic' | 'banner' ; // uniquely identify this choice cards component to avoid conflicting with others
158+ submitComponentEvent ?: ( componentEvent : ComponentEvent ) => void ;
155159} ;
156160
157161export const ThreeTierChoiceCards = ( {
158162 selectedChoiceCard,
159163 setSelectedChoiceCard,
160164 choices,
161165 id,
166+ submitComponentEvent,
162167} : ThreeTierChoiceCardsProps ) => {
168+ const [ hasBeenSeen , setNode ] = useIsInView ( {
169+ debounce : true ,
170+ threshold : 0 ,
171+ } ) ;
172+
173+ useEffect ( ( ) => {
174+ if ( submitComponentEvent ) {
175+ void submitComponentEvent ( {
176+ component : {
177+ componentType : 'ACQUISITIONS_OTHER' ,
178+ id : `${ id } -choice-cards` ,
179+ } ,
180+ action : 'INSERT' ,
181+ } ) ;
182+ }
183+ } , [ id , submitComponentEvent ] ) ;
184+
185+ useEffect ( ( ) => {
186+ if ( hasBeenSeen && submitComponentEvent ) {
187+ void submitComponentEvent ( {
188+ component : {
189+ componentType : 'ACQUISITIONS_OTHER' ,
190+ id : `${ id } -choice-cards` ,
191+ } ,
192+ action : 'VIEW' ,
193+ } ) ;
194+ }
195+ } , [ hasBeenSeen , id , submitComponentEvent ] ) ;
196+
163197 return (
164- < RadioGroup
165- cssOverrides = { css `
166- margin-top : ${ space [ 6 ] } px;
167- ` }
168- >
169- < Stack space = { 3 } >
170- { choices . map ( ( card ) => {
171- const { product, label, benefitsLabel, benefits, pill } =
172- card ;
173- const { supportTier } = product ;
174-
175- const isSelected = ( ) : boolean => {
176- if (
177- product . supportTier ===
178- selectedChoiceCard . product . supportTier
179- ) {
198+ < div ref = { setNode } >
199+ < RadioGroup
200+ cssOverrides = { css `
201+ margin-top : ${ space [ 6 ] } px;
202+ ` }
203+ >
204+ < Stack space = { 3 } >
205+ { choices . map ( ( card ) => {
206+ const {
207+ product,
208+ label,
209+ benefitsLabel,
210+ benefits,
211+ pill,
212+ } = card ;
213+ const { supportTier } = product ;
214+
215+ const isSelected = ( ) : boolean => {
180216 if (
181- product . supportTier !== 'OneOff' &&
182- selectedChoiceCard . product . supportTier !==
183- 'OneOff'
217+ product . supportTier ===
218+ selectedChoiceCard . product . supportTier
184219 ) {
185- return (
186- product . ratePlan ===
187- selectedChoiceCard . product . ratePlan
188- ) ;
220+ if (
221+ product . supportTier !== 'OneOff' &&
222+ selectedChoiceCard . product . supportTier !==
223+ 'OneOff'
224+ ) {
225+ return (
226+ product . ratePlan ===
227+ selectedChoiceCard . product . ratePlan
228+ ) ;
229+ } else {
230+ return true ;
231+ }
189232 } else {
190- return true ;
233+ return false ;
191234 }
192- } else {
193- return false ;
194- }
195- } ;
196- const selected = isSelected ( ) ;
197-
198- // Each radioId must be unique to the component and choice, e.g. "choicecard-epic-Contribution-Monthly"
199- const radioId = `choicecard-${ id } -${ supportTier } ${
200- supportTier !== 'OneOff' ? `-${ product . ratePlan } ` : ''
201- } `;
202-
203- return (
204- < div
205- key = { supportTier }
206- css = { css `
207- position : relative;
208- background-color : inherit;
209- ` }
210- >
211- { pill && < ChoiceCardPill pill = { pill } /> }
212- < label
213- css = { supportTierChoiceCardStyles ( selected ) }
214- htmlFor = { radioId }
235+ } ;
236+ const selected = isSelected ( ) ;
237+
238+ // Each radioId must be unique to the component and choice, e.g. "choicecard-epic-Contribution-Monthly"
239+ const radioId = `choicecard-${ id } -${ supportTier } ${
240+ supportTier !== 'OneOff'
241+ ? `-${ product . ratePlan } `
242+ : ''
243+ } `;
244+
245+ return (
246+ < div
247+ key = { supportTier }
248+ css = { css `
249+ position : relative;
250+ background-color : inherit;
251+ ` }
215252 >
216- < Radio
217- label = {
218- < span
219- dangerouslySetInnerHTML = { {
220- __html : sanitise ( label ) ,
221- } }
222- />
223- }
224- id = { radioId }
225- value = { radioId }
226- cssOverrides = { labelOverrideStyles ( selected ) }
227- supporting = {
228- selected && (
229- < SupportingBenefits
230- benefitsLabel = {
231- benefitsLabel as
232- | string
233- | undefined
234- }
235- benefits = { benefits }
253+ { pill && < ChoiceCardPill pill = { pill } /> }
254+ < label
255+ css = { supportTierChoiceCardStyles ( selected ) }
256+ htmlFor = { radioId }
257+ >
258+ < Radio
259+ label = {
260+ < span
261+ dangerouslySetInnerHTML = { {
262+ __html : sanitise ( label ) ,
263+ } }
236264 />
237- )
238- }
239- checked = { selected }
240- onChange = { ( ) => {
241- setSelectedChoiceCard ( card ) ;
242- } }
243- theme = { customRadioTheme }
244- />
245- </ label >
246- </ div >
247- ) ;
248- } ) }
249- </ Stack >
250- </ RadioGroup >
265+ }
266+ id = { radioId }
267+ value = { radioId }
268+ cssOverrides = { labelOverrideStyles (
269+ selected ,
270+ ) }
271+ supporting = {
272+ selected && (
273+ < SupportingBenefits
274+ benefitsLabel = {
275+ benefitsLabel as
276+ | string
277+ | undefined
278+ }
279+ benefits = { benefits }
280+ />
281+ )
282+ }
283+ checked = { selected }
284+ onChange = { ( ) => {
285+ setSelectedChoiceCard ( card ) ;
286+ } }
287+ theme = { customRadioTheme }
288+ />
289+ </ label >
290+ </ div >
291+ ) ;
292+ } ) }
293+ </ Stack >
294+ </ RadioGroup >
295+ </ div >
251296 ) ;
252297} ;
0 commit comments