import { LogtoProvider, useLogto, IdTokenClaims, Prompt } from '@logto/react'; import { demoAppApplicationId } from '@logto/schemas/lib/seeds'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import '@/scss/normalized.scss'; import * as styles from './App.module.scss'; import Callback from './Callback'; import congratsDark from './assets/congrats-dark.svg'; import congrats from './assets/congrats.svg'; import initI18n from './i18n/init'; void initI18n(); const Main = () => { const { isAuthenticated, getIdTokenClaims, signIn, signOut } = useLogto(); const [user, setUser] = useState>(); const { t } = useTranslation(undefined, { keyPrefix: 'demo_app' }); const isInCallback = Boolean(new URL(window.location.href).searchParams.get('code')); const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; const [congratsIcon, setCongratsIcon] = useState(isDarkMode ? congratsDark : congrats); useEffect(() => { if (isInCallback) { return; } if (isAuthenticated) { (async () => { const userInfo = await getIdTokenClaims(); setUser(userInfo ?? { sub: 'N/A', username: 'N/A' }); })(); } else { void signIn(window.location.href); } }, [getIdTokenClaims, isAuthenticated, isInCallback, signIn, t]); useEffect(() => { const onThemeChange = (event: MediaQueryListEvent) => { const isDarkMode = event.matches; setCongratsIcon(isDarkMode ? congratsDark : congrats); }; window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', onThemeChange); return () => { window .matchMedia('(prefers-color-scheme: dark)') .removeEventListener('change', onThemeChange); }; }, []); if (isInCallback) { return ; } if (!isAuthenticated || !user) { return null; } return (
{congratsIcon && Congrats}
{t('title')}
{t('subtitle')}
{user.username && (
{t('username')} {user.username}
)}
{t('user_id')} {user.sub}
signOut(`${window.location.origin}/demo-app`)} > {t('sign_out')}
); }; const App = () => { return (
); }; export default App;