Spaces:
Sleeping
Sleeping
File size: 4,821 Bytes
68f7925 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
'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>
</>
);
}
}
|