diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a59ee7d..bd52989 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -10,11 +10,13 @@ import PetZone from './components/PetZone'; import Wardrobe from './components/Wardrobe'; import Particles from './components/Particles'; import WelcomeScreen from './components/WelcomeScreen'; +import LoginScreen from './components/LoginScreen'; import Live2DStage from './components/Live2DStage'; import { SCENES, type Scene } from './components/scenes'; import { useConversation } from './hooks/useConversation'; export default function App() { + const [isLoggedIn, setIsLoggedIn] = useState(() => sessionStorage.getItem('kira-auth') === '1'); const { messages, isConnected, @@ -77,6 +79,10 @@ export default function App() { identify(name); }; + if (!isLoggedIn) { + return setIsLoggedIn(true)} />; + } + if (!identified && !loadingPrefs) { const savedId = localStorage.getItem('kira-user-id'); if (!savedId) { diff --git a/frontend/src/components/LoginScreen.tsx b/frontend/src/components/LoginScreen.tsx new file mode 100644 index 0000000..e489b62 --- /dev/null +++ b/frontend/src/components/LoginScreen.tsx @@ -0,0 +1,71 @@ +import { useState, FormEvent } from 'react'; + +interface Props { + onLogin: () => void; +} + +const PASSWORD = 'focusbestie'; + +export default function LoginScreen({ onLogin }: Props) { + const [input, setInput] = useState(''); + const [error, setError] = useState(false); + const [shake, setShake] = useState(false); + + const handleSubmit = (e: FormEvent) => { + e.preventDefault(); + if (input === PASSWORD) { + sessionStorage.setItem('kira-auth', '1'); + onLogin(); + } else { + setError(true); + setShake(true); + setTimeout(() => setShake(false), 500); + setTimeout(() => setError(false), 2000); + } + }; + + return ( +
+
+
🌸
+

hey kayla!

+

enter the magic word ✨

+ +
+
+ { setInput(e.target.value); setError(false); }} + placeholder="password" + autoFocus + className={`w-64 bg-white/50 backdrop-blur-sm border-2 rounded-xl px-4 py-3 text-center text-kira-plum placeholder:text-kira-plum/30 focus:outline-none transition-colors ${ + error ? 'border-red-400 bg-red-50/50' : 'border-kira-pink/30 focus:border-kira-pink' + }`} + /> + {error && ( +
+ hmm, that's not it 💭 +
+ )} +
+ + +
+
+ + +
+ ); +} diff --git a/frontend/tsconfig.tsbuildinfo b/frontend/tsconfig.tsbuildinfo index 7203c49..781de6f 100644 --- a/frontend/tsconfig.tsbuildinfo +++ b/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AnimatedAvatar.tsx","./src/components/BackgroundScene.tsx","./src/components/ChatBubble.tsx","./src/components/Clock.tsx","./src/components/KiraAvatar.tsx","./src/components/Live2DCat.tsx","./src/components/Live2DStage.tsx","./src/components/MusicPlayer.tsx","./src/components/Notes.tsx","./src/components/Particles.tsx","./src/components/PetZone.tsx","./src/components/TaskList.tsx","./src/components/Timer.tsx","./src/components/Toolbar.tsx","./src/components/Wardrobe.tsx","./src/components/WelcomeScreen.tsx","./src/components/WhiteNoise.tsx","./src/components/scenes.ts","./src/hooks/useConversation.ts","./src/types/index.ts"],"version":"6.0.3"} \ No newline at end of file +{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/AnimatedAvatar.tsx","./src/components/BackgroundScene.tsx","./src/components/ChatBubble.tsx","./src/components/Clock.tsx","./src/components/KiraAvatar.tsx","./src/components/Live2DCat.tsx","./src/components/Live2DStage.tsx","./src/components/LoginScreen.tsx","./src/components/MusicPlayer.tsx","./src/components/Notes.tsx","./src/components/Particles.tsx","./src/components/PetZone.tsx","./src/components/TaskList.tsx","./src/components/Timer.tsx","./src/components/Toolbar.tsx","./src/components/Wardrobe.tsx","./src/components/WelcomeScreen.tsx","./src/components/WhiteNoise.tsx","./src/components/scenes.ts","./src/hooks/useConversation.ts","./src/types/index.ts"],"version":"6.0.3"} \ No newline at end of file