Bankbot / frontend /src /components /layout /AppShell.tsx
mohsin-devs's picture
feat: improved light mode + language sync to html lang attribute
7782325
Raw
History Blame Contribute Delete
2.2 kB
"use client";
import { useEffect, useState } from "react";
import { usePathname, useRouter } from "next/navigation";
import { DashboardLayout } from "./DashboardLayout";
import { useAuthStore } from "@/lib/stores/authStore";
import { useThemeStore } from "@/lib/stores/themeStore";
import { useLanguageStore } from "@/lib/stores/languageStore";
import { Loader2, Sparkles } from "lucide-react";
const PUBLIC_PATHS = ["/login"];
// Lang codes mapped to BCP-47 HTML lang values
const LANG_MAP: Record<string, string> = {
en: "en",
hi: "hi",
mr: "mr",
};
function FullPageSpinner() {
return (
<div className="flex min-h-screen items-center justify-center" style={{ background: "var(--bg, #050505)" }}>
<div className="flex flex-col items-center gap-4">
<div className="flex h-14 w-14 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-400 to-cyan-500 shadow-2xl shadow-emerald-500/30">
<Sparkles className="h-7 w-7 text-white" />
</div>
<Loader2 className="h-5 w-5 animate-spin text-emerald-400" />
<p className="text-xs text-zinc-500">Loading BankBot AI...</p>
</div>
</div>
);
}
export function AppShell({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const router = useRouter();
const { isAuthenticated, restoreSession } = useAuthStore();
const { theme, setTheme } = useThemeStore();
const { language } = useLanguageStore();
const [hydrated, setHydrated] = useState(false);
const isPublic = PUBLIC_PATHS.includes(pathname);
// Apply persisted theme on mount
useEffect(() => {
setTheme(theme);
restoreSession().finally(() => setHydrated(true));
}, []); // eslint-disable-line react-hooks/exhaustive-deps
// Sync <html lang> whenever language changes
useEffect(() => {
if (typeof document !== "undefined") {
document.documentElement.lang = LANG_MAP[language] ?? language;
}
}, [language]);
if (!hydrated) return <FullPageSpinner />;
if (isPublic) return <>{children}</>;
if (!isAuthenticated) {
router.replace("/login");
return <FullPageSpinner />;
}
return <DashboardLayout>{children}</DashboardLayout>;
}