Spaces:
Sleeping
Sleeping
| '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> | |
| </> | |
| ); | |
| } | |
| } | |