Created
September 12, 2025 18:53
-
-
Save jmont96/18238b257e15a7fa93ccc45b3885873e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "use client"; | |
| import axios from "axios"; | |
| import { useCallback, useEffect, useRef, useState } from "react"; | |
| export default function CheckoutLinkPlaceholderDemoPage() { | |
| const [sessionKey, setSessionKey] = useState<string | null>(null); | |
| const [link, setLink] = useState<string | null>(null); | |
| const [iframeLoaded, setIframeLoaded] = useState(false); | |
| const initiateCheckout = useCallback(async () => { | |
| // Get Session Key | |
| const session = await axios.get("/api/session-key"); | |
| setSessionKey(session.data); | |
| // Get Checkout Link for iFrame | |
| const checkoutLink = await axios.get("/api/link"); | |
| setLink(checkoutLink.data.link); | |
| }, []); | |
| useEffect(() => { | |
| initiateCheckout(); | |
| }, [initiateCheckout]); | |
| const handleMessage = useCallback((event: MessageEvent) => { | |
| // Try to parse if it's a string | |
| let parsedData = event.data; | |
| if (typeof event.data === "string") { | |
| try { | |
| parsedData = JSON.parse(event.data); | |
| } catch (e) { | |
| console.log("Failed to parse as JSON:", e); | |
| } | |
| } | |
| const { method } = parsedData || {}; | |
| switch (method) { | |
| case "loaded": | |
| setTimeout(() => { | |
| setIframeLoaded(true); | |
| }, 1000); | |
| break; | |
| } | |
| }, []); | |
| useEffect(() => { | |
| window.addEventListener("message", handleMessage); | |
| return () => { | |
| window.removeEventListener("message", handleMessage); | |
| }; | |
| }, [handleMessage]); | |
| const IFrameRef = useRef<HTMLIFrameElement | null>(null); | |
| const handleIframeLoad = () => { | |
| if (IFrameRef.current) IFrameRef.current.style.opacity = "1"; | |
| }; | |
| if (!sessionKey || !link) { | |
| return <div>Loading...</div>; | |
| } | |
| return ( | |
| <div className="relative w-full h-screen bg-white flex"> | |
| <div className="h-180 w-100 m-auto relative"> | |
| <iframe | |
| allow={"payment;camera;clipboard-write"} | |
| src={link} | |
| onLoad={handleIframeLoad} | |
| ref={IFrameRef} | |
| className="w-full h-full border-none" | |
| style={{ | |
| width: "100%", | |
| height: "100%", | |
| opacity: 0, | |
| transition: "opacity 300ms linear", | |
| }} | |
| /> | |
| {!iframeLoaded && ( | |
| <div | |
| className={` | |
| absolute top-0 left-0 w-full h-full bg-zinc-100 | |
| flex flex-col items-center justify-center z-10 | |
| transition-opacity duration-500 ease-out border border-zinc-200 | |
| ${iframeLoaded ? "opacity-0" : "opacity-100"} | |
| `} | |
| > | |
| {/* Skeleton Header */} | |
| <div className="w-3/5 h-10 bg-zinc-300 rounded-lg mb-5 animate-pulse" /> | |
| {/* Skeleton Content Blocks */} | |
| <div className="w-4/5 flex flex-col gap-4"> | |
| <div className="w-full h-16 bg-zinc-300 rounded-lg animate-pulse" /> | |
| <div className="w-3/4 h-10 bg-zinc-300 rounded-lg animate-pulse" /> | |
| <div className="w-11/12 h-20 bg-zinc-300 rounded-lg animate-pulse" /> | |
| <div className="w-1/2 h-8 bg-zinc-300 rounded-lg animate-pulse" /> | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment