/** * BoostMedia AI Content Generator Admin - Layout Component * * @package BoostMedia_AI * @license GPL-2.0-or-later */ import { useState, useEffect } from 'react' import { Outlet, useLocation, useNavigate } from 'react-router-dom' import { AlertTriangle, X, Coins } from 'lucide-react' import { Sidebar } from './Sidebar' import { useDataLanguage } from '../../lib/DataLanguageContext' import { useTranslation } from '../../lib/TranslationContext' import { endpoints } from '../../api/client' import { t, tf } from '../../lib/i18n' function LowCreditsAlert() { const navigate = useNavigate() const [visible, setVisible] = useState(false) const [remaining, setRemaining] = useState(0) const [dismissed, setDismissed] = useState(false) useEffect(() => { const check = async () => { try { const [creditsRes, settingsRes] = await Promise.all([ endpoints.getCreditsStatus(), endpoints.getSettings(), ]) const credits = creditsRes.data as any const settings = settingsRes.data as any const rawThreshold = Number(settings?.low_credits_threshold) const threshold = Number.isNaN(rawThreshold) ? 100 : rawThreshold const rem = credits?.boost_credits?.remaining ?? 0 setRemaining(Math.round(rem)) if (threshold > 0 && rem < threshold && rem >= 0) { setVisible(true) } } catch { /* ignore */ } } check() }, []) if (!visible || dismissed) return null return (

{tf('Low BoostCoins balance: %s remaining.', remaining)}{' '}

) } export default function Layout() { const { isRtl } = useTranslation() const { dataLanguage } = useDataLanguage() const location = useLocation() useEffect(() => { window.scrollTo(0, 0) }, [location.pathname]) return (
) }