feat(analytics): add behavior and payment funnel tracking
This commit is contained in:
@@ -52,6 +52,7 @@ describe("auth Tailwind components", () => {
|
||||
expect(html).toContain("w-full");
|
||||
expect(html).toContain("gap-md");
|
||||
expect(html).toContain("Login");
|
||||
expect(html).toContain('data-analytics-key="auth.email_login"');
|
||||
});
|
||||
|
||||
it("renders EmailRegisterForm with Tailwind form layout", () => {
|
||||
@@ -62,6 +63,7 @@ describe("auth Tailwind components", () => {
|
||||
expect(html).toContain("w-full");
|
||||
expect(html).toContain("gap-md");
|
||||
expect(html).toContain("Register");
|
||||
expect(html).toContain('data-analytics-key="auth.email_register"');
|
||||
});
|
||||
|
||||
it("renders AuthBackground with Tailwind layout classes", () => {
|
||||
@@ -128,6 +130,7 @@ describe("auth Tailwind components", () => {
|
||||
);
|
||||
|
||||
expect(html).toContain("Login with Facebook");
|
||||
expect(html).toContain('data-analytics-key="auth.facebook_login"');
|
||||
expect(html).toContain("bg-auth-surface");
|
||||
expect(html).toContain("enabled:hover:brightness-[0.97]");
|
||||
expect(html).toContain("Other Sign In Options");
|
||||
|
||||
@@ -83,6 +83,9 @@ export function AuthEmailPanel({
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-analytics-key={
|
||||
mode === "login" ? "auth.open_register" : "auth.open_email_login"
|
||||
}
|
||||
className="self-center border-0 bg-transparent pt-md text-(length:--responsive-body) text-auth-text-primary underline underline-offset-[3px] transition-opacity duration-150 hover:opacity-80"
|
||||
onClick={() => setMode((m) => (m === "login" ? "register" : "login"))}
|
||||
>
|
||||
@@ -93,6 +96,8 @@ export function AuthEmailPanel({
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-analytics-key="auth.open_other_options"
|
||||
data-analytics-label="Open other sign-in options"
|
||||
className="self-center border-0 bg-transparent py-md text-(length:--responsive-body) text-auth-text-primary underline underline-offset-[3px] transition-opacity duration-150 hover:opacity-80"
|
||||
onClick={() => setShowOptions(true)}
|
||||
>
|
||||
|
||||
@@ -63,6 +63,8 @@ export function AuthFacebookPanel({
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-analytics-key="auth.facebook_login"
|
||||
data-analytics-label="Facebook login"
|
||||
className="mt-md inline-flex min-h-(--auth-field-height) w-full cursor-pointer items-center justify-center gap-md rounded-full border-0 bg-auth-surface px-lg text-(length:--responsive-body) font-semibold text-auth-text-primary shadow-[0_2px_6px_rgba(0,0,0,0.06)] transition-[filter,transform,opacity] duration-150 enabled:hover:brightness-[0.97] enabled:active:scale-98 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
onClick={() => handleFacebook()}
|
||||
disabled={isLoading}
|
||||
@@ -87,6 +89,8 @@ export function AuthFacebookPanel({
|
||||
|
||||
<button
|
||||
type="button"
|
||||
data-analytics-key="auth.open_other_options"
|
||||
data-analytics-label="Open other sign-in options"
|
||||
className="self-center border-0 bg-transparent py-md text-(length:--responsive-body) text-auth-text-primary underline underline-offset-[3px] transition-opacity duration-150 hover:opacity-80"
|
||||
onClick={() => setShowOptions(true)}
|
||||
>
|
||||
|
||||
@@ -52,6 +52,8 @@ export function AuthOtherOptionsDialog({
|
||||
|
||||
{mode === "email" ? (
|
||||
<AuthSocialButton
|
||||
data-analytics-key="auth.facebook_login"
|
||||
data-analytics-label="Facebook login"
|
||||
icon={<AuthProviderIcon provider="facebook" />}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
@@ -64,6 +66,8 @@ export function AuthOtherOptionsDialog({
|
||||
|
||||
{showNonProductionEmailOption ? (
|
||||
<AuthSocialButton
|
||||
data-analytics-key="auth.open_email_login"
|
||||
data-analytics-label="Email login option"
|
||||
icon={<MdEmail size={20} color="var(--color-auth-text-primary)" />}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
@@ -78,6 +82,8 @@ export function AuthOtherOptionsDialog({
|
||||
<div className="w-full">{googleSlot}</div>
|
||||
) : (
|
||||
<AuthSocialButton
|
||||
data-analytics-key="auth.google_login"
|
||||
data-analytics-label="Google login"
|
||||
icon={<AuthProviderIcon provider="google" />}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
|
||||
@@ -29,7 +29,7 @@ export function AuthPanel() {
|
||||
|
||||
return (
|
||||
<div className="relative flex min-h-0 w-full flex-auto flex-col">
|
||||
<BackButton onClick={handleBack} />
|
||||
<BackButton onClick={handleBack} analyticsKey="auth.back" />
|
||||
|
||||
{state.authPanelMode === "facebook" ? (
|
||||
<AuthFacebookPanel onSwitchToEmail={switchToEmail} />
|
||||
|
||||
@@ -98,7 +98,12 @@ export function EmailLoginForm({
|
||||
/>
|
||||
{/* 优先级:本地校验错误 > 后端 globalError(两个互斥场景:本地校验未过时,UI 不会再有 globalError) */}
|
||||
<AuthErrorMessage message={validationError ?? globalError ?? null} />
|
||||
<AuthPrimaryButton type="submit" isLoading={isLoading}>
|
||||
<AuthPrimaryButton
|
||||
type="submit"
|
||||
isLoading={isLoading}
|
||||
data-analytics-key="auth.email_login"
|
||||
data-analytics-label="Email login"
|
||||
>
|
||||
Login
|
||||
</AuthPrimaryButton>
|
||||
</form>
|
||||
|
||||
@@ -147,7 +147,12 @@ export function EmailRegisterForm({
|
||||
/>
|
||||
{/* 优先级:本地校验错误 > 后端 globalError */}
|
||||
<AuthErrorMessage message={validationError ?? globalError ?? null} />
|
||||
<AuthPrimaryButton type="submit" isLoading={isLoading}>
|
||||
<AuthPrimaryButton
|
||||
type="submit"
|
||||
isLoading={isLoading}
|
||||
data-analytics-key="auth.email_register"
|
||||
data-analytics-label="Email register"
|
||||
>
|
||||
Register
|
||||
</AuthPrimaryButton>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user