FE_Dev / components /auth-wrapper.tsx
GitHub Actions
Deploy from GitHub Actions [dev] - 2025-10-31 07:28:50
68f7925
'use client';
import { AppBar } from '@/components/parts/app-bar';
import { Bread } from '@/components/parts/bread';
import { OldAppBar } from '@/components/parts/old-app-bar';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import { sendLog } from '@/services/gradio';
import { useStateStore } from '@/store/state';
import { type UserState, useUserStore } from '@/store/user';
import { SessionProvider, getProviders, signIn, useSession } from 'next-auth/react';
import Image from 'next/image';
import { usePathname } from 'next/navigation';
import { useEffect, useRef, useState } from 'react';
export function AuthWrapper({ children }: { children: React.ReactNode }) {
return (
<SessionProvider>
<InnerAuthWrapper>{children}</InnerAuthWrapper>
</SessionProvider>
);
}
function InnerAuthWrapper({ children }: { children: React.ReactNode }) {
const { data: session, status } = useSession();
const { setUser } = useUserStore();
const logSentRef = useRef(false);
const [hasOktaProvider, setHasOktaProvider] = useState<boolean | null>(null);
const isProduction = process.env.NEXT_PUBLIC_APP_ENV === 'production';
// NextAuthで利用可能なプロバイダーをチェック
useEffect(() => {
getProviders().then((providers) => {
setHasOktaProvider(!!providers?.okta);
});
}, []);
useEffect(() => {
setUser(session as UserState);
// Send log only once when user logs in
if (session?.user?.email && !logSentRef.current) {
sendLog(session.user.email);
logSentRef.current = true;
}
}, [session, setUser]);
const pathname = usePathname();
const { getScoreLoading, getMomentLoading } = useStateStore();
const showBreadOnPages = [
'/',
'/speed-comparison-input',
'/speed-comparison-result',
'/prediction-input',
'/prediction-result',
'/detail',
'/refresh-moments',
'/refresh-moments/result',
];
// プロバイダーチェック中はローディング表示
if (hasOktaProvider === null) {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-gray-500 border-t-transparent"></div>
</div>
);
}
// Oktaプロバイダーが利用できない場合は認証をスキップ
if (!hasOktaProvider) {
return (
<>
{isProduction ? <OldAppBar email="dev@example.com" /> : <AppBar email="dev@example.com" />}
<main className="relative flex grow flex-col space-y-2">
<video
className={cn('background-video', pathname === '/error' || getScoreLoading ? 'opacity-20' : 'opacity-50')}
src="/background.mp4"
autoPlay
loop
playsInline
muted
/>
<div className="z-10 flex grow flex-col p-12">
{!getScoreLoading && !getMomentLoading && showBreadOnPages.includes(pathname) ? <Bread /> : null}
{children}
</div>
</main>
</>
);
}
// 本番環境では認証を有効化
if (status === 'loading') {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-gray-500 border-t-transparent"></div>
</div>
);
}
if (status === 'unauthenticated') {
return (
<div className="relative flex min-h-screen flex-col items-center justify-center">
{/* 背景ビデオ */}
<video className="background-video opacity-50" src="/background.mp4" autoPlay loop playsInline muted />
{/* ログインカード */}
<div className="z-10 w-full max-w-md rounded-xl bg-white/80 p-8">
<div className="mb-8 flex flex-col items-center">
<Image src="/logo.svg" alt="logo" width={120} height={60} className="mb-4" />
</div>
<Button onClick={() => signIn('okta')} variant="gradient">
Oktaでログイン
</Button>
</div>
</div>
);
}
if (session) {
return (
<>
{isProduction ? <OldAppBar email={session?.user?.email ?? ''} /> : <AppBar email={session?.user?.email ?? ''} />}
<main className="relative flex grow flex-col space-y-2">
<video
className={cn('background-video', pathname === '/error' || getScoreLoading ? 'opacity-20' : 'opacity-50')}
src="/background.mp4"
autoPlay
loop
playsInline
muted
/>
<div className="z-10 flex grow flex-col p-12">
{!getScoreLoading && !getMomentLoading && showBreadOnPages.includes(pathname) ? <Bread /> : null}
{children}
</div>
</main>
</>
);
}
}