Fix: Deduplicate toast and add session dismissal

This commit is contained in:
gpt-engineer-app[bot]
2025-10-14 16:47:49 +00:00
parent 69c16c2b1e
commit 3c70579ac9
2 changed files with 42 additions and 2 deletions

View File

@@ -34,6 +34,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
// Refs for lifecycle and cleanup management
const novuUpdateTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const previousEmailRef = useRef<string | null>(null);
const orphanedPasswordToastShownRef = useRef(false);
// Verify session is still valid - simplified
const verifySession = async () => {
@@ -98,6 +99,7 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
setUser(null);
setAal(null);
setLoading(false);
orphanedPasswordToastShownRef.current = false;
return;
}
@@ -115,6 +117,16 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
// Check for orphaned password on SIGNED_IN events
if (event === 'SIGNED_IN' && session?.user) {
try {
// Import sessionFlags
const { isOrphanedPasswordDismissed, setOrphanedPasswordDismissed } =
await import('@/lib/sessionFlags');
// Skip if already shown in this auth cycle or dismissed this session
if (orphanedPasswordToastShownRef.current || isOrphanedPasswordDismissed()) {
authLog('[Auth] Skipping orphaned password toast - already shown or dismissed');
return;
}
// Import identityService functions
const { getUserIdentities, hasOrphanedPassword, triggerOrphanedPasswordConfirmation } =
await import('@/lib/identityService');
@@ -128,12 +140,15 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
const isOrphaned = await hasOrphanedPassword();
if (isOrphaned) {
// Mark as shown to prevent duplicates
orphanedPasswordToastShownRef.current = true;
// Show persistent toast with Resend button
const { toast: sonnerToast } = await import('sonner');
sonnerToast.warning("Password Activation Pending", {
description: "Your password needs email confirmation to be fully activated.",
duration: Infinity, // Persistent until dismissed
duration: Infinity,
action: {
label: "Resend Email",
onClick: async () => {
@@ -154,7 +169,10 @@ function AuthProviderComponent({ children }: { children: React.ReactNode }) {
},
cancel: {
label: "Dismiss",
onClick: () => {} // Allow dismissal
onClick: () => {
setOrphanedPasswordDismissed();
authLog('[Auth] User dismissed orphaned password warning');
}
}
});
}

View File

@@ -7,6 +7,7 @@ export const SessionFlags = {
MFA_INTENDED_PATH: 'mfa_intended_path',
MFA_CHALLENGE_ID: 'mfa_challenge_id',
AUTH_METHOD: 'auth_method',
ORPHANED_PASSWORD_DISMISSED: 'orphaned_password_dismissed',
} as const;
export type SessionFlagKey = typeof SessionFlags[keyof typeof SessionFlags];
@@ -73,6 +74,27 @@ export function clearAuthMethod(): void {
sessionStorage.removeItem(SessionFlags.AUTH_METHOD);
}
/**
* Set the orphaned password dismissed flag
*/
export function setOrphanedPasswordDismissed(): void {
sessionStorage.setItem(SessionFlags.ORPHANED_PASSWORD_DISMISSED, 'true');
}
/**
* Check if orphaned password warning has been dismissed this session
*/
export function isOrphanedPasswordDismissed(): boolean {
return sessionStorage.getItem(SessionFlags.ORPHANED_PASSWORD_DISMISSED) === 'true';
}
/**
* Clear the orphaned password dismissed flag
*/
export function clearOrphanedPasswordDismissed(): void {
sessionStorage.removeItem(SessionFlags.ORPHANED_PASSWORD_DISMISSED);
}
/**
* Clear all authentication-related session flags
*/