1- import { useParams } from "react-router-dom" ;
1+ import { useParams , useLocation , useNavigate } from "react-router-dom" ;
22import Header from "../layout/Header" ;
33import Footer from "../layout/Footer" ;
44import { apps } from "../apps/appTransformers" ;
55import { Helmet } from "react-helmet" ;
6+ import { useEffect , useRef , useState } from "react" ;
67
78export default function AppPage ( ) {
89 const { appName } = useParams ( ) ;
10+ const location = useLocation ( ) ;
11+ const navigate = useNavigate ( ) ;
12+ const iframeRef = useRef ( null ) ;
913
1014 const app = apps . find ( ( app ) => app . slug === appName ) ;
1115
16+ // Check if this is an OBBBA app that needs special handling
17+ const isOBBBAApp = app ?. slug === "obbba-household-by-household" ;
18+ const [ initialUrl , setInitialUrl ] = useState ( null ) ;
19+
20+ // Construct iframe URL with parameters (for OBBBA app only on initial load)
21+ useEffect ( ( ) => {
22+ if ( ! app ) return ;
23+
24+ if ( isOBBBAApp && ! initialUrl ) {
25+ const baseUrl = app . url ;
26+ const separator = baseUrl . includes ( "?" ) ? "&" : "?" ;
27+ const urlParams = new URLSearchParams ( location . search ) ;
28+
29+ const url = urlParams . toString ( )
30+ ? `${ baseUrl } ${ separator } ${ urlParams . toString ( ) } `
31+ : baseUrl ;
32+
33+ setInitialUrl ( url ) ;
34+ } else if ( ! isOBBBAApp ) {
35+ // For non-OBBBA apps, just use the app URL
36+ setInitialUrl ( app . url ) ;
37+ }
38+ } , [ app , location . search , initialUrl , isOBBBAApp ] ) ;
39+
40+ // Listen for messages from OBBBA iframe
41+ useEffect ( ( ) => {
42+ if ( ! isOBBBAApp || ! app ) return ;
43+
44+ const handleMessage = ( event ) => {
45+ try {
46+ const iframeOrigin = new URL ( app . url ) . origin ;
47+ if ( event . origin !== iframeOrigin ) return ;
48+
49+ // Handle URL update messages from the iframe
50+ if ( event . data ?. type === "urlUpdate" && event . data ?. params ) {
51+ const newParams = new URLSearchParams ( event . data . params ) ;
52+ navigate ( `${ location . pathname } ?${ newParams . toString ( ) } ` , {
53+ replace : true ,
54+ } ) ;
55+ }
56+ } catch ( e ) {
57+ console . error ( "Error handling iframe message:" , e ) ;
58+ }
59+ } ;
60+
61+ window . addEventListener ( "message" , handleMessage ) ;
62+ return ( ) => window . removeEventListener ( "message" , handleMessage ) ;
63+ } , [ isOBBBAApp , app , navigate , location . pathname ] ) ;
64+
1265 if ( ! app ) {
1366 return (
1467 < >
@@ -30,16 +83,19 @@ export default function AppPage() {
3083 </ Helmet >
3184 < Header />
3285 < div style = { { height : "var(--app-content-height)" } } >
33- < iframe
34- src = { app . url }
35- style = { {
36- width : "100%" ,
37- height : "100%" ,
38- border : "none" ,
39- } }
40- title = { app . title }
41- aria-label = { app . description }
42- />
86+ { initialUrl && (
87+ < iframe
88+ ref = { iframeRef }
89+ src = { initialUrl }
90+ style = { {
91+ width : "100%" ,
92+ height : "100%" ,
93+ border : "none" ,
94+ } }
95+ title = { app . title }
96+ aria-label = { app . description }
97+ />
98+ ) }
4399 </ div >
44100 < Footer />
45101 </ >
0 commit comments