From b275a3668b140d9ce4663de646519d2dbd4297e7 Mon Sep 17 00:00:00 2001 From: 苏向夜 Date: Tue, 24 Feb 2026 22:41:36 +0800 Subject: refactor: rewrite login and settings pages --- packages/ui-new/src/components/login-modal.tsx | 292 ++++++++++++++----------- 1 file changed, 162 insertions(+), 130 deletions(-) (limited to 'packages/ui-new/src/components/login-modal.tsx') diff --git a/packages/ui-new/src/components/login-modal.tsx b/packages/ui-new/src/components/login-modal.tsx index 9152494..49596da 100644 --- a/packages/ui-new/src/components/login-modal.tsx +++ b/packages/ui-new/src/components/login-modal.tsx @@ -1,156 +1,188 @@ import { Mail, User } from "lucide-react"; -import { useAuthStore } from "@/stores/auth-store"; +import { useCallback, useState } from "react"; +import { toast } from "sonner"; +import { useAuthStore } from "@/models/auth"; +import { Button } from "./ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "./ui/dialog"; +import { + Field, + FieldDescription, + FieldError, + FieldGroup, + FieldLabel, +} from "./ui/field"; +import { Input } from "./ui/input"; -export function LoginModal() { +export interface LoginModalProps + extends Omit, "onOpenChange"> { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function LoginModal({ onOpenChange, ...props }: LoginModalProps) { const authStore = useAuthStore(); - const handleOfflineLogin = () => { - if (authStore.offlineUsername.trim()) { - authStore.performOfflineLogin(); - } - }; + const [offlineUsername, setOfflineUsername] = useState(""); + const [errorMessage, setErrorMessage] = useState(""); + const [isLoggingIn, setIsLoggingIn] = useState(false); - const handleKeyPress = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { - handleOfflineLogin(); + const handleMicrosoftLogin = useCallback(async () => { + setIsLoggingIn(true); + authStore.setLoginMode("microsoft"); + try { + await authStore.loginOnline(() => onOpenChange?.(false)); + } catch (error) { + const err = error as Error; + console.error("Failed to login with Microsoft:", err); + setErrorMessage(err.message); + } finally { + setIsLoggingIn(false); } - }; + }, [authStore.loginOnline, authStore.setLoginMode, onOpenChange]); - if (!authStore.isLoginModalOpen) return null; + const handleOfflineLogin = useCallback(async () => { + setIsLoggingIn(true); + try { + await authStore.loginOffline(offlineUsername); + toast.success("Logged in offline successfully"); + onOpenChange?.(false); + } catch (error) { + const err = error as Error; + console.error("Failed to login offline:", err); + setErrorMessage(err.message); + } finally { + setIsLoggingIn(false); + } + }, [authStore, offlineUsername, onOpenChange]); return ( -
-
-
- {/* Header */} -
-

Login

- -
- - {/* Content based on mode */} - {authStore.loginMode === "select" && ( -
-

- Choose your preferred login method -

- + + + Login Offline + +
+ )} + {authStore.loginMode === "microsoft" && ( +
-
- )} - - {authStore.loginMode === "offline" && ( -
-
- - authStore.setOfflineUsername(e.target.value)} - onKeyDown={handleKeyPress} - className="w-full px-4 py-2.5 bg-zinc-800 border border-zinc-700 rounded-lg text-white placeholder:text-zinc-500 focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 transition-colors" - placeholder="Enter your Minecraft username" - /> -
-
- - -
+ {authStore.deviceCode?.userCode} + {" "} + to authenticate, this code will be expired in{" "} + {authStore.deviceCode?.expiresIn} seconds. + + {errorMessage}
)} - - {authStore.loginMode === "microsoft" && ( -
- {authStore.deviceCodeData && ( -
-
-
- {authStore.deviceCodeData.userCode} -
-

- Your verification code -

-
-

- Visit{" "} - - {authStore.deviceCodeData.verificationUri} - {" "} - and enter the code above -

-
- )} -
-

- {authStore.msLoginStatus} -

- -
-
+ aria-invalid={!!errorMessage} + /> + {errorMessage} + + )}
-
-
+ +
+ + {authStore.statusMessage} + +
+ + {authStore.loginMode === "offline" && ( + + )} +
+ + ); } -- cgit v1.2.3-70-g09d2