"use client"; import { SolariBoard } from "./components/solari/SolariBoard"; import { useState, useEffect, useMemo, useRef, Suspense } from "react"; import { useSearchParams, useRouter } from "next/navigation"; // import { useDisplayLength } from "./components/useDisplayLength"; function formatCurrency(number: number, locale = "en-US", currency = "USD") { const formatter = new Intl.NumberFormat(locale, { style: "currency", currency: currency, maximumFractionDigits: 2, notation: "standard", }); return formatter.format(number).replace("$", "USD "); } // Initial loading rows - defined outside component to avoid recreation const getLoadingRows = (displayLength: number) => [ { value: "", length: displayLength }, { value: "", length: displayLength }, { value: "", length: displayLength }, { value: "", length: displayLength }, { value: " Loading...", length: displayLength }, { value: "", length: displayLength }, { value: "", length: displayLength }, { value: "", length: displayLength }, { value: "", length: displayLength }, ]; function HomeContent() { const searchParams = useSearchParams(); const router = useRouter(); // const displayLength = useDisplayLength(); const displayLength = 20; // Fallback to a fixed length for simplicity const [bitcoinPrice, setBitcoinPrice] = useState(0); const previousPriceRef = useRef(0); const [priceDirection, setPriceDirection] = useState(null); const [holding] = useState(8485); const [holdingValue, setHoldingValue] = useState(0); const [currentRowIndex, setCurrentRowIndex] = useState(-1); const [ticker, setTicker] = useState(searchParams.get("ticker") || "XYZ"); const [inputError, setInputError] = useState(null); const [error, setError] = useState(null); const [countdown, setCountdown] = useState(20); const [isFetching, setIsFetching] = useState(false); // Initialize loading rows immediately const loadingBoardRows = useMemo( () => getLoadingRows(displayLength), [displayLength] ); // Update holding value when Bitcoin price changes useEffect(() => { setHoldingValue(bitcoinPrice * holding); }, [bitcoinPrice, holding]); // Format the display values const displayValue = error ? "Error" : `${formatCurrency(bitcoinPrice).toString()}${ priceDirection ? ` ${priceDirection}` : "" }`; const holdingDisplay = error ? "Error" : formatCurrency(holdingValue); // Define the final board rows const finalBoardRows = useMemo( () => [ { value: "", length: displayLength }, { value: ` ${ticker}`, length: displayLength }, { value: "", length: displayLength }, { value: " TOTAL HOLDING", length: displayLength }, { value: ` ${holdingDisplay}`, length: displayLength }, { value: "", length: displayLength }, { value: " BTC PRICE", length: displayLength }, { value: ` ${displayValue}`, length: displayLength }, { value: "", length: displayLength }, ], [ticker, holdingDisplay, displayValue, displayLength] ); // Current board rows based on loading state and animation progress const currentBoardRows = useMemo(() => { if (currentRowIndex === -1) { return loadingBoardRows; } return loadingBoardRows.map((row, index) => { if (index <= currentRowIndex) { return finalBoardRows[index]; } return row; }); }, [loadingBoardRows, finalBoardRows, currentRowIndex]); // Handle the row-by-row animation useEffect(() => { if (!isFetching && currentRowIndex === -1) { // Start the row animation after data is loaded const animateRows = () => { const interval = setInterval(() => { setCurrentRowIndex((prev) => { if (prev >= finalBoardRows.length - 1) { clearInterval(interval); return prev; } return prev + 1; }); }, 300); // Adjust timing between each row update return () => clearInterval(interval); }; // Small delay before starting the animation setTimeout(animateRows, 1000); } }, [isFetching, currentRowIndex, finalBoardRows.length]); // Fetch Bitcoin price and manage countdown useEffect(() => { const fetchBitcoinPrice = async () => { setIsFetching(true); try { const response = await fetch( "https://pricing.bitcoin.block.xyz/current-price" ); if (!response.ok) { throw new Error(`API error: ${response.status}`); } const data = await response.json(); const newPrice = parseFloat(data["amount"]); // Check if this is not the first fetch if (!isFetching) { // Compare with previous price to determine direction if (newPrice > previousPriceRef.current) { setPriceDirection("↑"); } else if (newPrice < previousPriceRef.current) { setPriceDirection("↓"); } else { setPriceDirection(null); } // Remove the direction indicator after 5 seconds (increased from 2 seconds) if (newPrice !== previousPriceRef.current) { setTimeout(() => { setPriceDirection(null); }, 2000); } } else { // Set initial price without showing direction setPriceDirection(null); } // Update prices const oldPrice = previousPriceRef.current; previousPriceRef.current = newPrice; setBitcoinPrice(newPrice); } catch (err) { console.error("Failed to fetch Bitcoin price:", err); setError("Failed to fetch Bitcoin price"); } setIsFetching(false); setCountdown(20); }; // Fetch immediately on load fetchBitcoinPrice(); // Set up countdown interval const countdownInterval = setInterval(() => { setCountdown((prev) => { if (prev <= 1) { fetchBitcoinPrice(); // Fetch when countdown reaches 0 return 20; // Reset to 20 seconds } return prev - 1; }); }, 1000); // Clean up intervals on component unmount return () => { clearInterval(countdownInterval); }; }, []); return (
{/* Status indicator */}
{isFetching ? "Fetching..." : `Fetching latest in ${countdown} second${ countdown > 1 ? "s" : "" }`}
); } export default function Home() { return ( Loading...}> ); }