Files
cozsweet-frontend-nextjs/src/app/auth/components/auth-facebook-panel.tsx
T
kanban e2a57386e7 refactor(auth): funnel OAuth signIn into auth state machine
Move new AuthPlatform(provider).signIn() out of UI components and into
the auth state machine. UI now dispatches AuthGoogle/FacebookLoginSubmitted
events; a new oauthSignIn actor inside the machine calls next-auth/react's
signIn(provider). Errors and the OAuth redirect window are exposed via
the existing state.isLoading / state.errorMessage surface, removing the
local busy / error state in auth-facebook-panel.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-11 10:05:48 +08:00

106 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
/**
* Facebook 面板(默认登录面板)
*
* 原始 Dart: lib/ui/auth/widgets/auth_facebook_panel.dart
*
* 视觉规格(与 Dart 对齐):
* - Spacer → logo120h)→ Spacer → Facebook 主按钮 → 链接 → Spacer → 法律
* - Facebook 主按钮:46px 白胶囊 + Facebook "f" 图标(#1877f2+ "Login with Facebook"
* - 社交登录统一收口到 Auth 状态机:派发 `AuthFacebookLoginSubmitted` /
* `AuthGoogleLoginSubmitted` 事件,状态机内部调 next-auth/react 的 signIn(provider)
* - busy / error 状态来自 `useAuthState()`(与邮箱登录同源)
* - "Other Sign-in Options" 链接打开底部弹层
* - 弹层 Email 按钮 → 触发 `onSwitchToEmail`(父级派发 `AuthPanelModeChanged`
*/
import Image from "next/image";
import { useState } from "react";
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
import { AuthErrorMessage } from "./auth-error-message";
import { AuthLegalText } from "./auth-legal-text";
import { AuthOtherOptionsDialog } from "./auth-other-options-dialog";
import styles from "./auth-facebook-panel.module.css";
export interface AuthFacebookPanelProps {
onSwitchToEmail: () => void;
}
export function AuthFacebookPanel({ onSwitchToEmail }: AuthFacebookPanelProps) {
const [showOptions, setShowOptions] = useState(false);
const { isLoading, errorMessage } = useAuthState();
const authDispatch = useAuthDispatch();
const handleFacebook = () => {
authDispatch({
type: "AuthFacebookLoginSubmitted",
provider: "facebook",
});
};
const handleGoogle = () => {
authDispatch({
type: "AuthGoogleLoginSubmitted",
provider: "google",
});
};
return (
<div className={styles.panel}>
<div className={styles.spacer} />
<Image
src="/images/auth/ic-logo-login.png"
alt="Cozsweet"
width={120}
height={120}
className={styles.logo}
priority
/>
<div className={styles.spacer} />
<button
type="button"
className={styles.facebookButton}
onClick={() => handleFacebook()}
disabled={isLoading}
>
{isLoading ? (
<span className={styles.spinner} aria-hidden="true" />
) : (
<span className={styles.facebookIcon} aria-hidden="true">
<svg width="20" height="20" viewBox="0 0 24 24" fill="#1877f2">
<path d="M13 22v-8h3l1-4h-4V7.5c0-1.2.4-2 2-2h2V2.2C16.6 2.1 15.5 2 14.3 2 11.5 2 9.5 3.7 9.5 7v3h-3v4h3v8h3.5z" />
</svg>
</span>
)}
<span className={styles.facebookLabel}>
{isLoading ? "Logging in..." : "Login with Facebook"}
</span>
</button>
<button
type="button"
className={styles.linkButton}
onClick={() => setShowOptions(true)}
>
Other Sign In Options
</button>
<div className={styles.spacer} />
<AuthErrorMessage message={errorMessage} />
<AuthLegalText />
<AuthOtherOptionsDialog
open={showOptions}
onClose={() => setShowOptions(false)}
mode="facebook"
onFacebook={() => handleFacebook()}
onGoogle={() => handleGoogle()}
onEmail={onSwitchToEmail}
/>
</div>
);
}