125 lines
3.7 KiB
TypeScript
125 lines
3.7 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import { useSession } from 'next-auth/react';
|
|
|
|
interface ResponsiveIframeProps {
|
|
src: string;
|
|
className?: string;
|
|
allow?: string;
|
|
style?: React.CSSProperties;
|
|
}
|
|
|
|
export function ResponsiveIframe({ src, className = '', allow, style }: ResponsiveIframeProps) {
|
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
const { data: session } = useSession();
|
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
const [iframeSrc, setIframeSrc] = useState<string>('');
|
|
|
|
// Refresh NextAuth session (which will also refresh Keycloak tokens) before loading iframe
|
|
useEffect(() => {
|
|
if (!session || !src || isRefreshing) {
|
|
if (src && !isRefreshing) {
|
|
setIframeSrc(src);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const refreshSession = async () => {
|
|
setIsRefreshing(true);
|
|
|
|
try {
|
|
// Call our API to refresh the Keycloak session
|
|
// This ensures tokens are fresh and may help refresh Keycloak session cookies
|
|
const response = await fetch('/api/auth/refresh-keycloak-session', {
|
|
method: 'GET',
|
|
credentials: 'include', // Include cookies
|
|
});
|
|
|
|
if (response.ok) {
|
|
console.log('Session refreshed before loading iframe');
|
|
} else {
|
|
console.warn('Failed to refresh session, iframe may require login');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error refreshing session:', error);
|
|
} finally {
|
|
// Set iframe src after attempting refresh
|
|
setIframeSrc(src);
|
|
setIsRefreshing(false);
|
|
}
|
|
};
|
|
|
|
refreshSession();
|
|
}, [session, src, isRefreshing]);
|
|
|
|
useEffect(() => {
|
|
const iframe = iframeRef.current;
|
|
if (!iframe || !iframeSrc) return;
|
|
|
|
const calculateHeight = () => {
|
|
const pageY = (elem: HTMLElement): number => {
|
|
return elem.offsetParent ?
|
|
(elem.offsetTop + pageY(elem.offsetParent as HTMLElement)) :
|
|
elem.offsetTop;
|
|
};
|
|
|
|
const height = document.documentElement.clientHeight;
|
|
const iframeY = pageY(iframe);
|
|
const newHeight = Math.max(0, height - iframeY);
|
|
iframe.style.height = `${newHeight}px`;
|
|
};
|
|
|
|
const handleHashChange = () => {
|
|
if (window.location.hash && window.location.hash.length && iframe.src) {
|
|
const iframeURL = new URL(iframe.src);
|
|
iframeURL.hash = window.location.hash;
|
|
iframe.src = iframeURL.toString();
|
|
}
|
|
};
|
|
|
|
// Initial setup
|
|
calculateHeight();
|
|
handleHashChange();
|
|
|
|
// Event listeners
|
|
window.addEventListener('resize', calculateHeight);
|
|
window.addEventListener('hashchange', handleHashChange);
|
|
iframe.addEventListener('load', calculateHeight);
|
|
|
|
// Cleanup
|
|
return () => {
|
|
window.removeEventListener('resize', calculateHeight);
|
|
window.removeEventListener('hashchange', handleHashChange);
|
|
iframe.removeEventListener('load', calculateHeight);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<>
|
|
{isRefreshing && (
|
|
<div className="flex items-center justify-center w-full h-full absolute bg-black/50 z-10">
|
|
<div className="text-center bg-white p-4 rounded-lg">
|
|
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500 mx-auto mb-4"></div>
|
|
<p className="text-gray-600">Actualisation de la session...</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<iframe
|
|
ref={iframeRef}
|
|
id="myFrame"
|
|
src={iframeSrc || src}
|
|
className={`w-full border-none ${className}`}
|
|
style={{
|
|
display: 'block',
|
|
width: '100%',
|
|
height: '100%',
|
|
...style
|
|
}}
|
|
allow={allow}
|
|
allowFullScreen
|
|
/>
|
|
</>
|
|
);
|
|
}
|